Skip to content

Commit 36cad5e

Browse files
committed
Org preference to disable rollback flags and test
1 parent ced6295 commit 36cad5e

File tree

5 files changed

+274
-0
lines changed

5 files changed

+274
-0
lines changed

src/commands/omnistudio/migration/migrate.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import OmnistudioRelatedObjectMigrationFacade from '../../../migration/related/O
2323
import { generatePackageXml } from '../../../utils/generatePackageXml';
2424
import { OmnistudioOrgDetails, OrgUtils } from '../../../utils/orgUtils';
2525
import { Constants } from '../../../utils/constants/stringContants';
26+
import { OrgPreferences } from '../../../utils/orgpreferences';
2627

2728
// Initialize Messages with the current plugin directory
2829
Messages.importMessagesDirectory(__dirname);
@@ -67,6 +68,7 @@ export default class Migrate extends OmniStudioBaseCommand {
6768

6869
Logger.initialiseLogger(this.ux, this.logger);
6970
this.logger = Logger.logger;
71+
7072
// this.org is guaranteed because requiresUsername=true, as opposed to supportsUsername
7173
const conn = this.org.getConnection();
7274
conn.setApiVersion(apiVersion);
@@ -87,6 +89,17 @@ export default class Migrate extends OmniStudioBaseCommand {
8789
return;
8890
}
8991

92+
// Enable Omni preferences
93+
try {
94+
this.ux.log('Enabling Omni preferences...');
95+
await OrgPreferences.enableOmniPreferences(conn);
96+
this.ux.log('Omni preferences enabled successfully.');
97+
} catch (error) {
98+
const errMsg = error instanceof Error ? error.message : String(error);
99+
this.ux.log(`Error: Could not enable Omni preferences: ${errMsg}`);
100+
throw error;
101+
}
102+
90103
const namespace = orgs.packageDetails.namespace;
91104
// Let's time every step
92105
DebugTimer.getInstance().start();

src/utils/orgUtils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export interface OmnistudioOrgDetails {
2121
orgDetails: OrgDetails;
2222
dataModel: string;
2323
hasValidNamespace: boolean;
24+
rollbackFlags?: string[];
2425
}
2526

2627
export interface PackageDetail {

src/utils/orgpreferences.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { Connection } from '@salesforce/core';
2+
3+
/**
4+
* Interface representing the metadata structure for OmniStudio settings
5+
*
6+
* @interface OmniStudioSettingsMetadata
7+
* @property {string} fullName - The full name of the OmniStudio settings
8+
* @property {boolean} disableRollbackFlagsPref - Flag to disable rollback preferences
9+
*/
10+
interface OmniStudioSettingsMetadata {
11+
fullName: string;
12+
disableRollbackFlagsPref: boolean;
13+
}
14+
15+
/**
16+
* Interface representing the structure of query results from OmniInteractionConfig
17+
*
18+
* @interface QueryResult
19+
* @property {string} DeveloperName - Name of the configuration
20+
* @property {string} Value - Value of the configuration
21+
* @property {number} totalSize - Total number of records returned
22+
* @property {boolean} done - Whether the query is complete
23+
* @property {Array<{attributes: {type: string, url: string}, DeveloperName: string, Value: string}>} records - Array of query result records
24+
*/
25+
interface QueryResult {
26+
DeveloperName: string;
27+
Value: string;
28+
totalSize: number;
29+
done: boolean;
30+
records: Array<{
31+
attributes: {
32+
type: string;
33+
url: string;
34+
};
35+
DeveloperName: string;
36+
Value: string;
37+
}>;
38+
}
39+
40+
/**
41+
* Class to manage OmniStudio organization preferences
42+
*
43+
* @class OrgPreferences
44+
* @description Provides functionality to enable OmniStudio preferences and check rollback flags
45+
*/
46+
export class OrgPreferences {
47+
/**
48+
* List of rollback flags to check in OmniInteractionConfig
49+
*
50+
* @private
51+
* @static
52+
* @readonly
53+
* @type {string[]}
54+
*/
55+
private static readonly ROLLBACK_FLAGS: string[] = ['RollbackIPChanges', 'RollbackDRChanges', 'RollbackOSChanges'];
56+
57+
/**
58+
* Enables the disableRollbackFlagsPref setting in OmniStudio
59+
*
60+
* @public
61+
* @static
62+
* @async
63+
* @param {Connection} connection - Salesforce connection instance
64+
* @throws {Error} If enabling the preference fails
65+
* @returns {Promise<void>}
66+
*/
67+
public static async enableOmniPreferences(connection: Connection): Promise<void> {
68+
try {
69+
await connection.metadata.update('OmniStudioSettings', [
70+
{
71+
fullName: 'OmniStudio',
72+
disableRollbackFlagsPref: true,
73+
} as OmniStudioSettingsMetadata,
74+
]);
75+
} catch (error) {
76+
throw new Error(
77+
`Failed to enable disableRollbackFlagsPref: ${error instanceof Error ? error.message : String(error)}`
78+
);
79+
}
80+
}
81+
82+
/**
83+
* Checks which rollback flags are enabled in OmniInteractionConfig
84+
*
85+
* @public
86+
* @static
87+
* @async
88+
* @param {Connection} connection - Salesforce connection instance
89+
* @throws {Error} If checking rollback flags fails
90+
* @returns {Promise<string[]>} Array of enabled rollback flag names
91+
*/
92+
public static async checkRollbackFlags(connection: Connection): Promise<string[]> {
93+
try {
94+
const result = await connection.query<QueryResult>(
95+
`SELECT DeveloperName, Value FROM OmniInteractionConfig WHERE DeveloperName IN ('${this.ROLLBACK_FLAGS.join(
96+
"','"
97+
)}')`
98+
);
99+
const enabledFlags: string[] = [];
100+
for (const record of result.records) {
101+
if (record.Value === 'true') {
102+
enabledFlags.push(record.DeveloperName);
103+
}
104+
}
105+
return enabledFlags;
106+
} catch (error) {
107+
throw new Error(`Failed to check rollback flags: ${error instanceof Error ? error.message : String(error)}`);
108+
}
109+
}
110+
}

src/utils/resultsbuilder/assessmentReporter.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { ReportHeaderFormat } from '../reportGenerator/reportInterfaces';
77
import { OmnistudioOrgDetails } from '../orgUtils';
88
import { Constants } from '../constants/stringContants';
99
import { pushAssestUtilites } from '../file/fileUtil';
10+
import { OrgPreferences } from '../orgpreferences';
1011
import { OSAssessmentReporter } from './OSAssessmentReporter';
1112
import { ApexAssessmentReporter } from './ApexAssessmentReporter';
1213
import { IPAssessmentReporter } from './IPAssessmentReporter';
@@ -116,6 +117,7 @@ export class AssessmentReporter {
116117
// LWCAssessmentReporter.generateLwcAssesment(result.lwcAssessmentInfos, instanceUrl, orgDetails)
117118
// );
118119
// }
120+
119121
const nameUrls = [
120122
{
121123
name: 'omnscript assessment report',
@@ -143,6 +145,17 @@ export class AssessmentReporter {
143145
// location: 'lwc_assessment.html',
144146
// },
145147
];
148+
149+
// Check rollback flags
150+
const enabledFlags = omnistudioOrgDetails.rollbackFlags || [];
151+
if (enabledFlags.length > 0) {
152+
const rollbackFlagsReportPath = basePath + '/rollback_flags_report.html';
153+
this.createDocument(rollbackFlagsReportPath, this.generateRollbackFlagsReport(enabledFlags));
154+
nameUrls.push({
155+
name: 'Rollback Flags Report',
156+
location: 'rollback_flags_report.html',
157+
});
158+
}
146159

147160
await this.createMasterDocument(nameUrls, basePath);
148161
pushAssestUtilites('javascripts', basePath);
@@ -287,4 +300,18 @@ export class AssessmentReporter {
287300
</div>`;
288301
return tableBody;
289302
}
303+
private static generateRollbackFlagsReport(enabledFlags: string[]): string {
304+
return `
305+
<div class="slds-box slds-theme_warning" style="margin-bottom: 20px;">
306+
<div class="slds-text-heading_medium slds-m-bottom_small">⚠️ Warning: Rollback Flags Enabled</div>
307+
<p>The following rollback flags are currently enabled and will be disabled during migration:</p>
308+
<ul class="slds-m-top_small">
309+
${enabledFlags.map((flag) => `<li>${flag}</li>`).join('')}
310+
</ul>
311+
<p class="slds-m-top_small">
312+
<strong>Note:</strong> These flags will not be supported after migration. For assistance, please contact support.
313+
</p>
314+
</div>
315+
`;
316+
}
290317
}

test/utils/orgpreferences.test.ts

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { expect } from '@salesforce/command/lib/test';
2+
import { Connection } from '@salesforce/core';
3+
import sinon = require('sinon');
4+
import { OrgPreferences } from '../../src/utils/orgpreferences';
5+
6+
describe('OrgPreferences', () => {
7+
let connection: Connection;
8+
let sandbox: sinon.SinonSandbox;
9+
10+
beforeEach(() => {
11+
sandbox = sinon.createSandbox();
12+
connection = {
13+
metadata: {
14+
update: sandbox.stub(),
15+
},
16+
query: sandbox.stub(),
17+
} as unknown as Connection;
18+
});
19+
20+
afterEach(() => {
21+
sandbox.restore();
22+
});
23+
24+
describe('enableOmniPreferences', () => {
25+
it('should successfully enable OmniStudio preferences', async () => {
26+
// Arrange
27+
const metadataUpdateStub = sandbox.stub().resolves();
28+
connection.metadata.update = metadataUpdateStub;
29+
30+
// Act
31+
await OrgPreferences.enableOmniPreferences(connection);
32+
33+
// Assert
34+
expect(metadataUpdateStub.calledOnce).to.be.true;
35+
expect(metadataUpdateStub.firstCall.args[0]).to.equal('OmniStudioSettings');
36+
expect(metadataUpdateStub.firstCall.args[1]).to.deep.equal([
37+
{
38+
fullName: 'OmniStudio',
39+
disableRollbackFlagsPref: true,
40+
},
41+
]);
42+
});
43+
44+
it('should throw error when enabling preferences fails', async () => {
45+
// Arrange
46+
const error = new Error('Failed to update metadata');
47+
connection.metadata.update = sandbox.stub().rejects(error);
48+
49+
// Act & Assert
50+
try {
51+
await OrgPreferences.enableOmniPreferences(connection);
52+
expect.fail('Expected an error to be thrown');
53+
} catch (err: unknown) {
54+
if (err instanceof Error) {
55+
expect(err.message).to.equal('Failed to enable disableRollbackFlagsPref: Failed to update metadata');
56+
} else {
57+
expect.fail('Expected an Error object');
58+
}
59+
}
60+
});
61+
});
62+
63+
describe('checkRollbackFlags', () => {
64+
it('should return empty array when no flags are enabled', async () => {
65+
// Arrange
66+
const queryResult = {
67+
records: [
68+
{ DeveloperName: 'RollbackIPChanges', Value: 'false' },
69+
{ DeveloperName: 'RollbackDRChanges', Value: 'false' },
70+
{ DeveloperName: 'RollbackOSChanges', Value: 'false' },
71+
],
72+
};
73+
const queryStub = sandbox.stub().resolves(queryResult);
74+
connection.query = queryStub;
75+
76+
// Act
77+
const result = await OrgPreferences.checkRollbackFlags(connection);
78+
79+
// Assert
80+
expect(result).to.be.an('array').that.is.empty;
81+
expect(queryStub.calledOnce).to.be.true;
82+
expect(queryStub.firstCall.args[0]).to.include('SELECT DeveloperName, Value FROM OmniInteractionConfig');
83+
});
84+
85+
it('should return array of enabled flags', async () => {
86+
// Arrange
87+
const queryResult = {
88+
records: [
89+
{ DeveloperName: 'RollbackIPChanges', Value: 'true' },
90+
{ DeveloperName: 'RollbackDRChanges', Value: 'false' },
91+
{ DeveloperName: 'RollbackOSChanges', Value: 'true' },
92+
],
93+
};
94+
const queryStub = sandbox.stub().resolves(queryResult);
95+
connection.query = queryStub;
96+
97+
// Act
98+
const result = await OrgPreferences.checkRollbackFlags(connection);
99+
100+
// Assert
101+
expect(result).to.deep.equal(['RollbackIPChanges', 'RollbackOSChanges']);
102+
expect(queryStub.calledOnce).to.be.true;
103+
});
104+
105+
it('should throw error when checking flags fails', async () => {
106+
// Arrange
107+
const error = new Error('Failed to query');
108+
connection.query = sandbox.stub().rejects(error);
109+
110+
// Act & Assert
111+
try {
112+
await OrgPreferences.checkRollbackFlags(connection);
113+
expect.fail('Expected an error to be thrown');
114+
} catch (err: unknown) {
115+
if (err instanceof Error) {
116+
expect(err.message).to.equal('Failed to check rollback flags: Failed to query');
117+
} else {
118+
expect.fail('Expected an Error object');
119+
}
120+
}
121+
});
122+
});
123+
});

0 commit comments

Comments
 (0)