1import * as fs from 'fs'; 2import { vol } from 'memfs'; 3import * as path from 'path'; 4 5import { XcodeProject } from '../../Plugin.types'; 6import * as WarningAggregator from '../../utils/warnings'; 7import { setBitcodeWithConfig } from '../Bitcode'; 8import { getPbxproj, isNotComment } from '../utils/Xcodeproj'; 9 10const fsReal = jest.requireActual('fs') as typeof fs; 11 12jest.mock('fs'); 13jest.mock('../../utils/warnings'); 14 15describe(setBitcodeWithConfig, () => { 16 const projectRoot = '/tablet'; 17 beforeEach(async () => { 18 vol.fromJSON( 19 { 20 'ios/testproject.xcodeproj/project.pbxproj': fsReal.readFileSync( 21 path.join(__dirname, 'fixtures/project.pbxproj'), 22 'utf-8' 23 ), 24 'ios/testproject/AppDelegate.m': '', 25 }, 26 projectRoot 27 ); 28 }); 29 30 afterEach(() => { 31 vol.reset(); 32 }); 33 34 it('defaults to not modifying the bitcode settings', async () => { 35 setBitcodeEnabledForRoot({ ios: {} }, projectRoot, validateDefaultBitcode); 36 }); 37 38 it('enables bitcode for everything', async () => { 39 setBitcodeEnabledForRoot({ ios: { bitcode: true } }, projectRoot, (project) => { 40 const configurations = getConfigurations(project); 41 for (const [, configuration] of configurations) { 42 expect(configuration.buildSettings.ENABLE_BITCODE).toBe('YES'); 43 } 44 }); 45 }); 46 47 it('disables bitcode for everything', async () => { 48 setBitcodeEnabledForRoot({ ios: { bitcode: false } }, projectRoot, (project) => { 49 const configurations = getConfigurations(project); 50 for (const [, configuration] of configurations) { 51 expect(configuration.buildSettings.ENABLE_BITCODE).toBe('NO'); 52 } 53 }); 54 }); 55 56 it('enables bitcode on specific configuration', async () => { 57 setBitcodeEnabledForRoot({ ios: { bitcode: 'Debug' } }, projectRoot, (project) => { 58 const configurations = getConfigurations(project); 59 for (const [, configuration] of configurations) { 60 // ensure all others are disabled 61 expect(configuration.buildSettings.ENABLE_BITCODE).toBe( 62 configuration.name === 'Debug' ? 'YES' : 'NO' 63 ); 64 } 65 }); 66 }); 67 68 it('warns when enabling bitcode on an invalid configuration', async () => { 69 setBitcodeEnabledForRoot({ ios: { bitcode: 'Bacon' } }, projectRoot, validateDefaultBitcode); 70 expect(WarningAggregator.addWarningIOS).toHaveBeenLastCalledWith( 71 'ios.bitcode', 72 'No configuration named "Bacon". Expected one of: "Debug", "Release".' 73 ); 74 }); 75}); 76 77function getConfigurations(project: XcodeProject) { 78 return Object.entries(project.pbxXCBuildConfigurationSection()).filter(isNotComment); 79} 80 81function setBitcodeEnabledForRoot( 82 config: { ios?: { bitcode?: boolean | string } & any }, 83 projectRoot: string, 84 validate: (project: XcodeProject) => void 85) { 86 let project = getPbxproj(projectRoot); 87 project = setBitcodeWithConfig(config, { project }); 88 validate(project); 89 fs.writeFileSync(project.filepath, project.writeSync()); 90} 91 92function validateDefaultBitcode(project: XcodeProject) { 93 const configurations = getConfigurations(project); 94 for (const [id, configuration] of configurations) { 95 expect(configuration.buildSettings.ENABLE_BITCODE).toBe( 96 // Ensure nothing changed. 97 { 98 '13B07F941A680F5B00A75B9A': 'NO', 99 '13B07F951A680F5B00A75B9A': undefined, 100 '83CBBA201A601CBA00E9B192': undefined, 101 '83CBBA211A601CBA00E9B192': undefined, 102 }[id] 103 ); 104 } 105} 106