1import { ExpoConfig } from '@expo/config-types'; 2import { fs as memfs, vol } from 'memfs'; 3import path from 'path'; 4 5import { 6 getBundleIdentifier, 7 getBundleIdentifierFromPbxproj, 8 setBundleIdentifier, 9 setBundleIdentifierForPbxproj, 10} from '../BundleIdentifier'; 11 12const baseExpoConfig: ExpoConfig = { 13 name: 'testproject', 14 slug: 'testproject', 15 platforms: ['ios'], 16 version: '1.0.0', 17}; 18 19jest.mock('fs'); 20 21const originalFs = jest.requireActual('fs'); 22 23describe('BundleIdentifier module', () => { 24 describe(getBundleIdentifier, () => { 25 it('returns null if no bundleIdentifier is provided', () => { 26 expect(getBundleIdentifier(baseExpoConfig)).toBe(null); 27 }); 28 29 it('returns the bundleIdentifier if provided', () => { 30 expect( 31 getBundleIdentifier({ ...baseExpoConfig, ios: { bundleIdentifier: 'com.example.xyz' } }) 32 ).toBe('com.example.xyz'); 33 }); 34 }); 35 36 describe(getBundleIdentifierFromPbxproj, () => { 37 const projectRoot = '/testproject'; 38 39 afterEach(() => vol.reset()); 40 41 it('returns null if no project.pbxproj exists', () => { 42 vol.mkdirpSync(projectRoot); 43 const bundleId = getBundleIdentifierFromPbxproj(projectRoot, { targetName: 'testproject' }); 44 expect(bundleId).toBeNull(); 45 }); 46 47 it('returns the bundle identifier defined in project.pbxproj', () => { 48 vol.fromJSON( 49 { 50 'ios/testproject.xcodeproj/project.pbxproj': originalFs.readFileSync( 51 path.join(__dirname, 'fixtures/project.pbxproj'), 52 'utf-8' 53 ), 54 }, 55 projectRoot 56 ); 57 const bundleId = getBundleIdentifierFromPbxproj(projectRoot, { targetName: 'testproject' }); 58 expect(bundleId).toBe('org.name.testproject'); 59 }); 60 61 describe('multi-target project', () => { 62 it('returns correct bundle identifier for the default build configuration (Release)', () => { 63 vol.fromJSON( 64 { 65 'ios/testproject.xcodeproj/project.pbxproj': originalFs.readFileSync( 66 path.join(__dirname, 'fixtures/project-multitarget.pbxproj'), 67 'utf-8' 68 ), 69 'ios/testproject.xcodeproj/xcshareddata/xcschemes/multitarget.xcscheme': 70 originalFs.readFileSync( 71 path.join(__dirname, 'fixtures/multitarget.xcscheme'), 72 'utf-8' 73 ), 74 }, 75 projectRoot 76 ); 77 const bundleId = getBundleIdentifierFromPbxproj(projectRoot, { 78 targetName: 'multitarget', 79 }); 80 expect(bundleId).toBe('com.swmansion.dominik.multitarget'); 81 }); 82 83 it('returns correct bundle identifier for Debug build configuration', () => { 84 vol.fromJSON( 85 { 86 'ios/testproject.xcodeproj/project.pbxproj': originalFs.readFileSync( 87 path.join(__dirname, 'fixtures/project-multitarget.pbxproj'), 88 'utf-8' 89 ), 90 'ios/testproject.xcodeproj/xcshareddata/xcschemes/multitarget.xcscheme': 91 originalFs.readFileSync( 92 path.join(__dirname, 'fixtures/multitarget.xcscheme'), 93 'utf-8' 94 ), 95 }, 96 projectRoot 97 ); 98 const bundleId = getBundleIdentifierFromPbxproj(projectRoot, { 99 targetName: 'multitarget', 100 buildConfiguration: 'Debug', 101 }); 102 expect(bundleId).toBe('com.swmansion.dominik.multitarget.debug'); 103 }); 104 }); 105 }); 106 107 describe(setBundleIdentifier, () => { 108 it('sets the CFBundleShortVersionString if bundleIdentifier is given', () => { 109 expect( 110 setBundleIdentifier( 111 { ...baseExpoConfig, ios: { bundleIdentifier: 'host.exp.exponent' } }, 112 {} 113 ) 114 ).toMatchObject({ 115 CFBundleIdentifier: 'host.exp.exponent', 116 }); 117 }); 118 119 it('makes no changes to the infoPlist no bundleIdentifier is provided', () => { 120 expect(setBundleIdentifier(baseExpoConfig, {})).toMatchObject({}); 121 }); 122 }); 123 124 describe(setBundleIdentifierForPbxproj, () => { 125 const projectRoot = '/testproject'; 126 const pbxProjPath = 'ios/testproject.xcodeproj/project.pbxproj'; 127 const otherPbxProjPath = 'ios/otherproject.xcodeproj/project.pbxproj'; 128 129 beforeEach(() => { 130 vol.fromJSON( 131 { 132 [pbxProjPath]: originalFs.readFileSync( 133 path.join(__dirname, 'fixtures/project.pbxproj'), 134 'utf-8' 135 ), 136 [otherPbxProjPath]: originalFs.readFileSync( 137 path.join(__dirname, 'fixtures/project.pbxproj'), 138 'utf-8' 139 ), 140 }, 141 projectRoot 142 ); 143 }); 144 afterEach(() => vol.reset()); 145 146 it('sets the bundle identifier in the pbxproj file', () => { 147 setBundleIdentifierForPbxproj(projectRoot, 'com.swmansion.dominik.abcd.v2'); 148 const pbxprojContents = memfs.readFileSync(path.join(projectRoot, pbxProjPath), 'utf-8'); 149 const otherPbxprojContents = memfs.readFileSync( 150 path.join(projectRoot, otherPbxProjPath), 151 'utf-8' 152 ); 153 expect(pbxprojContents).toMatchSnapshot(); 154 // Ensure all paths are modified 155 expect(pbxprojContents).toBe(otherPbxprojContents); 156 }); 157 }); 158}); 159