1import { ExpoConfig } from '@expo/config-types'; 2import { vol } from 'memfs'; 3 4import { addWarningIOS } from '../../utils/warnings'; 5import { createInfoPlistPluginWithPropertyGuard } from '../ios-plugins'; 6import { evalModsAsync } from '../mod-compiler'; 7import { getIosModFileProviders, withIosBaseMods } from '../withIosBaseMods'; 8import rnFixture from './fixtures/react-native-project'; 9 10jest.mock('../../utils/warnings', () => ({ 11 addWarningIOS: jest.fn(), 12})); 13 14jest.mock('fs'); 15 16export const asMock = <T extends (...args: any[]) => any>(fn: T): jest.MockedFunction<T> => 17 fn as jest.MockedFunction<T>; 18describe(createInfoPlistPluginWithPropertyGuard, () => { 19 const projectRoot = '/app'; 20 21 beforeEach(async () => { 22 asMock(addWarningIOS).mockClear(); 23 vol.fromJSON( 24 { 25 ...rnFixture, 26 }, 27 projectRoot 28 ); 29 }); 30 31 afterEach(() => { 32 vol.reset(); 33 }); 34 35 it(`respects info plist manual values`, async () => { 36 const setter = jest.fn(); 37 const withPlugin = createInfoPlistPluginWithPropertyGuard(setter, { 38 infoPlistProperty: 'CFFakeValue', 39 // Supports nesting 40 expoConfigProperty: 'ios.appStoreUrl', 41 }); 42 43 let config: ExpoConfig = { 44 name: 'hey', 45 slug: '', 46 ios: { 47 appStoreUrl: 'underlying', 48 infoPlist: { 49 CFFakeValue: false, 50 }, 51 }, 52 }; 53 54 config = withPlugin(config); 55 56 config = withIosBaseMods(config, { 57 providers: { 58 infoPlist: getIosModFileProviders().infoPlist, 59 }, 60 }); 61 62 const results = await evalModsAsync(config, { 63 projectRoot, 64 platforms: ['ios'], 65 introspect: true, 66 assertMissingModProviders: true, 67 }); 68 69 expect(results.ios.infoPlist.CFFakeValue).toEqual(false); 70 71 expect(setter).not.toBeCalled(); 72 expect(addWarningIOS).toBeCalledWith( 73 'ios.appStoreUrl', 74 '"ios.infoPlist.CFFakeValue" is set in the config. Ignoring abstract property "ios.appStoreUrl": underlying' 75 ); 76 }); 77 78 it(`does not warn about info plist overrides if the abstract value is not defined`, async () => { 79 const setter = jest.fn(); 80 const withPlugin = createInfoPlistPluginWithPropertyGuard(setter, { 81 infoPlistProperty: 'CFFakeValue', 82 expoConfigProperty: 'foobar', 83 }); 84 85 let config: ExpoConfig = { 86 name: 'hey', 87 slug: '', 88 ios: { 89 infoPlist: { 90 CFFakeValue: false, 91 }, 92 }, 93 }; 94 95 config = withPlugin(config); 96 97 config = withIosBaseMods(config, { 98 providers: { 99 infoPlist: getIosModFileProviders().infoPlist, 100 }, 101 }); 102 103 const results = await evalModsAsync(config, { 104 projectRoot, 105 platforms: ['ios'], 106 introspect: true, 107 assertMissingModProviders: true, 108 }); 109 110 expect(results.ios.infoPlist.CFFakeValue).toEqual(false); 111 112 expect(setter).not.toBeCalled(); 113 expect(addWarningIOS).not.toBeCalled(); 114 }); 115 116 it(`uses default behavior when not overwritten`, async () => { 117 const setter = jest.fn(); 118 const withPlugin = createInfoPlistPluginWithPropertyGuard(setter, { 119 infoPlistProperty: 'CFFakeValue', 120 expoConfigProperty: 'name', 121 }); 122 123 let config: ExpoConfig = { 124 name: 'hey', 125 slug: '', 126 ios: { 127 infoPlist: {}, 128 }, 129 }; 130 131 config = withPlugin(config); 132 133 config = withIosBaseMods(config, { 134 providers: { 135 infoPlist: getIosModFileProviders().infoPlist, 136 }, 137 }); 138 139 await evalModsAsync(config, { 140 projectRoot, 141 platforms: ['ios'], 142 introspect: true, 143 assertMissingModProviders: true, 144 }); 145 146 expect(setter).toBeCalled(); 147 expect(addWarningIOS).not.toBeCalled(); 148 }); 149}); 150