Skip to content

Commit 0a5efa3

Browse files
committed
test(schematics): update tests for v49 as per the new data model
1 parent cb2afc1 commit 0a5efa3

16 files changed

+671
-2
lines changed

projects/element-ng/schematics/migrations/data/migration-test-data.ts

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import {
88
ComponentNamesInstruction,
99
ElementMigrationData,
1010
ElementSelectorInstruction,
11+
InputNamesInstruction,
1112
OutputNamesInstruction,
13+
PatternReplacementInstruction,
1214
SymbolRemovalInstruction
1315
} from './index.js';
1416

@@ -86,6 +88,22 @@ const COMPONENT_NAMES_MIGRATION: ComponentNamesInstruction[] = [
8688
{
8789
module: /@(siemens|simpl)\/dashboards-ng/,
8890
symbolRenamings: [{ replace: 'CONFIG_TOKEN', replaceWith: 'SI_DASHBOARD_CONFIGURATION' }]
91+
},
92+
{
93+
module: /@(siemens|simpl)\/element-ng(\/toast-notification)?/,
94+
symbolRenamings: [{ replace: 'ToastStateName', replaceWith: 'StatusType' }],
95+
toModule: '@siemens/element-ng/common'
96+
},
97+
{
98+
module: /@(siemens|simpl)\/element-ng(\/(info-page|unauthorized-page))?/,
99+
symbolRenamings: [
100+
{ replace: 'SiUnauthorizedPageComponent', replaceWith: 'SiInfoPageComponent' }
101+
],
102+
toModule: '@siemens/element-ng/info-page'
103+
},
104+
{
105+
module: /@(siemens|simpl)\/element-ng(\/filtered-search)?/,
106+
symbolRenamings: [{ replace: 'Criterion', replaceWith: 'CriterionValue' }]
89107
}
90108
];
91109

@@ -103,7 +121,16 @@ const ELEMENT_SELECTORS_MIGRATION: ElementSelectorInstruction[] = [
103121
// next to current
104122
{ replace: 'si-icon-next', replaceWith: 'si-icon' },
105123
{ replace: 'si-tabset-next', replaceWith: 'si-tabset' },
106-
{ replace: 'si-tab-next', replaceWith: 'si-tab' }
124+
{ replace: 'si-tab-next', replaceWith: 'si-tab' },
125+
// v48 to v49
126+
{
127+
replace: 'si-unauthorized-page',
128+
replaceWith: 'si-info-page',
129+
defaultAttributes: [
130+
{ name: 'icon', value: 'element-warning-filled' },
131+
{ name: 'iconColor', value: 'status-warning' }
132+
]
133+
}
107134
];
108135

109136
const SYMBOL_REMOVALS_MIGRATION: SymbolRemovalInstruction[] = [
@@ -169,6 +196,93 @@ const OUTPUT_NAMES_MIGRATION: OutputNamesInstruction[] = [
169196
}
170197
];
171198

199+
const INPUT_NAMES_MIGRATION: InputNamesInstruction[] = [
200+
// v48 to v49
201+
{
202+
module: /@(siemens|simpl)\/element-ng/,
203+
elementSelector: 'si-filtered-search',
204+
apiMappings: [{ replace: 'readonly', replaceWith: 'disabled' }]
205+
},
206+
{
207+
module: /@(siemens|simpl)\/charts-ng/,
208+
elementSelector: 'si-chart-gauge',
209+
apiMappings: [
210+
{ replace: 'numberOfDecimals', replaceWith: ['minNumberOfDecimals', 'maxNumberOfDecimals'] }
211+
]
212+
},
213+
{
214+
module: /@(siemens|simpl)\/element-ng(\/(info-page|unauthorized-page))?/,
215+
elementSelector: 'si-unauthorized-page',
216+
apiMappings: [
217+
{ replace: 'heading', replaceWith: 'titleText' },
218+
{ replace: 'subHeading', replaceWith: 'copyText' },
219+
{ replace: 'description', replaceWith: 'instructions' }
220+
]
221+
}
222+
];
223+
224+
const PATTERN_REPLACEMENTS_MIGRATION: PatternReplacementInstruction[] = [
225+
{
226+
module: /@(siemens|simpl)\/element-ng(\/filtered-search)?/,
227+
requiresSymbols: ['Criterion', 'CriterionValue', 'CriterionDefinition'],
228+
patterns: [
229+
// Union types: CriterionValue | Criterion → CriterionValue
230+
{ pattern: /\bCriterionValue\s*\|\s*Criterion\b/g, replacement: 'CriterionValue' },
231+
{ pattern: /\bCriterion\s*\|\s*CriterionValue\b/g, replacement: 'CriterionValue' },
232+
// Array union types: Criterion[] | CriterionDefinition[] → CriterionDefinition[]
233+
{
234+
pattern: /\bCriterion\[\]\s*\|\s*CriterionDefinition\[\]/g,
235+
replacement: 'CriterionDefinition[]'
236+
},
237+
{
238+
pattern: /\bCriterionDefinition\[\]\s*\|\s*Criterion\[\]/g,
239+
replacement: 'CriterionDefinition[]'
240+
},
241+
// Intersection types: CriterionValue & Criterion → CriterionValue
242+
{ pattern: /\bCriterionValue\s*&\s*Criterion\b/g, replacement: 'CriterionValue' },
243+
{ pattern: /\bCriterion\s*&\s*CriterionValue\b/g, replacement: 'CriterionValue' },
244+
// Array intersection types: Criterion[] & CriterionDefinition[] → CriterionDefinition[]
245+
{
246+
pattern: /\bCriterion\[\]\s*&\s*CriterionDefinition\[\]/g,
247+
replacement: 'CriterionDefinition[]'
248+
},
249+
{
250+
pattern: /\bCriterionDefinition\[\]\s*&\s*Criterion\[\]/g,
251+
replacement: 'CriterionDefinition[]'
252+
}
253+
]
254+
},
255+
{
256+
module: /@(siemens|simpl)\/element-ng(\/resize-observer)?/,
257+
requiresSymbols: ['SiResponsiveContainerDirective'],
258+
patterns: [
259+
{ pattern: /\.isXs\b/g, replacement: '.xs()' },
260+
{ pattern: /\.isSm\b/g, replacement: '.sm()' },
261+
{ pattern: /\.isMd\b/g, replacement: '.md()' },
262+
{ pattern: /\.isLg\b/g, replacement: '.lg()' },
263+
{ pattern: /\.isXl\b/g, replacement: '.xl()' },
264+
{ pattern: /\.isXxl\b/g, replacement: '.xxl()' }
265+
]
266+
},
267+
// v48 to v49 - Modal initialState → inputValues
268+
// Only matches initialState within .show() calls
269+
{
270+
module: /@(siemens|simpl)\/element-ng(\/modal)?/,
271+
requiresSymbols: ['SiModalService'],
272+
patterns: [
273+
// Matches: .show(Component, { initialState: ... })
274+
// Pattern breakdown:
275+
// $1 = '.show(Component, { ' up to the word boundary before initialState
276+
// $2 = 'initialState' (the property name we're replacing)
277+
// $3 = ':' (the colon after the property)
278+
{
279+
pattern: /(\bshow\([^)]*,\s*\{[^}]*\b)(initialState)(\s*:)/gs,
280+
replacement: '$1inputValues$3'
281+
}
282+
]
283+
}
284+
];
285+
172286
/**
173287
* Stable migration data for testing.
174288
* This data is frozen and used for testing to ensure test stability.
@@ -179,5 +293,7 @@ export const getElementMigrationTestData = (): ElementMigrationData => ({
179293
componentNameChanges: COMPONENT_NAMES_MIGRATION,
180294
elementSelectorChanges: ELEMENT_SELECTORS_MIGRATION,
181295
symbolRemovalChanges: SYMBOL_REMOVALS_MIGRATION,
182-
outputNameChanges: OUTPUT_NAMES_MIGRATION
296+
outputNameChanges: OUTPUT_NAMES_MIGRATION,
297+
inputNameChanges: INPUT_NAMES_MIGRATION,
298+
patternReplacementsChanges: PATTERN_REPLACEMENTS_MIGRATION
183299
});

projects/element-ng/schematics/migrations/element-migration/element-migration.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,32 @@ describe('to legacy migration', () => {
146146
it('should remove the deprecated api from module based accordion', async () => {
147147
await checkTemplateMigration(['module-based.accordion-inline-template.ts']);
148148
});
149+
150+
it('should migrate ToastStateName to StatusType', async () => {
151+
await checkTemplateMigration(['toast-state-name.ts']);
152+
});
153+
154+
it('should migrate filtered search readonly attribute in inline templates', async () => {
155+
await checkTemplateMigration(['filtered-search-inline-readonly.ts']);
156+
});
157+
158+
it('should migrate Criterion types to CriterionValue and CriterionDefinition', async () => {
159+
await checkTemplateMigration(['filtered-search-criterion-types.ts']);
160+
});
161+
162+
it('should migrate unauthorized page component in inline templates', async () => {
163+
await checkTemplateMigration(['unauthorized-page-inline.ts']);
164+
});
165+
166+
it('should migrate modal initialState to inputValues', async () => {
167+
await checkTemplateMigration(['modal-initial-state.ts']);
168+
});
169+
170+
it('should split numberOfDecimals into minNumberOfDecimals and maxNumberOfDecimals', async () => {
171+
await checkTemplateMigration(['chart-gauge-decimals.ts']);
172+
});
173+
174+
it('should migrate resize observer properties to signal calls', async () => {
175+
await checkTemplateMigration(['resize-observer.ts']);
176+
});
149177
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Component } from '@angular/core';
2+
import { SiChartGaugeComponent } from '@siemens/charts-ng/gauge';
3+
4+
@Component({
5+
selector: 'app-dashboard',
6+
standalone: true,
7+
template: `
8+
<si-chart-gauge
9+
[value]="75"
10+
[numberOfDecimals]="2"
11+
[min]="0"
12+
[max]="100"
13+
></si-chart-gauge>
14+
15+
<si-chart-gauge [numberOfDecimals]="0"></si-chart-gauge>
16+
17+
<si-chart-gauge
18+
[value]="gaugeValue"
19+
[numberOfDecimals]="decimals"
20+
></si-chart-gauge>
21+
`,
22+
imports: [SiChartGaugeComponent]
23+
})
24+
export class DashboardComponent {
25+
gaugeValue = 85;
26+
decimals = 1;
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Component } from '@angular/core';
2+
import { SiChartGaugeComponent } from '@siemens/charts-ng/gauge';
3+
4+
@Component({
5+
selector: 'app-dashboard',
6+
standalone: true,
7+
template: `
8+
<si-chart-gauge
9+
[value]="75"
10+
[minNumberOfDecimals]="2" [maxNumberOfDecimals]="2"
11+
[min]="0"
12+
[max]="100"
13+
></si-chart-gauge>
14+
15+
<si-chart-gauge [minNumberOfDecimals]="0" [maxNumberOfDecimals]="0"></si-chart-gauge>
16+
17+
<si-chart-gauge
18+
[value]="gaugeValue"
19+
[minNumberOfDecimals]="decimals" [maxNumberOfDecimals]="decimals"
20+
></si-chart-gauge>
21+
`,
22+
imports: [SiChartGaugeComponent]
23+
})
24+
export class DashboardComponent {
25+
gaugeValue = 85;
26+
decimals = 1;
27+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Copyright (c) Siemens 2016 - 2025
3+
* SPDX-License-Identifier: MIT
4+
*/
5+
import { Component, input } from '@angular/core';
6+
import { Observable } from 'rxjs';
7+
import {
8+
CriterionValue,
9+
CriterionDefinition,
10+
SearchCriteria,
11+
SiFilteredSearchModule
12+
} from '@siemens/element-ng/filtered-search';
13+
14+
@Component({
15+
selector: 'app-criterion-types-test',
16+
template: `
17+
<si-filtered-search
18+
[criteria]="criteria()"
19+
[lazyCriterionProvider]="lazyCriterionProvider()"
20+
(search)="onSearch($event)">
21+
</si-filtered-search>
22+
`,
23+
imports: [SiFilteredSearchModule],
24+
standalone: true
25+
})
26+
export class CriterionTypesTestComponent {
27+
// Test input with CriterionDefinition[]
28+
criteria = input<CriterionDefinition[]>([]);
29+
30+
// Test input with function returning Observable<CriterionDefinition[]>
31+
lazyCriterionProvider = input<
32+
(typed: string, searchCriteria?: SearchCriteria) => Observable<CriterionDefinition[]>
33+
>();
34+
35+
// Test method parameter and variable declaration
36+
onSearch(searchCriteria: SearchCriteria): void {
37+
const criterionValues: CriterionValue[] = searchCriteria.criteria;
38+
console.log(criterionValues);
39+
}
40+
41+
// Test method return type
42+
getCriteria(): CriterionDefinition[] {
43+
return [];
44+
}
45+
46+
// Test with arrays
47+
processCriteria(items: CriterionValue[]): void {
48+
const filtered: CriterionValue[] = items.filter(c => c.id !== '');
49+
}
50+
51+
// Test in generic type
52+
handleData(data: Array<CriterionValue>): CriterionValue[] {
53+
return data;
54+
}
55+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Copyright (c) Siemens 2016 - 2025
3+
* SPDX-License-Identifier: MIT
4+
*/
5+
import { Component } from '@angular/core';
6+
import { SiFilteredSearchModule } from '@siemens/element-ng/filtered-search';
7+
8+
@Component({
9+
selector: 'app-inline-readonly-test',
10+
template: `
11+
<div>
12+
<si-filtered-search [disabled]="true"></si-filtered-search>
13+
<si-filtered-search [disabled]="editMode === false" [criteria]="criteria"></si-filtered-search>
14+
<si-filtered-search
15+
[disabled]="isDisabled"
16+
[placeholder]="'Enter search criteria'"
17+
(search)="onSearch($event)">
18+
</si-filtered-search>
19+
</div>
20+
`,
21+
imports: [SiFilteredSearchModule],
22+
standalone: true
23+
})
24+
export class InlineReadonlyTestComponent {
25+
editMode = false;
26+
isDisabled = true;
27+
criteria = [];
28+
29+
onSearch(event: any): void {
30+
console.log(event);
31+
}
32+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Component } from '@angular/core';
2+
import { SiModalService } from '@siemens/element-ng/modal';
3+
import { MyModalComponent } from './my-modal.component';
4+
5+
@Component({
6+
selector: 'app-test',
7+
standalone: true,
8+
template: `<button (click)="openModal()">Open</button>`
9+
})
10+
export class TestComponent {
11+
constructor(private modalService: SiModalService) {}
12+
13+
openModal() {
14+
this.modalService.show(MyModalComponent, {
15+
inputValues: { title: 'Hello', data: { id: 1 } }
16+
});
17+
}
18+
19+
openModalWithOptions() {
20+
const modalRef = this.modalService.show(MyModalComponent, {
21+
inputValues: {
22+
title: 'Edit Item',
23+
item: { name: 'Test', value: 100 }
24+
},
25+
keyboard: false
26+
});
27+
return modalRef;
28+
}
29+
30+
openModalInline() {
31+
return this.modalService.show(MyModalComponent, { inputValues: { mode: 'create' } });
32+
}
33+
34+
openModalMultiline() {
35+
this.modalService.show(MyModalComponent, {
36+
inputValues: {
37+
user: { name: 'John', email: 'john@example.com' },
38+
permissions: ['read', 'write'],
39+
config: { theme: 'dark' }
40+
}
41+
});
42+
}
43+
}

0 commit comments

Comments
 (0)