diff --git a/test/commands/source/deploy.test.ts b/test/commands/source/deploy.test.ts index 8e5a29883..0346001c8 100644 --- a/test/commands/source/deploy.test.ts +++ b/test/commands/source/deploy.test.ts @@ -10,7 +10,7 @@ import * as sinon from 'sinon'; import { expect } from 'chai'; import { MetadataApiDeployOptions } from '@salesforce/source-deploy-retrieve'; import { fromStub, stubInterface, stubMethod } from '@salesforce/ts-sinon'; -import { Lifecycle, Org, SfdxProject } from '@salesforce/core'; +import { ConfigAggregator, Lifecycle, Org, SfdxProject } from '@salesforce/core'; import { UX } from '@salesforce/command'; import { IConfig } from '@oclif/config'; import { Deploy } from '../../../src/commands/force/source/deploy'; @@ -261,6 +261,87 @@ describe('force:source:deploy', () => { ensureProgressBar(1); }); + it('should use SOAP by default', async () => { + delete process.env.SFDX_REST_DEPLOY; + const sourcepath = ['somepath']; + const cmd = new TestDeploy(['--sourcepath', sourcepath[0]], oclifConfigStub); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore private method + expect(cmd.isRest).to.be.false; + }); + + it('should use SOAP from the env var', async () => { + try { + process.env.SFDX_REST_DEPLOY = 'false'; + const sourcepath = ['somepath']; + const cmd = new TestDeploy(['--sourcepath', sourcepath[0]], oclifConfigStub); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore private method + expect(cmd.isRest).to.be.false; + } finally { + delete process.env.SFDX_REST_DEPLOY; + } + }); + + it('should use REST from the env var', async () => { + try { + process.env.SFDX_REST_DEPLOY = 'true'; + const sourcepath = ['somepath']; + const cmd = new TestDeploy(['--sourcepath', sourcepath[0]], oclifConfigStub); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore private method + expect(cmd.isRest).to.be.false; + } finally { + delete process.env.SFDX_REST_DEPLOY; + } + }); + + it('should use SOAP by overriding env var with flag', async () => { + try { + process.env.SFDX_REST_DEPLOY = 'true'; + const sourcepath = ['somepath']; + const cmd = new TestDeploy(['--sourcepath', sourcepath[0], '--soapdeploy'], oclifConfigStub); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore private method + expect(cmd.isRest).to.be.false; + } finally { + delete process.env.SFDX_REST_DEPLOY; + } + }); + + it('should use SOAP from flag', async () => { + const sourcepath = ['somepath']; + const cmd = new TestDeploy(['--sourcepath', sourcepath[0], '--soapdeploy'], oclifConfigStub); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore private method + expect(cmd.isRest).to.be.false; + }); + + it('should use SOAP from config', async () => { + stubMethod(sandbox, ConfigAggregator, 'create').resolves(ConfigAggregator.prototype); + stubMethod(sandbox, ConfigAggregator.prototype, 'getPropertyValue').returns('false'); + const sourcepath = ['somepath']; + const cmd = new TestDeploy(['--sourcepath', sourcepath[0], '--soapdeploy'], oclifConfigStub); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore private method + expect(cmd.isRest).to.be.false; + }); + + it('should use SOAP by overriding env var with config', async () => { + try { + process.env.SFDX_REST_DEPLOY = 'true'; + stubMethod(sandbox, ConfigAggregator, 'create').resolves(ConfigAggregator.prototype); + stubMethod(sandbox, ConfigAggregator.prototype, 'getPropertyValue').returns('false'); + const sourcepath = ['somepath']; + const cmd = new TestDeploy(['--sourcepath', sourcepath[0], '--soapdeploy'], oclifConfigStub); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore private method + expect(cmd.isRest).to.be.false; + } finally { + delete process.env.SFDX_REST_DEPLOY; + } + }); + it('should emit postdeploy hooks for validateddeployrequestid deploys', async () => { await runDeployCmd(['--validateddeployrequestid', '0Af0x00000pkAXLCA2']); expect(lifecycleEmitStub.firstCall.args[0]).to.equal('postdeploy'); diff --git a/test/nuts/REST/deploy.mpd.nut.ts b/test/nuts/REST/deploy.mpd.nut.ts new file mode 100644 index 000000000..73d2809e5 --- /dev/null +++ b/test/nuts/REST/deploy.mpd.nut.ts @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2020, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ + +import * as path from 'path'; +import { SourceTestkit } from '@salesforce/source-testkit'; + +const EXECUTABLE = path.join(process.cwd(), 'bin', 'run'); + +const repo = { + name: 'sample-project-multiple-packages', + gitUrl: 'https://github.com/salesforcecli/sample-project-multiple-packages.git', + deploy: { + sourcepath: [ + { toDeploy: '"force-app, my-app, foo-bar"', toVerify: ['force-app/**/*', 'my-app/**/*', 'foo-bar/**/*'] }, + { + toDeploy: + 'force-app/main/default/labels/CustomLabels.labels-meta.xml,my-app/labels/CustomLabels.labels-meta.xml', + toVerify: [ + 'force-app/main/default/labels/CustomLabels.labels-meta.xml', + 'my-app/labels/CustomLabels.labels-meta.xml', + ], + }, + { + toDeploy: 'force-app/main/default/labels/CustomLabels.labels-meta.xml', + toVerify: ['force-app/main/default/labels/CustomLabels.labels-meta.xml'], + }, + ], + metadata: [ + { toDeploy: 'CustomObject', toVerify: ['force-app/main/default/objects/*__c/*', 'my-app/objects/*__c/*'] }, + { + toDeploy: 'CustomLabels', + toVerify: [ + 'force-app/main/default/labels/CustomLabels.labels-meta.xml', + 'my-app/labels/CustomLabels.labels-meta.xml', + ], + }, + ], + manifest: [ + { toDeploy: 'force-app', toVerify: ['force-app/**/*'] }, + // { toDeploy: '"force-app, my-app"', toVerify: ['force-app/**/*', 'my-app/**/*'] }, SDR BUG + ], + }, +}; + +context(`MPD REST Deploy NUTs [name: ${repo.name}] [exec: ${EXECUTABLE} ]`, () => { + let testkit: SourceTestkit; + + before(async () => { + process.env.SFDX_REST_DEPLOY = 'true'; + testkit = await SourceTestkit.create({ + repository: repo.gitUrl, + executable: EXECUTABLE, + nut: __filename, + }); + }); + + after(async () => { + try { + delete process.env.SFDX_REST_DEPLOY; + await testkit?.clean(); + } catch (e) { + // if the it fails to clean, don't throw so NUTs will pass + // eslint-disable-next-line no-console + console.log('Clean Failed: ', e); + } + }); + + describe('--sourcepath ', () => { + for (const sourcepath of repo.deploy.sourcepath) { + const toDeploy = path.normalize(sourcepath.toDeploy); + it(`should deploy ${toDeploy}`, async () => { + await testkit.deploy({ args: `--sourcepath ${toDeploy}` }); + await testkit.expect.filesToBeDeployed(sourcepath.toVerify); + }); + } + }); + + describe('--sourcepath ', () => { + for (const metadata of repo.deploy.metadata) { + const toDeploy = path.normalize(metadata.toDeploy); + it(`should deploy ${toDeploy}`, async () => { + await testkit.deploy({ args: `--metadata ${toDeploy}` }); + await testkit.expect.filesToBeDeployed(metadata.toVerify); + }); + } + }); + + describe('--manifest flag', () => { + for (const testCase of repo.deploy.manifest) { + const toDeploy = path.normalize(testCase.toDeploy); + it(`should deploy ${toDeploy}`, async () => { + await testkit.convert({ args: `--sourcepath ${toDeploy} --outputdir out` }); + const packageXml = path.join('out', 'package.xml'); + + await testkit.deploy({ args: `--manifest ${packageXml}` }); + await testkit.expect.filesToBeDeployed(testCase.toVerify); + }); + } + }); + + describe('--checkonly flag', () => { + const toDeploy = path.normalize(repo.deploy.sourcepath[0].toDeploy); + it(`should checkonly deploy ${toDeploy}`, async () => { + await testkit.deploy({ + args: `--sourcepath ${toDeploy} --checkonly --ignoreerrors`, + }); + await testkit.expect.filesToNotBeDeployed(repo.deploy.sourcepath[0].toVerify); + }); + }); + + it('should run tests in org (RunAllTestsInOrg)', async () => { + const toDeploy = path.normalize(repo.deploy.sourcepath[0].toDeploy); + await testkit.deploy({ + args: `--sourcepath ${toDeploy}`, + }); + await testkit.deploy({ + args: `--sourcepath ${toDeploy} --testlevel RunAllTestsInOrg`, + }); + await testkit.expect.apexTestsToBeRun(); + }); + + // TODO: once SDR v3 with async polling - update validateddeployrequestid polling + // describe('--validateddeployrequestid', () => { + // it('should return an id immediately when --wait is set to 0 and deploy:report should report results', async () => { + // // deploy all metadata to the org so that we can run tests + // await testkit.deploy({ args: '--sourcepath force-app' }); + // // running tests requires a special permission in the 'dreamhouse' permission set + // await testkit.assignPermissionSet({ args: '--permsetname dreamhouse' }); + // + // const checkOnly = await testkit.deploy({ + // args: '--sourcepath force-app/main/default/classes --testlevel RunLocalTests --checkonly --ignoreerrors', + // }); + // testkit.expect.toHaveProperty(checkOnly.result, 'id'); + // + // const quickDeploy = await testkit.deploy({ + // args: `--validateddeployrequestid ${checkOnly.result.id}`, + // }); + // testkit.expect.toHavePropertyAndValue(quickDeploy.result, 'status', 'Succeeded'); + // await testkit.expect.filesToBeDeployed(testkit.packageGlobs); + // }); + // }); +}); diff --git a/test/nuts/REST/deploy.nut.ts b/test/nuts/REST/deploy.nut.ts new file mode 100644 index 000000000..b829a585e --- /dev/null +++ b/test/nuts/REST/deploy.nut.ts @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2020, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ + +import * as path from 'path'; +import { SourceTestkit } from '@salesforce/source-testkit'; + +const EXECUTABLE = path.join(process.cwd(), 'bin', 'run'); + +const repo = { + name: 'dreamhouse-lwc', + gitUrl: 'https://github.com/trailheadapps/dreamhouse-lwc.git', + deploy: { + sourcepath: [ + { toDeploy: 'force-app/main/default/objects', toVerify: ['force-app/main/default/objects/**/*'] }, + { + toDeploy: 'force-app/main/default/classes,force-app/main/default/objects', + toVerify: ['force-app/main/default/classes/*', 'force-app/main/default/objects/**/*'], + }, + ], + metadata: [ + { toDeploy: 'ApexClass', toVerify: ['force-app/main/default/classes/*'] }, + { + toDeploy: 'ApexClass,CustomObject:Broker__c', + toVerify: ['force-app/main/default/classes/*', 'force-app/main/default/objects/Broker__c/*'], + }, + ], + manifest: [ + { + toDeploy: 'force-app/main/default/classes,force-app/main/default/objects', + toVerify: ['force-app/main/default/classes/*', 'force-app/main/default/objects/*'], + }, + ], + }, +}; + +context(`REST Deploy NUTs [name: ${repo.name}] [exec: ${EXECUTABLE} ]`, () => { + let testkit: SourceTestkit; + + before(async () => { + process.env.SFDX_REST_DEPLOY = 'true'; + testkit = await SourceTestkit.create({ + repository: repo.gitUrl, + executable: EXECUTABLE, + nut: __filename, + }); + }); + + after(async () => { + try { + delete process.env.SFDX_REST_DEPLOY; + await testkit?.clean(); + } catch (e) { + // if the it fails to clean, don't throw so NUTs will pass + // eslint-disable-next-line no-console + console.log('Clean Failed: ', e); + } + }); + + describe('--sourcepath', () => { + for (const sourcepath of repo.deploy.sourcepath) { + const toDeploy = path.normalize(sourcepath.toDeploy); + it(`should deploy ${toDeploy}`, async () => { + await testkit.deploy({ args: `--sourcepath ${toDeploy}` }); + await testkit.expect.filesToBeDeployed(sourcepath.toVerify); + }); + } + }); + + describe('--metadata ', () => { + for (const metadata of repo.deploy.metadata) { + const toDeploy = path.normalize(metadata.toDeploy); + it(`should deploy ${toDeploy}`, async () => { + await testkit.deploy({ args: `--metadata ${toDeploy}` }); + await testkit.expect.filesToBeDeployed(metadata.toVerify); + }); + } + }); + + describe('--manifest', () => { + for (const testCase of repo.deploy.manifest) { + const toDeploy = path.normalize(testCase.toDeploy); + it(`should deploy ${toDeploy}`, async () => { + await testkit.convert({ args: `--sourcepath ${toDeploy} --outputdir out` }); + const packageXml = path.join('out', 'package.xml'); + + await testkit.deploy({ args: `--manifest ${packageXml}` }); + await testkit.expect.filesToBeDeployed(testCase.toVerify); + }); + } + }); + + describe('--checkonly flag', () => { + const toDeploy = path.normalize(repo.deploy.sourcepath[0].toDeploy); + it(`should checkonly deploy ${toDeploy}`, async () => { + await testkit.deploy({ + args: `--sourcepath ${toDeploy} --checkonly --ignoreerrors`, + }); + await testkit.expect.filesToNotBeDeployed(repo.deploy.sourcepath[0].toVerify); + }); + }); + + // TODO: once SDR v3 with async polling - update validateddeployrequestid polling + // describe('--validateddeployrequestid', () => { + // it('should return an id immediately when --wait is set to 0 and deploy:report should report results', async () => { + // // deploy all metadata to the org so that we can run tests + // await testkit.deploy({ args: '--sourcepath force-app' }); + // // running tests requires a special permission in the 'dreamhouse' permission set + // await testkit.assignPermissionSet({ args: '--permsetname dreamhouse' }); + // + // const checkOnly = await testkit.deploy({ + // args: '--sourcepath force-app/main/default/classes --testlevel RunLocalTests --checkonly --ignoreerrors', + // }); + // testkit.expect.toHaveProperty(checkOnly.result, 'id'); + // + // const quickDeploy = await testkit.deploy({ + // args: `--validateddeployrequestid ${checkOnly.result.id}`, + // }); + // testkit.expect.toHavePropertyAndValue(quickDeploy.result, 'status', 'Succeeded'); + // await testkit.expect.filesToBeDeployed(testkit.packageGlobs); + // }); + // }); +});