From 0c90263c05c05aae32c5551226f2342f9f70f5c4 Mon Sep 17 00:00:00 2001 From: Jesse MacFadyen Date: Wed, 15 Sep 2021 18:40:06 -0700 Subject: [PATCH] parameterize extensions (#476) * parameterize extensions * add test for poorly formed extension ids --- src/commands/app/init.js | 61 ++++++++++++++++++++-------------- test/commands/app/init.test.js | 57 +++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 25 deletions(-) diff --git a/src/commands/app/init.js b/src/commands/app/init.js index adc6f3e3..42dc9042 100644 --- a/src/commands/app/init.js +++ b/src/commands/app/init.js @@ -135,32 +135,37 @@ class InitCommand extends BaseCommand { async selectExtensionPoints (flags, orgSupportedServices = null) { if (!flags.extensions) { return [implPromptChoices.find(i => i.value.name === 'application').value] + } else if (flags.extension) { + const extList = implPromptChoices.filter(i => flags.extension.indexOf(i.value.name) > -1) + .map(i => i.value) + if (extList.length < 1) { + throw new Error(`--extension=${flags.extension} not found.`) + } + return extList + } else { + const choices = cloneDeep(implPromptChoices).filter(i => i.value.name !== 'application') + + // disable extensions that lack required services + if (orgSupportedServices) { + const supportedServiceCodes = new Set(orgSupportedServices.map(s => s.code)) + // filter choices + choices.forEach(c => { + const missingServices = c.value.requiredServices.filter(s => !supportedServiceCodes.has(s)) + if (missingServices.length > 0) { + c.disabled = true + c.name = `${c.name}: missing service(s) in Org: '${missingServices}'` + } + }) + } + const answers = await this.prompt([{ + type: 'checkbox', + name: 'res', + message: 'Which extension point(s) do you wish to implement ?', + choices, + validate: atLeastOne + }]) + return answers.res } - - const choices = cloneDeep(implPromptChoices).filter(i => i.value.name !== 'application') - - // disable extensions that lack required services - if (orgSupportedServices) { - const supportedServiceCodes = new Set(orgSupportedServices.map(s => s.code)) - // filter choices - choices.forEach(c => { - const missingServices = c.value.requiredServices.filter(s => !supportedServiceCodes.has(s)) - if (missingServices.length > 0) { - c.disabled = true - c.name = `${c.name}: missing service(s) in Org: '${missingServices}'` - } - }) - } - - const answers = await this.prompt([{ - type: 'checkbox', - name: 'res', - message: 'Which extension point(s) do you wish to implement ?', - choices, - validate: atLeastOne - }]) - - return answers.res } async selectConsoleOrg (consoleCLI) { @@ -315,6 +320,12 @@ InitCommand.flags = { default: true, allowNo: true }), + extension: flags.string({ + description: 'Extension point(s) to implement', + char: 'e', + multiple: true, + exclusive: ['extensions'] + }), workspace: flags.string({ description: 'Specify the Adobe Developer Console Workspace to init from, defaults to Stage', default: DEFAULT_WORKSPACE, diff --git a/test/commands/app/init.test.js b/test/commands/app/init.test.js index 4de4eab6..3a0994a6 100644 --- a/test/commands/app/init.test.js +++ b/test/commands/app/init.test.js @@ -178,6 +178,9 @@ describe('bad args/flags', () => { test('--no-login and --workspace', async () => { await expect(TheCommand.run(['--no-login', '--workspace', 'dev'])).rejects.toThrow('--no-login and --workspace flags cannot be used together.') }) + test('--no-login and --extension does not exist', async () => { + await expect(TheCommand.run(['--no-login', '--extension', 'dev'])).rejects.toThrow('--extension=dev not found.') + }) }) describe('run', () => { @@ -277,6 +280,24 @@ describe('run', () => { expect(mockImport.importConfigJson).not.toHaveBeenCalled() }) + test('--no-login --yes --skip-install, --extension dx/asset-compute/worker/1', async () => { + mockExtensionPrompt.mockReturnValue({ res: excshellSelection }) + await TheCommand.run(['--no-login', '--yes', '--skip-install', '--extension', 'dx/asset-compute/worker/1']) + expect(mockGenInstantiate).toHaveBeenCalledTimes(2) + expect(mockGenInstantiate).toHaveBeenCalledWith( + 'fake-gen-base-app', + { options: { 'skip-prompt': true, 'project-name': 'cwd' } } + ) + expect(mockGenInstantiate).toHaveBeenCalledWith( + 'fake-gen-nui', + { options: { 'skip-prompt': true, force: true } } + ) + expect(mockInstallPackages).not.toHaveBeenCalled() + expect(LibConsoleCLI.init).not.toHaveBeenCalled() + expect(mockExtensionPrompt).not.toHaveBeenCalled() + expect(mockImport.importConfigJson).not.toHaveBeenCalled() + }) + // fake imported config const fakeConfig = { project: { @@ -518,6 +539,42 @@ describe('run', () => { expect(mockConsoleCLIInstance.createProject).toHaveBeenCalledWith(fakeOrg.id, 'fakedetails') }) + test('with login, --extension excshell, create new project', async () => { + mockConsoleCLIInstance.promptForSelectOrganization.mockResolvedValue(fakeOrg) + mockConsoleCLIInstance.promptForSelectProject.mockResolvedValue(null) // null = user selects to create a project + mockConsoleCLIInstance.createProject.mockResolvedValue(fakeProject) + mockConsoleCLIInstance.getWorkspaces.mockResolvedValue(fakeWorkspaces) + mockConsoleCLIInstance.getServicePropertiesFromWorkspace.mockResolvedValue(fakeServicePropertiesNoAssetCompute) + mockConsoleCLIInstance.getEnabledServicesForOrg.mockResolvedValue(fakeSupportedOrgServices) + mockConsoleCLIInstance.getWorkspaceConfig.mockResolvedValue(fakeConfig) + mockConsoleCLIInstance.promptForCreateProjectDetails.mockResolvedValue('fakedetails') + mockExtensionPrompt.mockReturnValue({}) + + await TheCommand.run(['--extension', 'dx/excshell/1']) + expect(mockGenInstantiate).toHaveBeenCalledTimes(2) + expect(mockGenInstantiate).toHaveBeenCalledWith( + 'fake-gen-base-app', + { options: { 'skip-prompt': false, 'project-name': 'hola' } } + ) + expect(mockGenInstantiate).toHaveBeenCalledWith( + 'fake-gen-excshell', + { options: { 'skip-prompt': false, force: true } } + ) + expect(mockInstallPackages).toHaveBeenCalled() + expect(LibConsoleCLI.init).toHaveBeenCalled() + expect(mockExtensionPrompt).not.toHaveBeenCalled() + expect(mockImport.importConfigJson).toHaveBeenCalledWith( + Buffer.from(JSON.stringify(fakeConfig)), + 'cwd', + { interactive: false, merge: true }, + { SERVICE_API_KEY: 'fakeclientid' } + ) + expect(mockConsoleCLIInstance.getWorkspaceConfig).toHaveBeenCalledWith(fakeOrg.id, fakeProject.id, fakeWorkspaces[0].id, fakeSupportedOrgServices) + // exchshell has no required service to be added + expect(mockConsoleCLIInstance.subscribeToServices).not.toHaveBeenCalled() + expect(mockConsoleCLIInstance.createProject).toHaveBeenCalledWith(fakeOrg.id, 'fakedetails') + }) + test('with login, select excshell, -w dev', async () => { mockConsoleCLIInstance.promptForSelectOrganization.mockResolvedValue(fakeOrg) mockConsoleCLIInstance.promptForSelectProject.mockResolvedValue(fakeProject)