import { ExpoConfig } from '@expo/config-types'; import { fs as memfs, vol } from 'memfs'; import path from 'path'; import rnFixture from '../../plugins/__tests__/fixtures/react-native-project'; import { getBundleIdentifier, getBundleIdentifierFromPbxproj, setBundleIdentifier, setBundleIdentifierForPbxproj, } from '../BundleIdentifier'; const baseExpoConfig: ExpoConfig = { name: 'testproject', slug: 'testproject', platforms: ['ios'], version: '1.0.0', }; jest.mock('fs'); const originalFs = jest.requireActual('fs'); describe('BundleIdentifier module', () => { describe(getBundleIdentifier, () => { it('returns null if no bundleIdentifier is provided', () => { expect(getBundleIdentifier(baseExpoConfig)).toBe(null); }); it('returns the bundleIdentifier if provided', () => { expect( getBundleIdentifier({ ...baseExpoConfig, ios: { bundleIdentifier: 'com.example.xyz' } }) ).toBe('com.example.xyz'); }); }); describe(getBundleIdentifierFromPbxproj, () => { const projectRoot = '/testproject'; afterEach(() => vol.reset()); it('returns null if no project.pbxproj exists', () => { vol.mkdirpSync(projectRoot); const bundleId = getBundleIdentifierFromPbxproj(projectRoot, { targetName: 'testproject' }); expect(bundleId).toBeNull(); }); it('returns the bundle identifier defined in project.pbxproj', () => { vol.fromJSON( { 'ios/HelloWorld.xcodeproj/project.pbxproj': rnFixture['ios/HelloWorld.xcodeproj/project.pbxproj'], }, projectRoot ); const bundleId = getBundleIdentifierFromPbxproj(projectRoot, { targetName: 'HelloWorld' }); expect(bundleId).toBe('org.name.HelloWorld'); }); describe('multi-target project', () => { it('returns correct bundle identifier for the default build configuration (Release)', () => { vol.fromJSON( { 'ios/testproject.xcodeproj/project.pbxproj': originalFs.readFileSync( path.join(__dirname, 'fixtures/project-multitarget.pbxproj'), 'utf-8' ), 'ios/testproject.xcodeproj/xcshareddata/xcschemes/multitarget.xcscheme': originalFs.readFileSync( path.join(__dirname, 'fixtures/multitarget.xcscheme'), 'utf-8' ), }, projectRoot ); const bundleId = getBundleIdentifierFromPbxproj(projectRoot, { targetName: 'multitarget', }); expect(bundleId).toBe('com.swmansion.dominik.multitarget'); }); it('returns correct bundle identifier for Debug build configuration', () => { vol.fromJSON( { 'ios/testproject.xcodeproj/project.pbxproj': originalFs.readFileSync( path.join(__dirname, 'fixtures/project-multitarget.pbxproj'), 'utf-8' ), 'ios/testproject.xcodeproj/xcshareddata/xcschemes/multitarget.xcscheme': originalFs.readFileSync( path.join(__dirname, 'fixtures/multitarget.xcscheme'), 'utf-8' ), }, projectRoot ); const bundleId = getBundleIdentifierFromPbxproj(projectRoot, { targetName: 'multitarget', buildConfiguration: 'Debug', }); expect(bundleId).toBe('com.swmansion.dominik.multitarget.debug'); }); }); }); describe(setBundleIdentifier, () => { it('sets the CFBundleShortVersionString if bundleIdentifier is given', () => { expect( setBundleIdentifier( { ...baseExpoConfig, ios: { bundleIdentifier: 'host.exp.exponent' } }, {} ) ).toMatchObject({ CFBundleIdentifier: 'host.exp.exponent', }); }); it('makes no changes to the infoPlist no bundleIdentifier is provided', () => { expect(setBundleIdentifier(baseExpoConfig, {})).toMatchObject({}); }); }); describe(setBundleIdentifierForPbxproj, () => { const projectRoot = '/testproject'; const pbxProjPath = 'ios/testproject.xcodeproj/project.pbxproj'; const otherPbxProjPath = 'ios/otherproject.xcodeproj/project.pbxproj'; beforeEach(() => { vol.fromJSON( { [pbxProjPath]: rnFixture['ios/HelloWorld.xcodeproj/project.pbxproj'], [otherPbxProjPath]: rnFixture['ios/HelloWorld.xcodeproj/project.pbxproj'], }, projectRoot ); }); afterEach(() => vol.reset()); it('sets the bundle identifier in the pbxproj file', () => { setBundleIdentifierForPbxproj(projectRoot, 'com.swmansion.dominik.abcd.v2'); const pbxprojContents = memfs.readFileSync(path.join(projectRoot, pbxProjPath), 'utf-8'); const otherPbxprojContents = memfs.readFileSync( path.join(projectRoot, otherPbxProjPath), 'utf-8' ); expect(pbxprojContents).toMatchSnapshot(); // Ensure all paths are modified expect(pbxprojContents).toBe(otherPbxprojContents); }); }); });