1082815dcSEvan Baconimport fs from 'fs'; 2082815dcSEvan Baconimport { vol } from 'memfs'; 3082815dcSEvan Baconimport path from 'path'; 4082815dcSEvan Bacon 5082815dcSEvan Baconimport { 6082815dcSEvan Bacon getNativeVersion, 7*f0d67e12SMateus Craveiro getRuntimeVersionAsync, 8082815dcSEvan Bacon getSDKVersion, 9082815dcSEvan Bacon getUpdatesCheckOnLaunch, 10082815dcSEvan Bacon getUpdatesCodeSigningCertificate, 11082815dcSEvan Bacon getUpdatesCodeSigningMetadata, 12082815dcSEvan Bacon getUpdatesCodeSigningMetadataStringified, 1309bd1012SUmberto Ghio getUpdatesRequestHeaders, 1409bd1012SUmberto Ghio getUpdatesRequestHeadersStringified, 15082815dcSEvan Bacon getUpdatesEnabled, 16082815dcSEvan Bacon getUpdatesTimeout, 17082815dcSEvan Bacon getUpdateUrl, 18082815dcSEvan Bacon} from '../Updates'; 19082815dcSEvan Bacon 20082815dcSEvan Baconconst fsReal = jest.requireActual('fs') as typeof fs; 21082815dcSEvan Baconjest.mock('fs'); 22082815dcSEvan Baconjest.mock('resolve-from'); 23082815dcSEvan Bacon 24082815dcSEvan Baconconst { silent } = require('resolve-from'); 25082815dcSEvan Bacon 26082815dcSEvan Baconconst fixturesPath = path.resolve(__dirname, 'fixtures'); 27082815dcSEvan Baconconst sampleCodeSigningCertificatePath = path.resolve(fixturesPath, 'codeSigningCertificate.pem'); 28082815dcSEvan Bacon 29082815dcSEvan Baconconsole.warn = jest.fn(); 30082815dcSEvan Bacon 31082815dcSEvan Bacondescribe('shared config getters', () => { 32082815dcSEvan Bacon beforeEach(() => { 33082815dcSEvan Bacon const resolveFrom = require('resolve-from'); 34082815dcSEvan Bacon resolveFrom.silent = silent; 35082815dcSEvan Bacon vol.reset(); 36082815dcSEvan Bacon }); 37082815dcSEvan Bacon 38082815dcSEvan Bacon it(`returns correct default values from all getters if no value provided`, () => { 39082815dcSEvan Bacon expect(getSDKVersion({})).toBe(null); 40082815dcSEvan Bacon expect(getUpdatesCheckOnLaunch({})).toBe('ALWAYS'); 41082815dcSEvan Bacon expect(getUpdatesTimeout({})).toBe(0); 42082815dcSEvan Bacon expect(getUpdatesCodeSigningCertificate('/app', {})).toBe(undefined); 43082815dcSEvan Bacon expect(getUpdatesCodeSigningMetadata({})).toBe(undefined); 4409bd1012SUmberto Ghio expect(getUpdatesRequestHeaders({})).toBe(undefined); 452fae8288SWill Schurman 4682ade864SWill Schurman expect(getUpdatesEnabled({})).toBe(false); 4782ade864SWill Schurman expect(getUpdatesEnabled({ updates: {} })).toBe(false); 48082815dcSEvan Bacon }); 49082815dcSEvan Bacon 50082815dcSEvan Bacon it(`returns correct value from all getters if value provided`, () => { 51082815dcSEvan Bacon vol.fromJSON({ 52082815dcSEvan Bacon '/app/hello': fsReal.readFileSync(sampleCodeSigningCertificatePath, 'utf-8'), 53082815dcSEvan Bacon }); 54082815dcSEvan Bacon 55082815dcSEvan Bacon expect(getSDKVersion({ sdkVersion: '37.0.0' })).toBe('37.0.0'); 56082815dcSEvan Bacon expect(getUpdatesCheckOnLaunch({ updates: { checkAutomatically: 'ON_ERROR_RECOVERY' } })).toBe( 57082815dcSEvan Bacon 'NEVER' 58082815dcSEvan Bacon ); 59082815dcSEvan Bacon expect( 60082815dcSEvan Bacon getUpdatesCheckOnLaunch({ updates: { checkAutomatically: 'ON_ERROR_RECOVERY' } }, '0.11.0') 61082815dcSEvan Bacon ).toBe('ERROR_RECOVERY_ONLY'); 62082815dcSEvan Bacon expect( 63082815dcSEvan Bacon getUpdatesCheckOnLaunch({ updates: { checkAutomatically: 'ON_ERROR_RECOVERY' } }, '0.10.15') 64082815dcSEvan Bacon ).toBe('NEVER'); 65082815dcSEvan Bacon expect(getUpdatesCheckOnLaunch({ updates: { checkAutomatically: 'ON_LOAD' } })).toBe('ALWAYS'); 66b8b0e64dSDouglas Lowder expect(getUpdatesCheckOnLaunch({ updates: { checkAutomatically: 'WIFI_ONLY' } })).toBe( 67b8b0e64dSDouglas Lowder 'WIFI_ONLY' 68b8b0e64dSDouglas Lowder ); 69b8b0e64dSDouglas Lowder expect(getUpdatesCheckOnLaunch({ updates: { checkAutomatically: 'NEVER' } })).toBe('NEVER'); 70b8b0e64dSDouglas Lowder expect(getUpdatesCheckOnLaunch({ updates: {} })).toBe('ALWAYS'); 7182ade864SWill Schurman expect(getUpdatesEnabled({ updates: { enabled: false } })).toBe(false); 72082815dcSEvan Bacon expect(getUpdatesTimeout({ updates: { fallbackToCacheTimeout: 2000 } })).toBe(2000); 73082815dcSEvan Bacon expect( 74082815dcSEvan Bacon getUpdatesCodeSigningCertificate('/app', { 75082815dcSEvan Bacon updates: { 76082815dcSEvan Bacon codeSigningCertificate: 'hello', 77082815dcSEvan Bacon }, 78082815dcSEvan Bacon }) 79082815dcSEvan Bacon ).toBe(fsReal.readFileSync(sampleCodeSigningCertificatePath, 'utf-8')); 80082815dcSEvan Bacon expect( 81082815dcSEvan Bacon getUpdatesCodeSigningMetadataStringified({ 82082815dcSEvan Bacon updates: { 83082815dcSEvan Bacon codeSigningMetadata: { 84082815dcSEvan Bacon alg: 'rsa-v1_5-sha256', 85082815dcSEvan Bacon keyid: 'test', 86082815dcSEvan Bacon }, 87082815dcSEvan Bacon }, 88082815dcSEvan Bacon }) 89082815dcSEvan Bacon ).toBe( 90082815dcSEvan Bacon JSON.stringify({ 91082815dcSEvan Bacon alg: 'rsa-v1_5-sha256', 92082815dcSEvan Bacon keyid: 'test', 93082815dcSEvan Bacon }) 94082815dcSEvan Bacon ); 95082815dcSEvan Bacon expect( 96082815dcSEvan Bacon getUpdatesCodeSigningMetadata({ 97082815dcSEvan Bacon updates: { 98082815dcSEvan Bacon codeSigningMetadata: { 99082815dcSEvan Bacon alg: 'rsa-v1_5-sha256', 100082815dcSEvan Bacon keyid: 'test', 101082815dcSEvan Bacon }, 102082815dcSEvan Bacon }, 103082815dcSEvan Bacon }) 104082815dcSEvan Bacon ).toMatchObject({ 105082815dcSEvan Bacon alg: 'rsa-v1_5-sha256', 106082815dcSEvan Bacon keyid: 'test', 107082815dcSEvan Bacon }); 10809bd1012SUmberto Ghio expect( 10909bd1012SUmberto Ghio getUpdatesRequestHeadersStringified({ 11009bd1012SUmberto Ghio updates: { 11109bd1012SUmberto Ghio requestHeaders: { 11209bd1012SUmberto Ghio 'expo-channel-name': 'test', 11309bd1012SUmberto Ghio testheader: 'test', 11409bd1012SUmberto Ghio }, 11509bd1012SUmberto Ghio }, 11609bd1012SUmberto Ghio }) 11709bd1012SUmberto Ghio ).toBe( 11809bd1012SUmberto Ghio JSON.stringify({ 11909bd1012SUmberto Ghio 'expo-channel-name': 'test', 12009bd1012SUmberto Ghio testheader: 'test', 12109bd1012SUmberto Ghio }) 12209bd1012SUmberto Ghio ); 12309bd1012SUmberto Ghio expect( 12409bd1012SUmberto Ghio getUpdatesRequestHeaders({ 12509bd1012SUmberto Ghio updates: { 12609bd1012SUmberto Ghio requestHeaders: { 12709bd1012SUmberto Ghio 'expo-channel-name': 'test', 12809bd1012SUmberto Ghio testheader: 'test', 12909bd1012SUmberto Ghio }, 13009bd1012SUmberto Ghio }, 13109bd1012SUmberto Ghio }) 13209bd1012SUmberto Ghio ).toMatchObject({ 13309bd1012SUmberto Ghio 'expo-channel-name': 'test', 13409bd1012SUmberto Ghio testheader: 'test', 13509bd1012SUmberto Ghio }); 136082815dcSEvan Bacon }); 137082815dcSEvan Bacon}); 138082815dcSEvan Bacon 139082815dcSEvan Bacondescribe(getUpdateUrl, () => { 140082815dcSEvan Bacon it(`returns correct default values from all getters if no value provided.`, () => { 141082815dcSEvan Bacon const url = 'https://u.expo.dev/00000000-0000-0000-0000-000000000000'; 14282ade864SWill Schurman expect(getUpdateUrl({ updates: { url } })).toBe(url); 1432fae8288SWill Schurman }); 1442fae8288SWill Schurman 1452fae8288SWill Schurman it(`returns correct legacy urls if 'updates.url' is not provided, but 'slug' and ('username'|'owner') are provided and useClassicUpdates is false.`, () => { 14682ade864SWill Schurman expect(getUpdateUrl({})).toBe(null); 147082815dcSEvan Bacon }); 148082815dcSEvan Bacon}); 149082815dcSEvan Bacon 150082815dcSEvan Bacondescribe(getNativeVersion, () => { 151082815dcSEvan Bacon const version = '2.0.0'; 152082815dcSEvan Bacon const versionCode = 42; 153082815dcSEvan Bacon const buildNumber = '13'; 154082815dcSEvan Bacon it('works for android', () => { 155082815dcSEvan Bacon expect(getNativeVersion({ version, android: { versionCode } }, 'android')).toBe( 156082815dcSEvan Bacon `${version}(${versionCode})` 157082815dcSEvan Bacon ); 158082815dcSEvan Bacon }); 159082815dcSEvan Bacon it('works for ios', () => { 160082815dcSEvan Bacon expect(getNativeVersion({ version, ios: { buildNumber } }, 'ios')).toBe( 161082815dcSEvan Bacon `${version}(${buildNumber})` 162082815dcSEvan Bacon ); 163082815dcSEvan Bacon }); 164082815dcSEvan Bacon it('throws an error if platform is not recognized', () => { 165082815dcSEvan Bacon const fakePlatform = 'doesnotexist'; 166082815dcSEvan Bacon expect(() => { 167082815dcSEvan Bacon getNativeVersion({ version }, fakePlatform as any); 168082815dcSEvan Bacon }).toThrow(`"${fakePlatform}" is not a supported platform. Choose either "ios" or "android".`); 169082815dcSEvan Bacon }); 170082815dcSEvan Bacon it('uses the default version if the version is missing', () => { 171082815dcSEvan Bacon expect(getNativeVersion({}, 'ios')).toBe('1.0.0(1)'); 172082815dcSEvan Bacon }); 173082815dcSEvan Bacon it('uses the default buildNumber if the platform is ios and the buildNumber is missing', () => { 174082815dcSEvan Bacon expect(getNativeVersion({ version }, 'ios')).toBe(`${version}(1)`); 175082815dcSEvan Bacon }); 176082815dcSEvan Bacon it('uses the default versionCode if the platform is android and the versionCode is missing', () => { 177082815dcSEvan Bacon expect(getNativeVersion({ version }, 'android')).toBe(`${version}(1)`); 178082815dcSEvan Bacon }); 179082815dcSEvan Bacon}); 180082815dcSEvan Bacon 181*f0d67e12SMateus Craveirodescribe(getRuntimeVersionAsync, () => { 182*f0d67e12SMateus Craveiro it('works if the top level runtimeVersion is a string', async () => { 183082815dcSEvan Bacon const runtimeVersion = '42'; 184*f0d67e12SMateus Craveiro expect(await getRuntimeVersionAsync('', { runtimeVersion }, 'ios')).toBe(runtimeVersion); 185082815dcSEvan Bacon }); 186*f0d67e12SMateus Craveiro it('works if the platform specific runtimeVersion is a string', async () => { 187082815dcSEvan Bacon const runtimeVersion = '42'; 188*f0d67e12SMateus Craveiro expect(await getRuntimeVersionAsync('', { ios: { runtimeVersion } }, 'ios')).toBe( 189*f0d67e12SMateus Craveiro runtimeVersion 190*f0d67e12SMateus Craveiro ); 191082815dcSEvan Bacon }); 192*f0d67e12SMateus Craveiro it('works if the runtimeVersion is a nativeVersion policy', async () => { 193082815dcSEvan Bacon const version = '1'; 194082815dcSEvan Bacon const buildNumber = '2'; 195082815dcSEvan Bacon expect( 196*f0d67e12SMateus Craveiro await getRuntimeVersionAsync( 197*f0d67e12SMateus Craveiro '', 198082815dcSEvan Bacon { version, runtimeVersion: { policy: 'nativeVersion' }, ios: { buildNumber } }, 199082815dcSEvan Bacon 'ios' 200082815dcSEvan Bacon ) 201082815dcSEvan Bacon ).toBe(`${version}(${buildNumber})`); 202082815dcSEvan Bacon }); 203*f0d67e12SMateus Craveiro it('works if the runtimeVersion is an appVersion policy', async () => { 204053187fcSWojciech Kozyra const version = '1'; 205053187fcSWojciech Kozyra const buildNumber = '2'; 206053187fcSWojciech Kozyra expect( 207*f0d67e12SMateus Craveiro await getRuntimeVersionAsync( 208*f0d67e12SMateus Craveiro '', 209053187fcSWojciech Kozyra { version, runtimeVersion: { policy: 'appVersion' }, ios: { buildNumber } }, 210053187fcSWojciech Kozyra 'ios' 211053187fcSWojciech Kozyra ) 212053187fcSWojciech Kozyra ).toBe(version); 213053187fcSWojciech Kozyra }); 214*f0d67e12SMateus Craveiro it('returns null if no runtime version is supplied', async () => { 215*f0d67e12SMateus Craveiro expect(await getRuntimeVersionAsync('', {}, 'ios')).toEqual(null); 216082815dcSEvan Bacon }); 217*f0d67e12SMateus Craveiro it('throws if runtime version is not parseable', async () => { 218*f0d67e12SMateus Craveiro await expect(getRuntimeVersionAsync('', { runtimeVersion: 1 } as any, 'ios')).rejects.toThrow( 219*f0d67e12SMateus Craveiro `"1" is not a valid runtime version. getRuntimeVersionAsync only supports a string, "sdkVersion", "appVersion", "nativeVersion" or "fingerprintExperimental" policy.` 220082815dcSEvan Bacon ); 221*f0d67e12SMateus Craveiro await expect( 222*f0d67e12SMateus Craveiro getRuntimeVersionAsync('', { runtimeVersion: { policy: 'unsupportedPlugin' } } as any, 'ios') 223*f0d67e12SMateus Craveiro ).rejects.toThrow( 224*f0d67e12SMateus Craveiro `"{"policy":"unsupportedPlugin"}" is not a valid runtime version. getRuntimeVersionAsync only supports a string, "sdkVersion", "appVersion", "nativeVersion" or "fingerprintExperimental" policy.` 225082815dcSEvan Bacon ); 226082815dcSEvan Bacon }); 227082815dcSEvan Bacon}); 228