diff --git a/lib/services/ios/export-options-plist-service.ts b/lib/services/ios/export-options-plist-service.ts index da763082e9..5f98c77df3 100644 --- a/lib/services/ios/export-options-plist-service.ts +++ b/lib/services/ios/export-options-plist-service.ts @@ -4,9 +4,39 @@ import { IProjectData, IBuildConfig } from "../../definitions/project"; import { IFileSystem } from "../../common/declarations"; import { injector } from "../../common/yok"; import { ITempService } from "../../definitions/temp-service"; +import * as constants from "../../constants"; export class ExportOptionsPlistService implements IExportOptionsPlistService { - constructor(private $fs: IFileSystem, private $tempService: ITempService) {} + constructor( + private $fs: IFileSystem, + private $tempService: ITempService, + private $projectData: IProjectData + ) {} + + private getExtensionProvisions() { + const provisioningJSONPath = path.join( + this.$projectData.getAppResourcesDirectoryPath(), + "iOS", + constants.NATIVE_EXTENSION_FOLDER, + "provisioning.json" + ); + if (!this.$fs.exists(provisioningJSONPath)) { + return ""; + } + + interface IProvisioningJSON { + [identifier: string]: string; + } + const provisioningJSON = this.$fs.readJson( + provisioningJSONPath + ) as IProvisioningJSON; + + return Object.entries(provisioningJSON) + .map(([id, provision]) => { + return `${id}\n ${provision}`; + }) + .join("\n"); + } public async createDevelopmentExportOptionsPlist( archivePath: string, @@ -31,6 +61,7 @@ export class ExportOptionsPlistService implements IExportOptionsPlistService { ${projectData.projectIdentifiers.ios} ${provision} + ${this.getExtensionProvisions()} `; } plistTemplate += ` @@ -87,6 +118,7 @@ export class ExportOptionsPlistService implements IExportOptionsPlistService { ${projectData.projectIdentifiers.ios} ${provision} + ${this.getExtensionProvisions()} `; } plistTemplate += ` method diff --git a/test/services/ios/export-options-plist-service.ts b/test/services/ios/export-options-plist-service.ts index f4b637eb60..3001e37407 100644 --- a/test/services/ios/export-options-plist-service.ts +++ b/test/services/ios/export-options-plist-service.ts @@ -2,26 +2,49 @@ import { Yok } from "../../../lib/common/yok"; import { ExportOptionsPlistService } from "../../../lib/services/ios/export-options-plist-service"; import { assert } from "chai"; import * as _ from "lodash"; -import { TempServiceStub } from "../../stubs"; +import { TempServiceStub, ProjectDataStub } from "../../stubs"; let actualPlistTemplate: string = null; const projectName = "myProjectName"; const projectRoot = "/my/test/project/platforms/ios"; const archivePath = "/my/test/archive/path"; +let provisioningJSON: Record | undefined; + function createTestInjector() { const injector = new Yok(); + provisioningJSON = undefined; injector.register("fs", { + exists(path: string) { + return path.endsWith("provisioning.json"); + }, writeFile: (exportPath: string, plistTemplate: string) => { actualPlistTemplate = plistTemplate; }, + readJson() { + return provisioningJSON ?? {}; + }, }); injector.register("exportOptionsPlistService", ExportOptionsPlistService); injector.register("tempService", TempServiceStub); + const projectData = new ProjectDataStub(); + projectData.initializeProjectData(projectRoot); + projectData.projectName = projectName; + + injector.register("projectData", projectData); return injector; } +function expectPlistTemplateToContain(template: string, expected: string) { + const trimmedTemplate = template.replace(/\s/g, ""); + const trimmedExpected = expected.replace(/\s/g, ""); + assert.isTrue( + trimmedTemplate.indexOf(trimmedExpected) !== -1, + `Expected plist template to contain:\n\n${expected}\n\nbut it was:\n\n${template}` + ); +} + describe("ExportOptionsPlistService", () => { describe("createDevelopmentExportOptionsPlist", () => { const testCases = [ @@ -33,21 +56,29 @@ describe("ExportOptionsPlistService", () => { name: "should create export options plist with provision", buildConfig: { provision: "myTestProvision" }, expectedPlist: - "provisioningProfiles org.nativescript.myTestApp myTestProvision ", + "provisioningProfilesorg.nativescript.myTestAppmyTestProvision", }, { - name: - "should create export options plist with mobileProvisionIdentifier", + name: "should create export options plist with mobileProvisionIdentifier", buildConfig: { mobileProvisionIdentifier: "myTestProvision" }, expectedPlist: - "provisioningProfiles org.nativescript.myTestApp myTestProvision ", + "provisioningProfilesorg.nativescript.myTestAppmyTestProvision", }, { - name: - "should create export options plist with Production iCloudContainerEnvironment", + name: "should create export options plist with Production iCloudContainerEnvironment", buildConfig: { iCloudContainerEnvironment: "Production" }, expectedPlist: - "iCloudContainerEnvironment Production", + "iCloudContainerEnvironmentProduction", + }, + { + name: "should add extension provisioning profiles if there are any", + buildConfig: { provision: "myTestProvision" }, + provisioningJSON: { + "org.nativescript.myTestApp.SampleExtension": + "mySampleExtensionTestProvision", + }, + expectedPlist: + "provisioningProfilesorg.nativescript.myTestAppmyTestProvisionorg.nativescript.myTestApp.SampleExtensionmySampleExtensionTestProvision", }, ]; @@ -57,6 +88,9 @@ describe("ExportOptionsPlistService", () => { (provisionType) => { it(testCase.name, async () => { const injector = createTestInjector(); + if (testCase.provisioningJSON) { + provisioningJSON = testCase.provisioningJSON; + } const exportOptionsPlistService = injector.resolve( "exportOptionsPlistService" ); @@ -73,20 +107,23 @@ describe("ExportOptionsPlistService", () => { testCase.buildConfig ); - const template = actualPlistTemplate.split("\n").join(" "); - assert.isTrue( - template.indexOf( - `method ${provisionType}` - ) > 0 + expectPlistTemplateToContain( + actualPlistTemplate, + `method${provisionType}` ); - assert.isTrue( - template.indexOf("uploadBitcode ") > 0 + expectPlistTemplateToContain( + actualPlistTemplate, + `uploadBitcode` ); - assert.isTrue( - template.indexOf("compileBitcode ") > 0 + expectPlistTemplateToContain( + actualPlistTemplate, + `compileBitcode` ); if (testCase.expectedPlist) { - assert.isTrue(template.indexOf(testCase.expectedPlist) > 0); + expectPlistTemplateToContain( + actualPlistTemplate, + testCase.expectedPlist + ); } }); } @@ -103,25 +140,37 @@ describe("ExportOptionsPlistService", () => { name: "should create export options plist with provision", buildConfig: { provision: "myTestProvision" }, expectedPlist: - "provisioningProfiles org.nativescript.myTestApp myTestProvision ", + "provisioningProfilesorg.nativescript.myTestAppmyTestProvision", }, { - name: - "should create export options plist with mobileProvisionIdentifier", + name: "should create export options plist with mobileProvisionIdentifier", buildConfig: { mobileProvisionIdentifier: "myTestProvision" }, expectedPlist: - "provisioningProfiles org.nativescript.myTestApp myTestProvision ", + "provisioningProfilesorg.nativescript.myTestAppmyTestProvision", }, { name: "should create export options plist with teamID", buildConfig: { teamId: "myTeamId" }, - expectedPlist: "teamID myTeamId", + expectedPlist: "teamIDmyTeamId", + }, + { + name: "should add extension provisioning profiles if there are any", + buildConfig: { provision: "myTestProvision" }, + provisioningJSON: { + "org.nativescript.myTestApp.SampleExtension": + "mySampleExtensionTestProvision", + }, + expectedPlist: + "provisioningProfilesorg.nativescript.myTestAppmyTestProvisionorg.nativescript.myTestApp.SampleExtensionmySampleExtensionTestProvision", }, ]; _.each(testCases, (testCase) => { it(testCase.name, async () => { const injector = createTestInjector(); + if (testCase.provisioningJSON) { + provisioningJSON = testCase.provisioningJSON; + } const exportOptionsPlistService = injector.resolve( "exportOptionsPlistService" ); @@ -137,22 +186,28 @@ describe("ExportOptionsPlistService", () => { testCase.buildConfig ); - const template = actualPlistTemplate.split("\n").join(" "); - assert.isTrue( - template.indexOf("method app-store") > - 0 + expectPlistTemplateToContain( + actualPlistTemplate, + `methodapp-store` ); - assert.isTrue( - template.indexOf("uploadBitcode ") > 0 + expectPlistTemplateToContain( + actualPlistTemplate, + `uploadBitcode` ); - assert.isTrue( - template.indexOf("compileBitcode ") > 0 + expectPlistTemplateToContain( + actualPlistTemplate, + `compileBitcode` ); - assert.isTrue( - template.indexOf("uploadSymbols ") > 0 + expectPlistTemplateToContain( + actualPlistTemplate, + `uploadSymbols` ); + if (testCase.expectedPlist) { - assert.isTrue(template.indexOf(testCase.expectedPlist) > 0); + expectPlistTemplateToContain( + actualPlistTemplate, + testCase.expectedPlist + ); } }); });