diff --git a/src/plugins/picklists/index.e2e-spec.ts b/src/plugins/picklists/index.e2e-spec.ts index 2bea79ee..1cef9596 100644 --- a/src/plugins/picklists/index.e2e-spec.ts +++ b/src/plugins/picklists/index.e2e-spec.ts @@ -91,4 +91,16 @@ describe(Picklists.name, function() { cmd.output.toString() ); }); + it('should replace and deactivate a picklist value', () => { + const replaceCmd = child.spawnSync(path.resolve('bin', 'run'), [ + 'browserforce:apply', + '-f', + path.resolve(path.join(__dirname, 'replace-and-deactivate.json')) + ]); + assert.deepStrictEqual(replaceCmd.status, 0, replaceCmd.output.toString()); + assert( + /changing 'picklistValues' to.*/.test(replaceCmd.output.toString()), + replaceCmd.output.toString() + ); + }); }); diff --git a/src/plugins/picklists/index.ts b/src/plugins/picklists/index.ts index 85a51c81..379e782f 100644 --- a/src/plugins/picklists/index.ts +++ b/src/plugins/picklists/index.ts @@ -22,19 +22,47 @@ export default class Picklists extends BrowserforcePlugin { const page = await this.browserforce.openPage(picklistUrl); const picklistPage = new PicklistPage(page); const values = await picklistPage.getPicklistValues(); - const actionRequired = isActionRequired(action, values); - if (actionRequired) { - result.picklistValues.push({ - ...action, - actionRequired: true - }); - } else { - result.picklistValues.push(action); - } + const state = { ...action }; + const valueMatch = + action.value !== undefined + ? values.find(x => x.value === action.value) + : undefined; + const newValueMatch = + action.newValue !== undefined + ? values.find(x => x.value === action.newValue) + : undefined; + state.absent = !valueMatch; + state.active = valueMatch?.active; + state.newValueExists = Boolean(newValueMatch) || action.newValue === null; + result.picklistValues.push(state); } return result; } + public diff(state, definition) { + const actions = definition.picklistValues.filter((target, i) => { + const source = state.picklistValues[i]; + if (target.absent) { + return target.absent !== source.absent; + } + if (target.active !== undefined) { + return target.active !== source.active; + } + // replacing a picklist value is not idempotent + if ( + source.newValueExists && + (target.value !== undefined || target.replaceAllBlankValues) + ) { + return true; + } + return false; + }); + if (actions.length) { + return { picklistValues: actions }; + } + return undefined; + } + public async apply(config) { const conn = this.org.getConnection(); const fileProperties = await listMetadata( @@ -104,22 +132,3 @@ async function listMetadata(conn, sobjectTypes) { return []; } } - -function isActionRequired(action, values) { - const valueGiven = action.value !== undefined && action.value !== null; - const newValueGiven = - action.newValue !== undefined && action.newValue !== null; - if (valueGiven) { - const match = values.find(x => x.value === action.value); - if (!match) { - return false; - } - if (action.active !== undefined && action.active === match.active) { - return false; - } - } - if (newValueGiven && !values.find(x => x.value === action.newValue)) { - return false; - } - return true; -} diff --git a/src/plugins/picklists/pages.ts b/src/plugins/picklists/pages.ts index 34d2b366..4fd7dfc9 100644 --- a/src/plugins/picklists/pages.ts +++ b/src/plugins/picklists/pages.ts @@ -76,6 +76,7 @@ export class PicklistPage { this.page.waitForNavigation(), actionLinkHandles[0].click() ]); + await throwPageErrors(this.page); return new PicklistReplaceAndDeletePage(this.page); } @@ -106,6 +107,7 @@ export class PicklistPage { this.page.waitForNavigation(), actionLinkHandles[0].click() ]); + await throwPageErrors(this.page); return this.page; } } @@ -145,7 +147,7 @@ export class PicklistReplacePage { this.page.waitForNavigation(), this.page.click(this.saveButton) ]); - await this.throwPageErrors(); + await throwPageErrors(this.page); }, { onFailedAttempt: error => { @@ -162,22 +164,6 @@ export class PicklistReplacePage { } ); } - - async throwPageErrors() { - const errorHandle = await this.page.$( - 'div#validationError div.messageText' - ); - if (errorHandle) { - const errorMsg = await this.page.evaluate( - (div: HTMLDivElement) => div.innerText, - errorHandle - ); - await errorHandle.dispose(); - if (errorMsg && errorMsg.trim()) { - throw new Error(errorMsg.trim()); - } - } - } } export class PicklistReplaceAndDeletePage extends PicklistReplacePage { @@ -201,3 +187,17 @@ export class PicklistReplaceAndDeletePage extends PicklistReplacePage { await this.save(); } } + +async function throwPageErrors(page) { + const errorHandle = await page.$('div#validationError div.messageText'); + if (errorHandle) { + const errorMsg = await page.evaluate( + (div: HTMLDivElement) => div.innerText, + errorHandle + ); + await errorHandle.dispose(); + if (errorMsg && errorMsg.trim()) { + throw new Error(errorMsg.trim()); + } + } +} diff --git a/src/plugins/picklists/replace-and-deactivate.json b/src/plugins/picklists/replace-and-deactivate.json new file mode 100644 index 00000000..b3c79c5c --- /dev/null +++ b/src/plugins/picklists/replace-and-deactivate.json @@ -0,0 +1,21 @@ +{ + "$schema": "../schema.json", + "settings": { + "picklists": { + "picklistValues": [ + { + "metadataType": "CustomField", + "metadataFullName": "Vehicle__c.Features__c", + "value": "AUX", + "newValue": "Media" + }, + { + "metadataType": "CustomField", + "metadataFullName": "Vehicle__c.Features__c", + "value": "AUX", + "active": false + } + ] + } + } +} diff --git a/src/plugins/picklists/sfdx-source/objects/Vehicle__c/fields/Features__c.field-meta.xml b/src/plugins/picklists/sfdx-source/objects/Vehicle__c/fields/Features__c.field-meta.xml index fbd83a2b..91449f67 100644 --- a/src/plugins/picklists/sfdx-source/objects/Vehicle__c/fields/Features__c.field-meta.xml +++ b/src/plugins/picklists/sfdx-source/objects/Vehicle__c/fields/Features__c.field-meta.xml @@ -35,6 +35,11 @@ false + + AUX + false + +