1import type { ExpoConfig } from '@expo/config-types';
2import fs from 'fs';
3import { vol } from 'memfs';
4
5import rnFixture from '../../plugins/__tests__/fixtures/react-native-project';
6import { getName, setDisplayName, setName, setProductName } from '../Name';
7import { getPbxproj, isBuildConfig, isNotComment } from '../utils/Xcodeproj';
8
9jest.mock('fs');
10
11describe(getName, () => {
12  it(`returns null if no bundleIdentifier is provided`, () => {
13    expect(getName({} as any)).toBe(null);
14  });
15
16  it(`returns the name if provided`, () => {
17    expect(getName({ name: 'Some iOS app' })).toBe('Some iOS app');
18  });
19});
20describe(setDisplayName, () => {
21  it(`sets the CFBundleDisplayName if name is given`, () => {
22    expect(setDisplayName({ name: 'Expo app' }, {})).toMatchObject({
23      CFBundleDisplayName: 'Expo app',
24    });
25  });
26});
27describe(setName, () => {
28  it(`makes no changes to the infoPlist no name is provided`, () => {
29    expect(setName({} as any, {})).toMatchObject({});
30  });
31});
32describe(setProductName, () => {
33  const projectRoot = '/';
34  beforeAll(async () => {
35    vol.fromJSON(
36      {
37        'ios/testproject.xcodeproj/project.pbxproj':
38          rnFixture['ios/HelloWorld.xcodeproj/project.pbxproj'],
39        'ios/testproject/AppDelegate.m': '',
40      },
41      projectRoot
42    );
43  });
44
45  afterAll(() => {
46    vol.reset();
47  });
48
49  it(`sets the iOS PRODUCT_NAME value`, () => {
50    for (const [input, output] of [
51      ['My Cool Thing', `"MyCoolThing"`],
52      ['h"&<world/>��', `"hworld"`],
53    ]) {
54      // Ensure the value can be parsed and written.
55      const project = setProductNameForRoot({ name: input, slug: '' }, projectRoot);
56      expect(
57        Object.entries(project.pbxXCBuildConfigurationSection())
58          .filter(isNotComment)
59          // @ts-ignore
60          .filter(isBuildConfig)[0][1]?.buildSettings?.PRODUCT_NAME
61        // Ensure the value is wrapped in quotes.
62      ).toBe(output);
63    }
64  });
65});
66
67function setProductNameForRoot(config: ExpoConfig, projectRoot: string) {
68  let project = getPbxproj(projectRoot);
69  project = setProductName(config, project);
70  fs.writeFileSync(project.filepath, project.writeSync());
71  return project;
72}
73