1import { ExpoConfig } from '@expo/config-types'; 2import * as fs from 'fs'; 3import { vol } from 'memfs'; 4 5import rnFixture from '../../plugins/__tests__/fixtures/react-native-project'; 6import * as WarningAggregator from '../../utils/warnings'; 7import { 8 formatDeviceFamilies, 9 getDeviceFamilies, 10 getIsTabletOnly, 11 getSupportsTablet, 12 setDeviceFamily, 13} from '../DeviceFamily'; 14import { getPbxproj } from '../utils/Xcodeproj'; 15 16jest.mock('fs'); 17jest.mock('../../utils/warnings'); 18 19const TABLET_AND_PHONE_SUPPORTED = [1, 2]; 20const ONLY_PHONE_SUPPORTED = [1]; 21const ONLY_TABLET_SUPPORTED = [2]; 22 23describe(getDeviceFamilies, () => { 24 it(`warns about invalid config`, () => { 25 getDeviceFamilies({ ios: { isTabletOnly: true, supportsTablet: false } } as any); 26 expect(WarningAggregator.addWarningIOS).toHaveBeenLastCalledWith( 27 'ios.supportsTablet', 28 'Found contradictory values: `{ ios: { isTabletOnly: true, supportsTablet: false } }`. Using `{ isTabletOnly: true }`.' 29 ); 30 }); 31}); 32 33describe('device family', () => { 34 it(`returns false ios.isTabletOnly is not provided`, () => { 35 expect(getIsTabletOnly({ ios: {} })).toBe(false); 36 }); 37 38 it(`returns true ios.isTabletOnly is provided`, () => { 39 expect(getIsTabletOnly({ ios: { isTabletOnly: true } })).toBe(true); 40 }); 41 42 it(`returns false ios.supportsTablet is provided`, () => { 43 expect(getSupportsTablet({ ios: {} })).toBe(false); 44 }); 45 46 it(`returns true ios.supportsTablet is provided`, () => { 47 expect(getSupportsTablet({ ios: { supportsTablet: true } })).toBe(true); 48 }); 49 50 it(`supports tablet and mobile if supportsTablet is true`, () => { 51 expect(getDeviceFamilies({ ios: { supportsTablet: true } })).toEqual( 52 TABLET_AND_PHONE_SUPPORTED 53 ); 54 }); 55 56 it(`supports only mobile if supportsTablet is blank/false and isTabletOnly is blank/false`, () => { 57 expect(getDeviceFamilies({ ios: {} })).toEqual(ONLY_PHONE_SUPPORTED); 58 expect(getDeviceFamilies({ ios: { supportsTablet: false, isTabletOnly: false } })).toEqual( 59 ONLY_PHONE_SUPPORTED 60 ); 61 }); 62 63 it(`supports only tablet if isTabletOnly is true`, () => { 64 expect(getDeviceFamilies({ ios: { isTabletOnly: true } })).toEqual(ONLY_TABLET_SUPPORTED); 65 }); 66 67 // It's important that this format is always correct. 68 // Otherwise the xcode parser will throw `Expected ".", "/*", ";", or [0-9] but "," found.` when we attempt to write to it. 69 it(`formats the families correctly`, () => { 70 expect(formatDeviceFamilies([1])).toEqual(`"1"`); 71 expect(formatDeviceFamilies([1, 2, 3])).toEqual(`"1,2,3"`); 72 }); 73 74 // TODO: update tests to run against pbxproj 75 // it(`sets to phone only if no value is provided`, () => { 76 // expect(setDeviceFamily({}, {})).toMatchObject({ UIDeviceFamily: ONLY_PHONE_SUPPORTED }); 77 // }); 78 79 // it(`sets to given config when provided`, () => { 80 // expect(setDeviceFamily({ ios: { supportsTablet: true } }, {})).toMatchObject({ 81 // UIDeviceFamily: TABLET_AND_PHONE_SUPPORTED, 82 // }); 83 // }); 84}); 85 86describe(setDeviceFamily, () => { 87 const projectRoot = '/tablet'; 88 beforeAll(async () => { 89 vol.fromJSON( 90 { 91 'ios/testproject.xcodeproj/project.pbxproj': 92 rnFixture['ios/HelloWorld.xcodeproj/project.pbxproj'], 93 'ios/testproject/AppDelegate.m': '', 94 }, 95 projectRoot 96 ); 97 }); 98 99 afterAll(() => { 100 vol.reset(); 101 }); 102 103 it('updates device families without throwing', async () => { 104 setDeviceFamilyForRoot({ name: '', slug: '', ios: {} }, projectRoot); 105 setDeviceFamilyForRoot({ name: '', slug: '', ios: { supportsTablet: true } }, projectRoot); 106 setDeviceFamilyForRoot({ name: '', slug: '', ios: { isTabletOnly: true } }, projectRoot); 107 }); 108}); 109 110function setDeviceFamilyForRoot(config: ExpoConfig, projectRoot: string) { 111 let project = getPbxproj(projectRoot); 112 project = setDeviceFamily(config, { project }); 113 fs.writeFileSync(project.filepath, project.writeSync()); 114} 115