From 3cf7e82ebe3bc96b3d350866da5ae6d1fcf03abe Mon Sep 17 00:00:00 2001 From: fransflippo Date: Sun, 25 Jul 2021 20:06:43 +0200 Subject: [PATCH] Handling existing permission set errors better --- src/helpers/permissionSetHelper.ts | 46 ++++++++++++++---------- test/commands/ci/setup.test.ts | 15 +++++++- test/helpers/permissionSetHelper.test.ts | 17 +++++++-- 3 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/helpers/permissionSetHelper.ts b/src/helpers/permissionSetHelper.ts index c4b566e..c88ed93 100644 --- a/src/helpers/permissionSetHelper.ts +++ b/src/helpers/permissionSetHelper.ts @@ -1,4 +1,5 @@ import {Connection} from '@salesforce/core'; +import {SaveError} from 'jsforce'; import {PermissionSet} from '../types/permissionSet'; import {handleSaveResultError, toApiName} from './sfdx-utils'; @@ -23,32 +24,39 @@ export class PermissionSetHelper { const saveResult = await connection.metadata .create('PermissionSet', permissionSet) .catch(error => { - if (error.name === 'DUPLICATE_VALUE') { - // Permission set already exists, return false - return false; - } else { - // Synthesize a SaveResult that contains the error information so that all errors are handled in the same way - return { - fullName: permissionSetApiName, - success: false, - errors: { - fields: '', - message: error.toString(), - statusCode: '' - } - }; - } + // Synthesize a SaveResult that contains the error information so that all errors are handled in the same way + return { + fullName: permissionSetApiName, + success: false, + errors: { + fields: '', + message: error.toString(), + statusCode: '' + } + }; }); - if (saveResult === false) { - return false; - } if (Array.isArray(saveResult)) { throw new Error('Expected a single SaveResult but got: ' + saveResult); } + if (saveResult.success) { + return true; + } + let errors: SaveError[]; + if (!Array.isArray(saveResult.errors)) { + errors = [saveResult.errors as SaveError]; + } else { + errors = saveResult.errors as SaveError[]; + } + for (const i in errors) { + if (errors[i].statusCode === 'DUPLICATE_DEVELOPER_NAME') { + // Duplicate API name: we can safely ignore this + return false; + } + } + // Report error if (!saveResult.success) { handleSaveResultError(saveResult); } - return true; } /** diff --git a/test/commands/ci/setup.test.ts b/test/commands/ci/setup.test.ts index 8f9aff5..83c8338 100644 --- a/test/commands/ci/setup.test.ts +++ b/test/commands/ci/setup.test.ts @@ -274,7 +274,20 @@ the connected app by assigning the permission set using: connectionIdentityStub.resolves({ user_id: userId, username } as IdentityInfo); const error = new Error(); error.name = 'DUPLICATE_VALUE'; - metadataCreateStub.withArgs('PermissionSet', { fullName: 'Continuous_Integration', label: 'Continuous Integration', description: 'Permission set for the Continuous Integration connected app'}).rejects(error); + metadataCreateStub.withArgs('PermissionSet', { fullName: 'Continuous_Integration', label: 'Continuous Integration', description: 'Permission set for the Continuous Integration connected app'}).resolves({ + success: false, + errors: [ + { + fields: 'Label', + message: 'The label you entered is in use. Enter a unique label.', + statusCode: 'DUPLICATE_MASTER_LABEL' + }, { + fields: 'Label', + message: 'The API name you entered is already in use. Enter a unique API name.', + statusCode: 'DUPLICATE_DEVELOPER_NAME' + } + ] + }); connectionQueryStub.withArgs("SELECT Id, Name from PermissionSet WHERE Name = 'Continuous_Integration'").resolves({ done: true, totalSize: 1, records: [ { Id: 'PermissionSetId' } ]}); // eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore diff --git a/test/helpers/permissionSetHelper.test.ts b/test/helpers/permissionSetHelper.test.ts index 18d8113..1112cac 100644 --- a/test/helpers/permissionSetHelper.test.ts +++ b/test/helpers/permissionSetHelper.test.ts @@ -44,9 +44,20 @@ describe('PermissionSetHelper', () => { const metadataStub = sinon.createStubInstance(Metadata); const metadata = metadataStub as unknown as Metadata; connection.metadata = metadata; - const error = new Error(); - error.name = 'DUPLICATE_VALUE'; - metadata.create.withArgs('PermissionSet', sinon.match.any).returns(Promise.reject(error)); + metadata.create.withArgs('PermissionSet', sinon.match.any).returns(Promise.resolve({ + success: false, + errors: [ + { + fields: 'Label', + message: 'The label you entered is in use. Enter a unique label.', + statusCode: 'DUPLICATE_MASTER_LABEL' + }, { + fields: 'Label', + message: 'The API name you entered is already in use. Enter a unique API name.', + statusCode: 'DUPLICATE_DEVELOPER_NAME' + } + ] + })); // When const created = await permissionSetHelper.createPermissionSet(connection, 'My Permissions', 'This is my permission set');