1082815dcSEvan Baconimport { ExpoConfig } from '@expo/config-types';
2082815dcSEvan Baconimport * as fs from 'fs';
3082815dcSEvan Baconimport { vol } from 'memfs';
4082815dcSEvan Bacon
5*ed3bd27bSEvan Baconimport rnFixture from '../../plugins/__tests__/fixtures/react-native-project';
6082815dcSEvan Baconimport * as WarningAggregator from '../../utils/warnings';
7082815dcSEvan Baconimport {
8082815dcSEvan Bacon  formatDeviceFamilies,
9082815dcSEvan Bacon  getDeviceFamilies,
10082815dcSEvan Bacon  getIsTabletOnly,
11082815dcSEvan Bacon  getSupportsTablet,
12082815dcSEvan Bacon  setDeviceFamily,
13082815dcSEvan Bacon} from '../DeviceFamily';
14082815dcSEvan Baconimport { getPbxproj } from '../utils/Xcodeproj';
15082815dcSEvan Bacon
16082815dcSEvan Baconjest.mock('fs');
17082815dcSEvan Baconjest.mock('../../utils/warnings');
18082815dcSEvan Bacon
19082815dcSEvan Baconconst TABLET_AND_PHONE_SUPPORTED = [1, 2];
20082815dcSEvan Baconconst ONLY_PHONE_SUPPORTED = [1];
21082815dcSEvan Baconconst ONLY_TABLET_SUPPORTED = [2];
22082815dcSEvan Bacon
23082815dcSEvan Bacondescribe(getDeviceFamilies, () => {
24082815dcSEvan Bacon  it(`warns about invalid config`, () => {
25082815dcSEvan Bacon    getDeviceFamilies({ ios: { isTabletOnly: true, supportsTablet: false } } as any);
26082815dcSEvan Bacon    expect(WarningAggregator.addWarningIOS).toHaveBeenLastCalledWith(
27082815dcSEvan Bacon      'ios.supportsTablet',
28082815dcSEvan Bacon      'Found contradictory values: `{ ios: { isTabletOnly: true, supportsTablet: false } }`. Using `{ isTabletOnly: true }`.'
29082815dcSEvan Bacon    );
30082815dcSEvan Bacon  });
31082815dcSEvan Bacon});
32082815dcSEvan Bacon
33082815dcSEvan Bacondescribe('device family', () => {
34082815dcSEvan Bacon  it(`returns false ios.isTabletOnly is not provided`, () => {
35082815dcSEvan Bacon    expect(getIsTabletOnly({ ios: {} })).toBe(false);
36082815dcSEvan Bacon  });
37082815dcSEvan Bacon
38082815dcSEvan Bacon  it(`returns true ios.isTabletOnly is provided`, () => {
39082815dcSEvan Bacon    expect(getIsTabletOnly({ ios: { isTabletOnly: true } })).toBe(true);
40082815dcSEvan Bacon  });
41082815dcSEvan Bacon
42082815dcSEvan Bacon  it(`returns false ios.supportsTablet is provided`, () => {
43082815dcSEvan Bacon    expect(getSupportsTablet({ ios: {} })).toBe(false);
44082815dcSEvan Bacon  });
45082815dcSEvan Bacon
46082815dcSEvan Bacon  it(`returns true ios.supportsTablet is provided`, () => {
47082815dcSEvan Bacon    expect(getSupportsTablet({ ios: { supportsTablet: true } })).toBe(true);
48082815dcSEvan Bacon  });
49082815dcSEvan Bacon
50082815dcSEvan Bacon  it(`supports tablet and mobile if supportsTablet is true`, () => {
51082815dcSEvan Bacon    expect(getDeviceFamilies({ ios: { supportsTablet: true } })).toEqual(
52082815dcSEvan Bacon      TABLET_AND_PHONE_SUPPORTED
53082815dcSEvan Bacon    );
54082815dcSEvan Bacon  });
55082815dcSEvan Bacon
56082815dcSEvan Bacon  it(`supports only mobile if supportsTablet is blank/false and isTabletOnly is blank/false`, () => {
57082815dcSEvan Bacon    expect(getDeviceFamilies({ ios: {} })).toEqual(ONLY_PHONE_SUPPORTED);
58082815dcSEvan Bacon    expect(getDeviceFamilies({ ios: { supportsTablet: false, isTabletOnly: false } })).toEqual(
59082815dcSEvan Bacon      ONLY_PHONE_SUPPORTED
60082815dcSEvan Bacon    );
61082815dcSEvan Bacon  });
62082815dcSEvan Bacon
63082815dcSEvan Bacon  it(`supports only tablet if isTabletOnly is true`, () => {
64082815dcSEvan Bacon    expect(getDeviceFamilies({ ios: { isTabletOnly: true } })).toEqual(ONLY_TABLET_SUPPORTED);
65082815dcSEvan Bacon  });
66082815dcSEvan Bacon
67082815dcSEvan Bacon  // It's important that this format is always correct.
68082815dcSEvan Bacon  // Otherwise the xcode parser will throw `Expected ".", "/*", ";", or [0-9] but "," found.` when we attempt to write to it.
69082815dcSEvan Bacon  it(`formats the families correctly`, () => {
70082815dcSEvan Bacon    expect(formatDeviceFamilies([1])).toEqual(`"1"`);
71082815dcSEvan Bacon    expect(formatDeviceFamilies([1, 2, 3])).toEqual(`"1,2,3"`);
72082815dcSEvan Bacon  });
73082815dcSEvan Bacon
74082815dcSEvan Bacon  // TODO: update tests to run against pbxproj
75082815dcSEvan Bacon  // it(`sets to phone only if no value is provided`, () => {
76082815dcSEvan Bacon  //   expect(setDeviceFamily({}, {})).toMatchObject({ UIDeviceFamily: ONLY_PHONE_SUPPORTED });
77082815dcSEvan Bacon  // });
78082815dcSEvan Bacon
79082815dcSEvan Bacon  // it(`sets to given config when provided`, () => {
80082815dcSEvan Bacon  //   expect(setDeviceFamily({ ios: { supportsTablet: true } }, {})).toMatchObject({
81082815dcSEvan Bacon  //     UIDeviceFamily: TABLET_AND_PHONE_SUPPORTED,
82082815dcSEvan Bacon  //   });
83082815dcSEvan Bacon  // });
84082815dcSEvan Bacon});
85082815dcSEvan Bacon
86082815dcSEvan Bacondescribe(setDeviceFamily, () => {
87082815dcSEvan Bacon  const projectRoot = '/tablet';
88082815dcSEvan Bacon  beforeAll(async () => {
89082815dcSEvan Bacon    vol.fromJSON(
90082815dcSEvan Bacon      {
91*ed3bd27bSEvan Bacon        'ios/testproject.xcodeproj/project.pbxproj':
92*ed3bd27bSEvan Bacon          rnFixture['ios/HelloWorld.xcodeproj/project.pbxproj'],
93082815dcSEvan Bacon        'ios/testproject/AppDelegate.m': '',
94082815dcSEvan Bacon      },
95082815dcSEvan Bacon      projectRoot
96082815dcSEvan Bacon    );
97082815dcSEvan Bacon  });
98082815dcSEvan Bacon
99082815dcSEvan Bacon  afterAll(() => {
100082815dcSEvan Bacon    vol.reset();
101082815dcSEvan Bacon  });
102082815dcSEvan Bacon
103082815dcSEvan Bacon  it('updates device families without throwing', async () => {
104082815dcSEvan Bacon    setDeviceFamilyForRoot({ name: '', slug: '', ios: {} }, projectRoot);
105082815dcSEvan Bacon    setDeviceFamilyForRoot({ name: '', slug: '', ios: { supportsTablet: true } }, projectRoot);
106082815dcSEvan Bacon    setDeviceFamilyForRoot({ name: '', slug: '', ios: { isTabletOnly: true } }, projectRoot);
107082815dcSEvan Bacon  });
108082815dcSEvan Bacon});
109082815dcSEvan Bacon
110082815dcSEvan Baconfunction setDeviceFamilyForRoot(config: ExpoConfig, projectRoot: string) {
111082815dcSEvan Bacon  let project = getPbxproj(projectRoot);
112082815dcSEvan Bacon  project = setDeviceFamily(config, { project });
113082815dcSEvan Bacon  fs.writeFileSync(project.filepath, project.writeSync());
114082815dcSEvan Bacon}
115