1import fs from 'fs'; 2import { vol } from 'memfs'; 3import path from 'path'; 4 5import * as Updates from '../Updates'; 6import { getPbxproj } from '../utils/Xcodeproj'; 7 8const fsReal = jest.requireActual('fs') as typeof fs; 9jest.mock('fs'); 10jest.mock('resolve-from'); 11 12const { silent } = require('resolve-from'); 13 14const fixturesPath = path.resolve(__dirname, 'fixtures'); 15const sampleCodeSigningCertificatePath = path.resolve(fixturesPath, 'codeSigningCertificate.pem'); 16 17describe('iOS Updates config', () => { 18 beforeEach(() => { 19 const resolveFrom = require('resolve-from'); 20 resolveFrom.silent = silent; 21 vol.reset(); 22 }); 23 24 it('sets the correct values in Expo.plist', () => { 25 vol.fromJSON({ 26 '/app/hello': fsReal.readFileSync(sampleCodeSigningCertificatePath, 'utf-8'), 27 }); 28 29 expect( 30 Updates.setUpdatesConfig( 31 '/app', 32 { 33 sdkVersion: '37.0.0', 34 slug: 'my-app', 35 owner: 'owner', 36 updates: { 37 enabled: false, 38 fallbackToCacheTimeout: 2000, 39 checkAutomatically: 'ON_ERROR_RECOVERY', 40 codeSigningCertificate: 'hello', 41 codeSigningMetadata: { 42 alg: 'rsa-v1_5-sha256', 43 keyid: 'test', 44 }, 45 }, 46 }, 47 {} as any, 48 'user', 49 '0.11.0' 50 ) 51 ).toMatchObject({ 52 EXUpdatesEnabled: false, 53 EXUpdatesURL: 'https://exp.host/@owner/my-app', 54 EXUpdatesCheckOnLaunch: 'ERROR_RECOVERY_ONLY', 55 EXUpdatesLaunchWaitMs: 2000, 56 EXUpdatesSDKVersion: '37.0.0', 57 EXUpdatesCodeSigningCertificate: fsReal.readFileSync( 58 sampleCodeSigningCertificatePath, 59 'utf-8' 60 ), 61 EXUpdatesCodeSigningMetadata: { alg: 'rsa-v1_5-sha256', keyid: 'test' }, 62 }); 63 }); 64 65 describe(Updates.ensureBundleReactNativePhaseContainsConfigurationScript, () => { 66 beforeEach(() => { 67 vol.reset(); 68 const resolveFrom = require('resolve-from'); 69 resolveFrom.silent = silent; 70 }); 71 72 it("adds create-manifest-ios.sh line to the 'Bundle React Native code and images' build phase ", () => { 73 vol.fromJSON( 74 { 75 'ios/testproject.xcodeproj/project.pbxproj': fsReal.readFileSync( 76 path.join(__dirname, 'fixtures/project-without-create-manifest-ios.pbxproj'), 77 'utf-8' 78 ), 79 'node_modules/expo-updates/scripts/create-manifest-ios.sh': 'whatever', 80 }, 81 '/app' 82 ); 83 84 const xcodeProject = getPbxproj('/app'); 85 Updates.ensureBundleReactNativePhaseContainsConfigurationScript('/app', xcodeProject); 86 const bundleReactNative = Updates.getBundleReactNativePhase(xcodeProject); 87 expect(bundleReactNative.shellScript).toMatchSnapshot(); 88 }); 89 90 it('fixes the path to create-manifest-ios.sh in case of a monorepo', () => { 91 // Pseudo node module resolution since actually mocking it could prove challenging. 92 // In a yarn workspace, resolve-from would be able to locate a module in any node_module folder if properly linked. 93 const resolveFrom = require('resolve-from'); 94 resolveFrom.silent = (p, a) => { 95 return silent(path.join(p, '..'), a); 96 }; 97 98 vol.fromJSON( 99 { 100 'workspace/ios/testproject.xcodeproj/project.pbxproj': fsReal.readFileSync( 101 path.join( 102 __dirname, 103 'fixtures/project-with-incorrect-create-manifest-ios-path.pbxproj' 104 ), 105 'utf-8' 106 ), 107 'node_modules/expo-updates/scripts/create-manifest-ios.sh': 'whatever', 108 }, 109 '/app' 110 ); 111 const xcodeProject = getPbxproj('/app/workspace'); 112 Updates.ensureBundleReactNativePhaseContainsConfigurationScript( 113 '/app/workspace', 114 xcodeProject 115 ); 116 const bundleReactNative = Updates.getBundleReactNativePhase(xcodeProject); 117 expect(bundleReactNative.shellScript).toMatchSnapshot(); 118 }); 119 }); 120}); 121