|
5 | 5 | * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause |
6 | 6 | */ |
7 | 7 |
|
8 | | -import { AuthInfo, Messages, Org, SfError } from '@salesforce/core'; |
| 8 | +import { AuthInfo, Connection, Messages, Org, SfError } from '@salesforce/core'; |
9 | 9 | import { MockTestOrgData, TestContext } from '@salesforce/core/testSetup'; |
10 | 10 | import { SinonStub } from 'sinon'; |
11 | 11 | import { config, expect } from 'chai'; |
@@ -38,6 +38,12 @@ describe('org delete', () => { |
38 | 38 | }); |
39 | 39 |
|
40 | 40 | describe('sandbox', () => { |
| 41 | + let sandboxReadStub: SinonStub; |
| 42 | + |
| 43 | + beforeEach(() => { |
| 44 | + sandboxReadStub = $$.SANDBOX.stub(SandboxAccessor.prototype, 'read').resolves(null); |
| 45 | + }); |
| 46 | + |
41 | 47 | it('will throw an error when no org provided', async () => { |
42 | 48 | await $$.stubConfig({}); |
43 | 49 | try { |
@@ -67,21 +73,6 @@ describe('org delete', () => { |
67 | 73 | } |
68 | 74 | }); |
69 | 75 |
|
70 | | - it('will throw an error when the org is not identified as a sandbox', async () => { |
71 | | - $$.SANDBOX.stub(SandboxAccessor.prototype, 'hasFile').resolves(false); |
72 | | - await $$.stubConfig({ 'target-org': testOrg.username }); |
73 | | - try { |
74 | | - await DeleteSandbox.run(['--target-org', testOrg.username]); |
75 | | - expect.fail('should have thrown UnknownSandboxError'); |
76 | | - } catch (e) { |
77 | | - const err = e as SfError; |
78 | | - expect(err.name).to.equal('UnknownSandboxError'); |
79 | | - const expectedActions = sbxOrgMessages.getMessage('error.unknownSandbox.actions'); |
80 | | - const errorActions = err.actions ?? []; |
81 | | - expect(errorActions[0]).to.equal(expectedActions); |
82 | | - } |
83 | | - }); |
84 | | - |
85 | 76 | it('will prompt before attempting to delete by username', async () => { |
86 | 77 | $$.SANDBOX.stub(SandboxAccessor.prototype, 'hasFile').resolves(true); |
87 | 78 | await $$.stubConfig({ 'target-org': testOrg.username }); |
@@ -128,6 +119,61 @@ describe('org delete', () => { |
128 | 119 | JSON.stringify(sfCommandUxStubs.logSuccess.getCalls().flatMap((call) => call.args)) |
129 | 120 | ).to.deep.include(sbxOrgMessages.getMessage('success.Idempotent', [testOrg.username])); |
130 | 121 | }); |
| 122 | + |
| 123 | + it('will throw a clean SfError when the user lacks Manage Sandboxes permission', async () => { |
| 124 | + $$.SANDBOX.stub(SandboxAccessor.prototype, 'hasFile').resolves(true); |
| 125 | + orgDeleteStub.restore(); |
| 126 | + const insufficientAccessError = Object.assign(new Error('INSUFFICIENT_ACCESS_OR_READONLY'), { |
| 127 | + errorCode: 'INSUFFICIENT_ACCESS_OR_READONLY', |
| 128 | + }); |
| 129 | + $$.SANDBOX.stub(Org.prototype, 'delete').throws(insufficientAccessError); |
| 130 | + try { |
| 131 | + await DeleteSandbox.run(['--no-prompt', '--target-org', testOrg.username]); |
| 132 | + expect.fail('should have thrown InsufficientAccessError'); |
| 133 | + } catch (e) { |
| 134 | + const err = e as SfError; |
| 135 | + expect(err.name).to.equal('InsufficientAccessError'); |
| 136 | + expect(err.message).to.equal(sbxOrgMessages.getMessage('error.insufficientAccess')); |
| 137 | + } |
| 138 | + }); |
| 139 | + |
| 140 | + describe('DeleteSandbox permission check', () => { |
| 141 | + let identityStub: SinonStub; |
| 142 | + let queryStub: SinonStub; |
| 143 | + |
| 144 | + beforeEach(() => { |
| 145 | + $$.SANDBOX.stub(SandboxAccessor.prototype, 'hasFile').resolves(true); |
| 146 | + $$.SANDBOX.stub(Org.prototype, 'refreshAuth').resolves(); |
| 147 | + identityStub = $$.SANDBOX.stub(Connection.prototype, 'identity'); |
| 148 | + queryStub = $$.SANDBOX.stub(Connection.prototype, 'query'); |
| 149 | + }); |
| 150 | + |
| 151 | + it('will allow deletion when user has DeleteSandbox permission set', async () => { |
| 152 | + sandboxReadStub.resolves({ sandboxOrgId: testOrg.orgId, prodOrgUsername: testHub.username }); |
| 153 | + // eslint-disable-next-line camelcase |
| 154 | + identityStub.resolves({ user_id: '005xx000001X' }); |
| 155 | + queryStub.resolves({ totalSize: 1, records: [{ Id: '0Pa000000000001' }] }); |
| 156 | + const res = await DeleteSandbox.run(['--no-prompt', '--target-org', testOrg.username]); |
| 157 | + expect(sfCommandUxStubs.logSuccess.callCount).to.equal(1); |
| 158 | + expect(res).to.deep.equal({ orgId: testOrg.orgId, username: testOrg.username }); |
| 159 | + }); |
| 160 | + |
| 161 | + it('will block deletion when user lacks DeleteSandbox permission set', async () => { |
| 162 | + sandboxReadStub.resolves({ sandboxOrgId: testOrg.orgId, prodOrgUsername: testHub.username }); |
| 163 | + // eslint-disable-next-line camelcase |
| 164 | + identityStub.resolves({ user_id: '005xx000001X' }); |
| 165 | + queryStub.resolves({ totalSize: 0, records: [] }); |
| 166 | + try { |
| 167 | + await DeleteSandbox.run(['--no-prompt', '--target-org', testOrg.username]); |
| 168 | + expect.fail('should have thrown InsufficientPermissionsError'); |
| 169 | + } catch (e) { |
| 170 | + const err = e as SfError; |
| 171 | + expect(err.name).to.equal('InsufficientPermissionsError'); |
| 172 | + expect(err.message).to.include(testOrg.username); |
| 173 | + expect(err.message).to.include('DeleteSandbox'); |
| 174 | + } |
| 175 | + }); |
| 176 | + }); |
131 | 177 | }); |
132 | 178 |
|
133 | 179 | describe('scratch', () => { |
|
0 commit comments