Skip to content

Commit 310de73

Browse files
committed
fix: flexipage issues
1 parent 3f73508 commit 310de73

File tree

5 files changed

+198
-24
lines changed

5 files changed

+198
-24
lines changed

src/migration/related/FlexipageMigration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ export class FlexipageMigration extends BaseRelatedObjectMigration {
192192
Logger.logVerbose(this.messages.getMessage('updatedModifiedContent', [filePath]));
193193
}
194194

195-
const diff = new FileDiffUtil().getFileDiff(fileName, fileContent, modifiedContent);
195+
const diff = new FileDiffUtil().getXMLDiff(fileContent, modifiedContent);
196196
Logger.logVerbose(this.messages.getMessage('generatedDiffForFile', [fileName]));
197197

198198
return {

src/utils/flexipage/flexiPageTransformer.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ const targetComponentNameOS = 'runtime_omnistudio:omniscript';
2121
/** Target identifier after transformation */
2222
const targetIdentifierOS = 'runtime_omnistudio_omniscript';
2323

24+
let osSeq = 1;
25+
let fcSeq = 1;
26+
2427
const targetComponentNameFlexCard = 'runtime_omnistudio:flexcard';
2528
const targetIdentifierFlexCard = 'runtime_omnistudio_flexcard';
2629

@@ -46,6 +49,9 @@ export function transformFlexipageBundle(
4649
namespace: string,
4750
mode: 'assess' | 'migrate'
4851
): Flexipage | boolean {
52+
osSeq = 1;
53+
fcSeq = 1;
54+
4955
const bundle: Flexipage = JSON.parse(JSON.stringify(ogBundle)) as Flexipage;
5056
let changes = false;
5157

@@ -142,7 +148,7 @@ function createNewPropsForOmniScript(
142148

143149
return {
144150
componentName: targetComponentNameOS,
145-
identifier: targetIdentifierOS,
151+
identifier: `${targetIdentifierOS}${osSeq++}`,
146152
props: newProps,
147153
};
148154
}
@@ -173,7 +179,7 @@ function createNewPropsForFlexCard(
173179

174180
return {
175181
componentName: targetComponentNameFlexCard,
176-
identifier: targetIdentifierFlexCard,
182+
identifier: `${targetIdentifierFlexCard}${fcSeq++}`,
177183
props: newProps,
178184
};
179185
}

src/utils/lwcparser/fileutils/FileDiffUtil.ts

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,25 @@ export class FileDiffUtil {
4646
let linecount = 0;
4747
for (const { old: original, new: modified } of diffArray) {
4848
if (original === modified) {
49-
result += `<div style="color: black;">• Line ${modifiedLine}: ${this.escapeHtml(original)}</div>`;
49+
result += `<div style="color: black;">• Line ${modifiedLine}: ${this.escapeHtml(original).replace(
50+
/ /g,
51+
'&nbsp;'
52+
)}</div>`;
5053
modifiedLine++;
5154
originalLine++;
5255
linecount++;
5356
} else if (original !== null && modified === null) {
54-
result += `<div style="color: red;">- Line ${originalLine}: ${this.escapeHtml(original)}</div>`;
57+
result += `<div style="color: red;">- Line ${originalLine}: ${this.escapeHtml(original).replace(
58+
/ /g,
59+
'&nbsp;'
60+
)}</div>`;
5561
originalLine++;
5662
linecount++;
5763
} else if (original === null && modified !== null) {
58-
result += `<div style="color: green;">+ Line ${modifiedLine}: ${this.escapeHtml(modified)}</div>`;
64+
result += `<div style="color: green;">+ Line ${modifiedLine}: ${this.escapeHtml(modified).replace(
65+
/ /g,
66+
'&nbsp;'
67+
)}</div>`;
5968
modifiedLine++;
6069
linecount++;
6170
}
@@ -149,24 +158,23 @@ export class FileDiffUtil {
149158
}
150159

151160
public getXMLDiff(originalFileContent: string, modifiedFileContent: string): DiffPair[] {
152-
const diff = diffLines(originalFileContent, modifiedFileContent, { newlineIsToken: true });
153-
return diff.map((line): DiffPair => {
154-
if (line.added) {
155-
return {
156-
old: null,
157-
new: line.value,
158-
};
159-
} else if (line.removed) {
160-
return {
161-
old: line.value,
162-
new: null,
163-
};
161+
const diff = diffLines(originalFileContent, modifiedFileContent, { stripTrailingCr: true });
162+
const result: DiffPair[] = [];
163+
for (const block of diff) {
164+
if (block.added) {
165+
block.value.split('\n').forEach((line) => {
166+
result.push({ old: null, new: line });
167+
});
168+
} else if (block.removed) {
169+
block.value.split('\n').forEach((line) => {
170+
result.push({ old: line, new: null });
171+
});
164172
} else {
165-
return {
166-
old: line.value,
167-
new: line.value,
168-
};
173+
block.value.split('\n').forEach((line) => {
174+
result.push({ old: line, new: line });
175+
});
169176
}
170-
}) as DiffPair[];
177+
}
178+
return result;
171179
}
172180
}

test/migration/related/FlexipageMigration.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ interface MockXmlUtil {
2929

3030
interface MockFileDiffUtil {
3131
getFileDiff: sinon.SinonStub;
32+
getXMLDiff: sinon.SinonStub;
3233
}
3334

3435
interface MockTransformFlexipageBundle extends sinon.SinonStub {
@@ -104,6 +105,7 @@ describe('FlexipageMigration', () => {
104105
// Mock FileDiffUtil
105106
mockFileDiffUtil = {
106107
getFileDiff: sandbox.stub().returns('mock-diff'),
108+
getXMLDiff: sandbox.stub().returns('mock-diff'),
107109
};
108110

109111
// Mock transformFlexipageBundle

test/utils/flexipage/flexiPageTransformer.test.ts

Lines changed: 159 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ describe('transformFlexipageBundle', () => {
7070
const changed = result as Flexipage;
7171
const item = changed.flexiPageRegions[0].itemInstances[0];
7272
expect(item.componentInstance.componentName).to.equal(targetComponentName);
73-
expect(item.componentInstance.identifier).to.equal(targetIdentifier);
73+
expect(item.componentInstance.identifier).to.equal(`${targetIdentifier}1`);
7474
// Should not have 'target' property
7575
expect(item.componentInstance.componentInstanceProperties.find((p) => p.name === 'target')).to.be.undefined;
7676
// Should have new properties
@@ -129,4 +129,162 @@ describe('transformFlexipageBundle', () => {
129129
transformFlexipageBundle(bundle, namespace, 'migrate');
130130
expect(JSON.stringify(bundle)).to.equal(original);
131131
});
132+
133+
it('generates sequential IDs for multiple OmniScript components on the same page', () => {
134+
// Mock StorageUtil
135+
const mockStorage = {
136+
osStorage: new Map([
137+
['subtype1', { type: 'OSForCustomLWC', subtype: 'OSForCustomLWC', language: 'English', isDuplicate: false }],
138+
['subtype2', { type: 'OSForCustomLWC', subtype: 'OSForCustomLWC', language: 'English', isDuplicate: false }],
139+
['subtype3', { type: 'OSForCustomLWC', subtype: 'OSForCustomLWC', language: 'English', isDuplicate: false }],
140+
]),
141+
fcStorage: new Map(),
142+
};
143+
sandbox.stub(StorageUtil, 'getOmnistudioMigrationStorage').returns(mockStorage);
144+
145+
const bundle: Flexipage = {
146+
flexiPageRegions: [
147+
makeRegion([
148+
makeItemInstance([{ name: 'target', value: 'type:subtype1' }]),
149+
makeItemInstance([{ name: 'target', value: 'type:subtype2' }]),
150+
makeItemInstance([{ name: 'target', value: 'type:subtype3' }]),
151+
]),
152+
],
153+
};
154+
const result = transformFlexipageBundle(bundle, namespace, 'migrate');
155+
expect(result).to.not.equal(false);
156+
const changed = result as Flexipage;
157+
158+
// Check sequential IDs
159+
expect(changed.flexiPageRegions[0].itemInstances[0].componentInstance.identifier).to.equal(`${targetIdentifier}1`);
160+
expect(changed.flexiPageRegions[0].itemInstances[1].componentInstance.identifier).to.equal(`${targetIdentifier}2`);
161+
expect(changed.flexiPageRegions[0].itemInstances[2].componentInstance.identifier).to.equal(`${targetIdentifier}3`);
162+
});
163+
164+
it('generates sequential IDs for multiple FlexCard components on the same page', () => {
165+
// Mock StorageUtil
166+
const mockStorage = {
167+
osStorage: new Map(),
168+
fcStorage: new Map([
169+
['card1', { name: 'Card1', isDuplicate: false }],
170+
['card2', { name: 'Card2', isDuplicate: false }],
171+
['card3', { name: 'Card3', isDuplicate: false }],
172+
]),
173+
};
174+
sandbox.stub(StorageUtil, 'getOmnistudioMigrationStorage').returns(mockStorage);
175+
176+
const bundle: Flexipage = {
177+
flexiPageRegions: [
178+
makeRegion([
179+
makeItemInstance([{ name: 'target', value: 'type:cfcard1' }]),
180+
makeItemInstance([{ name: 'target', value: 'type:cfcard2' }]),
181+
makeItemInstance([{ name: 'target', value: 'type:cfcard3' }]),
182+
]),
183+
],
184+
};
185+
const result = transformFlexipageBundle(bundle, namespace, 'migrate');
186+
expect(result).to.not.equal(false);
187+
const changed = result as Flexipage;
188+
189+
// Check sequential IDs for FlexCards
190+
expect(changed.flexiPageRegions[0].itemInstances[0].componentInstance.identifier).to.equal(
191+
'runtime_omnistudio_flexcard1'
192+
);
193+
expect(changed.flexiPageRegions[0].itemInstances[1].componentInstance.identifier).to.equal(
194+
'runtime_omnistudio_flexcard2'
195+
);
196+
expect(changed.flexiPageRegions[0].itemInstances[2].componentInstance.identifier).to.equal(
197+
'runtime_omnistudio_flexcard3'
198+
);
199+
});
200+
201+
it('generates sequential IDs for mixed OmniScript and FlexCard components on the same page', () => {
202+
// Mock StorageUtil
203+
const mockStorage = {
204+
osStorage: new Map([
205+
['subtype1', { type: 'OSForCustomLWC', subtype: 'OSForCustomLWC', language: 'English', isDuplicate: false }],
206+
['subtype2', { type: 'OSForCustomLWC', subtype: 'OSForCustomLWC', language: 'English', isDuplicate: false }],
207+
]),
208+
fcStorage: new Map([
209+
['card1', { name: 'Card1', isDuplicate: false }],
210+
['card2', { name: 'Card2', isDuplicate: false }],
211+
]),
212+
};
213+
sandbox.stub(StorageUtil, 'getOmnistudioMigrationStorage').returns(mockStorage);
214+
215+
const bundle: Flexipage = {
216+
flexiPageRegions: [
217+
makeRegion([
218+
makeItemInstance([{ name: 'target', value: 'type:subtype1' }]),
219+
makeItemInstance([{ name: 'target', value: 'type:cfcard1' }]),
220+
makeItemInstance([{ name: 'target', value: 'type:subtype2' }]),
221+
makeItemInstance([{ name: 'target', value: 'type:cfcard2' }]),
222+
]),
223+
],
224+
};
225+
const result = transformFlexipageBundle(bundle, namespace, 'migrate');
226+
expect(result).to.not.equal(false);
227+
const changed = result as Flexipage;
228+
229+
// Check sequential IDs for mixed components
230+
expect(changed.flexiPageRegions[0].itemInstances[0].componentInstance.identifier).to.equal(`${targetIdentifier}1`);
231+
expect(changed.flexiPageRegions[0].itemInstances[1].componentInstance.identifier).to.equal(
232+
'runtime_omnistudio_flexcard1'
233+
);
234+
expect(changed.flexiPageRegions[0].itemInstances[2].componentInstance.identifier).to.equal(`${targetIdentifier}2`);
235+
expect(changed.flexiPageRegions[0].itemInstances[3].componentInstance.identifier).to.equal(
236+
'runtime_omnistudio_flexcard2'
237+
);
238+
});
239+
240+
it('resets sequence counters for different pages', () => {
241+
// Mock StorageUtil
242+
const mockStorage = {
243+
osStorage: new Map([
244+
['subtype1', { type: 'OSForCustomLWC', subtype: 'OSForCustomLWC', language: 'English', isDuplicate: false }],
245+
['subtype2', { type: 'OSForCustomLWC', subtype: 'OSForCustomLWC', language: 'English', isDuplicate: false }],
246+
]),
247+
fcStorage: new Map([
248+
['card1', { name: 'Card1', isDuplicate: false }],
249+
['card2', { name: 'Card2', isDuplicate: false }],
250+
]),
251+
};
252+
sandbox.stub(StorageUtil, 'getOmnistudioMigrationStorage').returns(mockStorage);
253+
254+
// First page
255+
const bundle1: Flexipage = {
256+
flexiPageRegions: [
257+
makeRegion([
258+
makeItemInstance([{ name: 'target', value: 'type:subtype1' }]),
259+
makeItemInstance([{ name: 'target', value: 'type:cfcard1' }]),
260+
]),
261+
],
262+
};
263+
const result1 = transformFlexipageBundle(bundle1, namespace, 'migrate');
264+
expect(result1).to.not.equal(false);
265+
const changed1 = result1 as Flexipage;
266+
267+
// Second page
268+
const bundle2: Flexipage = {
269+
flexiPageRegions: [
270+
makeRegion([
271+
makeItemInstance([{ name: 'target', value: 'type:subtype2' }]),
272+
makeItemInstance([{ name: 'target', value: 'type:cfcard2' }]),
273+
]),
274+
],
275+
};
276+
const result2 = transformFlexipageBundle(bundle2, namespace, 'migrate');
277+
expect(result2).to.not.equal(false);
278+
const changed2 = result2 as Flexipage;
279+
280+
// Check that sequence counters reset for second page
281+
expect(changed1.flexiPageRegions[0].itemInstances[0].componentInstance.identifier).to.equal(`${targetIdentifier}1`);
282+
expect(changed1.flexiPageRegions[0].itemInstances[1].componentInstance.identifier).to.equal(
283+
'runtime_omnistudio_flexcard1'
284+
);
285+
expect(changed2.flexiPageRegions[0].itemInstances[0].componentInstance.identifier).to.equal(`${targetIdentifier}1`);
286+
expect(changed2.flexiPageRegions[0].itemInstances[1].componentInstance.identifier).to.equal(
287+
'runtime_omnistudio_flexcard1'
288+
);
289+
});
132290
});

0 commit comments

Comments
 (0)