diff --git a/packages/config-plugins/src/ios/Target.ts b/packages/config-plugins/src/ios/Target.ts index d02df3a3bc..a8b1b4c794 100644 --- a/packages/config-plugins/src/ios/Target.ts +++ b/packages/config-plugins/src/ios/Target.ts @@ -7,18 +7,21 @@ interface SchemeXML { Scheme?: { BuildAction?: { BuildActionEntries?: { - BuildActionEntry?: { - BuildableReference?: { - $?: { - BlueprintName?: string; - }; - }[]; - }[]; + BuildActionEntry?: BuildActionEntryType[]; }[]; }[]; }; } +interface BuildActionEntryType { + BuildableReference?: { + $?: { + BlueprintName?: string; + BuildableName?: string; + }; + }[]; +} + export async function getApplicationTargetForSchemeAsync( projectRoot: string, scheme: string @@ -31,12 +34,23 @@ export async function getApplicationTargetForSchemeAsync( } const schemeXML = ((await readXMLAsync({ path: schemePath })) as unknown) as SchemeXML; + const buildActionEntry = + schemeXML.Scheme?.BuildAction?.[0]?.BuildActionEntries?.[0]?.BuildActionEntry; const targetName = - schemeXML.Scheme?.BuildAction?.[0]?.BuildActionEntries?.[0]?.BuildActionEntry?.[0] - ?.BuildableReference?.[0]?.['$']?.BlueprintName; + buildActionEntry?.length === 1 + ? getBlueprintName(buildActionEntry[0]) + : getBlueprintName( + buildActionEntry?.find(entry => { + return entry.BuildableReference?.[0]?.['$']?.BuildableName?.endsWith('.app'); + }) + ); if (!targetName) { const schemeRelativePath = path.relative(projectRoot, schemePath); throw new Error(`${schemeRelativePath} seems to be corrupted`); } return targetName; } + +function getBlueprintName(entry?: BuildActionEntryType): string | undefined { + return entry?.BuildableReference?.[0]?.['$']?.BlueprintName; +} diff --git a/packages/config-plugins/src/ios/__tests__/Target-test.ts b/packages/config-plugins/src/ios/__tests__/Target-test.ts index a68a843d37..6181b812d8 100644 --- a/packages/config-plugins/src/ios/__tests__/Target-test.ts +++ b/packages/config-plugins/src/ios/__tests__/Target-test.ts @@ -9,30 +9,60 @@ const fsReal = jest.requireActual('fs') as typeof fs; jest.mock('fs'); describe(getApplicationTargetForSchemeAsync, () => { - beforeAll(async () => { - vol.fromJSON( - { - 'ios/testproject.xcodeproj/xcshareddata/xcschemes/testproject.xcscheme': fsReal.readFileSync( - path.join(__dirname, 'fixtures/testproject.xcscheme'), - 'utf-8' - ), - }, - '/app' - ); - }); + describe('single build action entry', () => { + beforeAll(async () => { + vol.fromJSON( + { + 'ios/testproject.xcodeproj/xcshareddata/xcschemes/testproject.xcscheme': fsReal.readFileSync( + path.join(__dirname, 'fixtures/testproject.xcscheme'), + 'utf-8' + ), + }, + '/app' + ); + }); - afterAll(() => { - vol.reset(); - }); + afterAll(() => { + vol.reset(); + }); + + it('returns the target name for existing scheme', async () => { + const target = await getApplicationTargetForSchemeAsync('/app', 'testproject'); + expect(target).toBe('testproject'); + }); - it('returns the target name for existing scheme', async () => { - const target = await getApplicationTargetForSchemeAsync('/app', 'testproject'); - expect(target).toBe('testproject'); + it('throws if the scheme does not exist', async () => { + await expect(() => + getApplicationTargetForSchemeAsync('/app', 'nonexistentscheme') + ).rejects.toThrow(/does not exist/); + }); }); + describe('multiple build action entries', () => { + beforeAll(async () => { + vol.fromJSON( + { + 'ios/testproject.xcodeproj/xcshareddata/xcschemes/testproject.xcscheme': fsReal.readFileSync( + path.join(__dirname, 'fixtures/testproject-2.xcscheme'), + 'utf-8' + ), + }, + '/app' + ); + }); + + afterAll(() => { + vol.reset(); + }); + + it('returns the target name for existing scheme', async () => { + const target = await getApplicationTargetForSchemeAsync('/app', 'testproject'); + expect(target).toBe('testproject'); + }); - it('throws if the scheme does not exist', async () => { - await expect(() => - getApplicationTargetForSchemeAsync('/app', 'nonexistentscheme') - ).rejects.toThrow(/does not exist/); + it('throws if the scheme does not exist', async () => { + await expect(() => + getApplicationTargetForSchemeAsync('/app', 'nonexistentscheme') + ).rejects.toThrow(/does not exist/); + }); }); }); diff --git a/packages/config-plugins/src/ios/__tests__/fixtures/testproject-2.xcscheme b/packages/config-plugins/src/ios/__tests__/fixtures/testproject-2.xcscheme new file mode 100644 index 0000000000..ec4309cddf --- /dev/null +++ b/packages/config-plugins/src/ios/__tests__/fixtures/testproject-2.xcscheme @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +