@dragonworks/ngx-dashboard-widgets 20.0.4 → 20.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ng-package.json +7 -0
- package/package.json +31 -42
- package/src/lib/arrow-widget/arrow-state-dialog.component.ts +187 -0
- package/src/lib/arrow-widget/arrow-widget.component.html +9 -0
- package/src/lib/arrow-widget/arrow-widget.component.scss +52 -0
- package/src/lib/arrow-widget/arrow-widget.component.ts +78 -0
- package/src/lib/arrow-widget/arrow-widget.metadata.ts +3 -0
- package/src/lib/clock-widget/analog-clock/analog-clock.component.html +66 -0
- package/src/lib/clock-widget/analog-clock/analog-clock.component.scss +103 -0
- package/src/lib/clock-widget/analog-clock/analog-clock.component.ts +120 -0
- package/src/lib/clock-widget/clock-state-dialog.component.ts +170 -0
- package/src/lib/clock-widget/clock-widget.component.html +16 -0
- package/src/lib/clock-widget/clock-widget.component.scss +160 -0
- package/src/lib/clock-widget/clock-widget.component.ts +87 -0
- package/src/lib/clock-widget/clock-widget.metadata.ts +42 -0
- package/src/lib/clock-widget/digital-clock/__tests__/digital-clock.component.spec.ts +276 -0
- package/src/lib/clock-widget/digital-clock/digital-clock.component.html +1 -0
- package/src/lib/clock-widget/digital-clock/digital-clock.component.scss +43 -0
- package/src/lib/clock-widget/digital-clock/digital-clock.component.ts +105 -0
- package/src/lib/directives/__tests__/responsive-text.directive.spec.ts +906 -0
- package/src/lib/directives/responsive-text.directive.ts +334 -0
- package/src/lib/label-widget/__tests__/label-widget.component.spec.ts +539 -0
- package/src/lib/label-widget/label-state-dialog.component.ts +385 -0
- package/src/lib/label-widget/label-widget.component.html +21 -0
- package/src/lib/label-widget/label-widget.component.scss +112 -0
- package/src/lib/label-widget/label-widget.component.ts +96 -0
- package/src/lib/label-widget/label-widget.metadata.ts +3 -0
- package/src/public-api.ts +7 -0
- package/tsconfig.lib.json +15 -0
- package/tsconfig.lib.prod.json +11 -0
- package/tsconfig.spec.json +14 -0
- package/fesm2022/dragonworks-ngx-dashboard-widgets.mjs +0 -1255
- package/fesm2022/dragonworks-ngx-dashboard-widgets.mjs.map +0 -1
- package/index.d.ts +0 -147
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { LabelWidgetComponent, LabelWidgetState } from '../label-widget.component';
|
|
3
|
+
|
|
4
|
+
describe('LabelWidgetComponent', () => {
|
|
5
|
+
let component: LabelWidgetComponent;
|
|
6
|
+
let fixture: ComponentFixture<LabelWidgetComponent>;
|
|
7
|
+
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
await TestBed.configureTestingModule({
|
|
10
|
+
imports: [LabelWidgetComponent]
|
|
11
|
+
})
|
|
12
|
+
.compileComponents();
|
|
13
|
+
|
|
14
|
+
fixture = TestBed.createComponent(LabelWidgetComponent);
|
|
15
|
+
component = fixture.componentInstance;
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
fixture.destroy();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should create', () => {
|
|
23
|
+
expect(component).toBeTruthy();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('Default State Serialization', () => {
|
|
27
|
+
it('should return complete default state with correct min/max font sizes', () => {
|
|
28
|
+
fixture.detectChanges();
|
|
29
|
+
|
|
30
|
+
const state = component.dashboardGetState();
|
|
31
|
+
|
|
32
|
+
expect(state).toEqual({
|
|
33
|
+
label: '',
|
|
34
|
+
fontSize: 16,
|
|
35
|
+
alignment: 'center',
|
|
36
|
+
fontWeight: 'normal',
|
|
37
|
+
opacity: 1,
|
|
38
|
+
hasBackground: true,
|
|
39
|
+
responsive: false,
|
|
40
|
+
minFontSize: 8,
|
|
41
|
+
maxFontSize: 64
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should have all required properties in default state', () => {
|
|
46
|
+
fixture.detectChanges();
|
|
47
|
+
|
|
48
|
+
const state = component.dashboardGetState();
|
|
49
|
+
|
|
50
|
+
expect(state.label).toBeDefined();
|
|
51
|
+
expect(state.fontSize).toBeDefined();
|
|
52
|
+
expect(state.alignment).toBeDefined();
|
|
53
|
+
expect(state.fontWeight).toBeDefined();
|
|
54
|
+
expect(state.opacity).toBeDefined();
|
|
55
|
+
expect(state.hasBackground).toBeDefined();
|
|
56
|
+
expect(state.responsive).toBeDefined();
|
|
57
|
+
expect(state.minFontSize).toBeDefined();
|
|
58
|
+
expect(state.maxFontSize).toBeDefined();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should use correct default values for new font size properties', () => {
|
|
62
|
+
fixture.detectChanges();
|
|
63
|
+
|
|
64
|
+
const state = component.dashboardGetState();
|
|
65
|
+
|
|
66
|
+
expect(state.minFontSize).toBe(8);
|
|
67
|
+
expect(state.maxFontSize).toBe(64);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('State Deserialization', () => {
|
|
72
|
+
it('should accept complete state object and preserve all properties', () => {
|
|
73
|
+
const inputState: LabelWidgetState = {
|
|
74
|
+
label: 'Test Label',
|
|
75
|
+
fontSize: 20,
|
|
76
|
+
alignment: 'left',
|
|
77
|
+
fontWeight: 'bold',
|
|
78
|
+
opacity: 0.8,
|
|
79
|
+
hasBackground: false,
|
|
80
|
+
responsive: true,
|
|
81
|
+
minFontSize: 10,
|
|
82
|
+
maxFontSize: 48
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
component.dashboardSetState(inputState);
|
|
86
|
+
fixture.detectChanges();
|
|
87
|
+
|
|
88
|
+
const retrievedState = component.dashboardGetState();
|
|
89
|
+
expect(retrievedState).toEqual(inputState);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should handle partial state objects and use defaults for missing properties', () => {
|
|
93
|
+
const partialState = {
|
|
94
|
+
label: 'Partial State Test',
|
|
95
|
+
responsive: true
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
component.dashboardSetState(partialState);
|
|
99
|
+
fixture.detectChanges();
|
|
100
|
+
|
|
101
|
+
const state = component.dashboardGetState();
|
|
102
|
+
|
|
103
|
+
expect(state.label).toBe('Partial State Test');
|
|
104
|
+
expect(state.responsive).toBe(true);
|
|
105
|
+
expect(state.fontSize).toBe(16); // default
|
|
106
|
+
expect(state.alignment).toBe('center'); // default
|
|
107
|
+
expect(state.fontWeight).toBe('normal'); // default
|
|
108
|
+
expect(state.opacity).toBe(1); // default
|
|
109
|
+
expect(state.hasBackground).toBe(true); // default
|
|
110
|
+
expect(state.minFontSize).toBe(8); // default
|
|
111
|
+
expect(state.maxFontSize).toBe(64); // default
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should handle undefined state input gracefully', () => {
|
|
115
|
+
component.dashboardSetState(undefined);
|
|
116
|
+
fixture.detectChanges();
|
|
117
|
+
|
|
118
|
+
const state = component.dashboardGetState();
|
|
119
|
+
|
|
120
|
+
// Should return default state
|
|
121
|
+
expect(state).toEqual({
|
|
122
|
+
label: '',
|
|
123
|
+
fontSize: 16,
|
|
124
|
+
alignment: 'center',
|
|
125
|
+
fontWeight: 'normal',
|
|
126
|
+
opacity: 1,
|
|
127
|
+
hasBackground: true,
|
|
128
|
+
responsive: false,
|
|
129
|
+
minFontSize: 8,
|
|
130
|
+
maxFontSize: 64
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should handle null state input gracefully', () => {
|
|
135
|
+
component.dashboardSetState(null);
|
|
136
|
+
fixture.detectChanges();
|
|
137
|
+
|
|
138
|
+
const state = component.dashboardGetState();
|
|
139
|
+
|
|
140
|
+
// Should return default state
|
|
141
|
+
expect(state).toEqual({
|
|
142
|
+
label: '',
|
|
143
|
+
fontSize: 16,
|
|
144
|
+
alignment: 'center',
|
|
145
|
+
fontWeight: 'normal',
|
|
146
|
+
opacity: 1,
|
|
147
|
+
hasBackground: true,
|
|
148
|
+
responsive: false,
|
|
149
|
+
minFontSize: 8,
|
|
150
|
+
maxFontSize: 64
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
describe('Responsive Mode State Preservation', () => {
|
|
156
|
+
it('should preserve min/max font sizes when responsive is true', () => {
|
|
157
|
+
const responsiveState: LabelWidgetState = {
|
|
158
|
+
label: 'Responsive Label',
|
|
159
|
+
fontSize: 18,
|
|
160
|
+
alignment: 'center',
|
|
161
|
+
fontWeight: 'normal',
|
|
162
|
+
opacity: 1,
|
|
163
|
+
hasBackground: true,
|
|
164
|
+
responsive: true,
|
|
165
|
+
minFontSize: 12,
|
|
166
|
+
maxFontSize: 72
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
component.dashboardSetState(responsiveState);
|
|
170
|
+
fixture.detectChanges();
|
|
171
|
+
|
|
172
|
+
const state = component.dashboardGetState();
|
|
173
|
+
|
|
174
|
+
expect(state.responsive).toBe(true);
|
|
175
|
+
expect(state.minFontSize).toBe(12);
|
|
176
|
+
expect(state.maxFontSize).toBe(72);
|
|
177
|
+
expect(state.fontSize).toBe(18); // Should still be preserved even when responsive
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should preserve min/max font sizes when responsive is false', () => {
|
|
181
|
+
const nonResponsiveState: LabelWidgetState = {
|
|
182
|
+
label: 'Non-Responsive Label',
|
|
183
|
+
fontSize: 24,
|
|
184
|
+
alignment: 'right',
|
|
185
|
+
fontWeight: 'bold',
|
|
186
|
+
opacity: 0.9,
|
|
187
|
+
hasBackground: false,
|
|
188
|
+
responsive: false,
|
|
189
|
+
minFontSize: 16,
|
|
190
|
+
maxFontSize: 96
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
component.dashboardSetState(nonResponsiveState);
|
|
194
|
+
fixture.detectChanges();
|
|
195
|
+
|
|
196
|
+
const state = component.dashboardGetState();
|
|
197
|
+
|
|
198
|
+
expect(state.responsive).toBe(false);
|
|
199
|
+
expect(state.minFontSize).toBe(16);
|
|
200
|
+
expect(state.maxFontSize).toBe(96);
|
|
201
|
+
expect(state.fontSize).toBe(24);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('should preserve custom min/max values across responsive mode changes', () => {
|
|
205
|
+
// Start with responsive mode
|
|
206
|
+
component.dashboardSetState({
|
|
207
|
+
label: 'Toggle Test',
|
|
208
|
+
responsive: true,
|
|
209
|
+
minFontSize: 14,
|
|
210
|
+
maxFontSize: 80
|
|
211
|
+
});
|
|
212
|
+
fixture.detectChanges();
|
|
213
|
+
|
|
214
|
+
let state = component.dashboardGetState();
|
|
215
|
+
expect(state.responsive).toBe(true);
|
|
216
|
+
expect(state.minFontSize).toBe(14);
|
|
217
|
+
expect(state.maxFontSize).toBe(80);
|
|
218
|
+
|
|
219
|
+
// Switch to non-responsive mode
|
|
220
|
+
component.dashboardSetState({
|
|
221
|
+
...state,
|
|
222
|
+
responsive: false
|
|
223
|
+
});
|
|
224
|
+
fixture.detectChanges();
|
|
225
|
+
|
|
226
|
+
state = component.dashboardGetState();
|
|
227
|
+
expect(state.responsive).toBe(false);
|
|
228
|
+
expect(state.minFontSize).toBe(14); // Should be preserved
|
|
229
|
+
expect(state.maxFontSize).toBe(80); // Should be preserved
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
describe('Backward Compatibility', () => {
|
|
234
|
+
it('should handle legacy state format without min/max font size properties', () => {
|
|
235
|
+
const legacyState = {
|
|
236
|
+
label: 'Legacy Widget',
|
|
237
|
+
fontSize: 18,
|
|
238
|
+
alignment: 'left' as const,
|
|
239
|
+
fontWeight: 'bold' as const,
|
|
240
|
+
opacity: 0.7,
|
|
241
|
+
hasBackground: true,
|
|
242
|
+
responsive: true
|
|
243
|
+
// Note: minFontSize and maxFontSize are intentionally missing
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
component.dashboardSetState(legacyState);
|
|
247
|
+
fixture.detectChanges();
|
|
248
|
+
|
|
249
|
+
const state = component.dashboardGetState();
|
|
250
|
+
|
|
251
|
+
// Legacy properties should be preserved
|
|
252
|
+
expect(state.label).toBe('Legacy Widget');
|
|
253
|
+
expect(state.fontSize).toBe(18);
|
|
254
|
+
expect(state.alignment).toBe('left');
|
|
255
|
+
expect(state.fontWeight).toBe('bold');
|
|
256
|
+
expect(state.opacity).toBe(0.7);
|
|
257
|
+
expect(state.hasBackground).toBe(true);
|
|
258
|
+
expect(state.responsive).toBe(true);
|
|
259
|
+
|
|
260
|
+
// Missing properties should get default values
|
|
261
|
+
expect(state.minFontSize).toBe(8);
|
|
262
|
+
expect(state.maxFontSize).toBe(64);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should handle very old state format with minimal properties', () => {
|
|
266
|
+
const minimalState = {
|
|
267
|
+
label: 'Old Widget'
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
component.dashboardSetState(minimalState);
|
|
271
|
+
fixture.detectChanges();
|
|
272
|
+
|
|
273
|
+
const state = component.dashboardGetState();
|
|
274
|
+
|
|
275
|
+
expect(state.label).toBe('Old Widget');
|
|
276
|
+
expect(state.fontSize).toBe(16);
|
|
277
|
+
expect(state.alignment).toBe('center');
|
|
278
|
+
expect(state.fontWeight).toBe('normal');
|
|
279
|
+
expect(state.opacity).toBe(1);
|
|
280
|
+
expect(state.hasBackground).toBe(true);
|
|
281
|
+
expect(state.responsive).toBe(false);
|
|
282
|
+
expect(state.minFontSize).toBe(8);
|
|
283
|
+
expect(state.maxFontSize).toBe(64);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('should upgrade legacy responsive state correctly', () => {
|
|
287
|
+
const legacyResponsiveState = {
|
|
288
|
+
label: 'Legacy Responsive',
|
|
289
|
+
responsive: true
|
|
290
|
+
// Missing min/max properties
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
component.dashboardSetState(legacyResponsiveState);
|
|
294
|
+
fixture.detectChanges();
|
|
295
|
+
|
|
296
|
+
const state = component.dashboardGetState();
|
|
297
|
+
|
|
298
|
+
expect(state.responsive).toBe(true);
|
|
299
|
+
expect(state.minFontSize).toBe(8); // Should get defaults
|
|
300
|
+
expect(state.maxFontSize).toBe(64); // Should get defaults
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
describe('State Roundtrip Consistency', () => {
|
|
305
|
+
it('should maintain state consistency through multiple set/get cycles', () => {
|
|
306
|
+
const originalState: LabelWidgetState = {
|
|
307
|
+
label: 'Roundtrip Test',
|
|
308
|
+
fontSize: 22,
|
|
309
|
+
alignment: 'right',
|
|
310
|
+
fontWeight: 'bold',
|
|
311
|
+
opacity: 0.85,
|
|
312
|
+
hasBackground: false,
|
|
313
|
+
responsive: true,
|
|
314
|
+
minFontSize: 10,
|
|
315
|
+
maxFontSize: 100
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
// First roundtrip
|
|
319
|
+
component.dashboardSetState(originalState);
|
|
320
|
+
fixture.detectChanges();
|
|
321
|
+
const firstRetrieved = component.dashboardGetState();
|
|
322
|
+
|
|
323
|
+
// Second roundtrip
|
|
324
|
+
component.dashboardSetState(firstRetrieved);
|
|
325
|
+
fixture.detectChanges();
|
|
326
|
+
const secondRetrieved = component.dashboardGetState();
|
|
327
|
+
|
|
328
|
+
// Third roundtrip
|
|
329
|
+
component.dashboardSetState(secondRetrieved);
|
|
330
|
+
fixture.detectChanges();
|
|
331
|
+
const thirdRetrieved = component.dashboardGetState();
|
|
332
|
+
|
|
333
|
+
// All states should be identical
|
|
334
|
+
expect(firstRetrieved).toEqual(originalState);
|
|
335
|
+
expect(secondRetrieved).toEqual(originalState);
|
|
336
|
+
expect(thirdRetrieved).toEqual(originalState);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it('should handle edge case font size values consistently', () => {
|
|
340
|
+
const edgeCaseState: LabelWidgetState = {
|
|
341
|
+
label: 'Edge Cases',
|
|
342
|
+
fontSize: 8,
|
|
343
|
+
alignment: 'center',
|
|
344
|
+
fontWeight: 'normal',
|
|
345
|
+
opacity: 0.1,
|
|
346
|
+
hasBackground: true,
|
|
347
|
+
responsive: true,
|
|
348
|
+
minFontSize: 8, // Minimum allowed value
|
|
349
|
+
maxFontSize: 128 // Maximum allowed value
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
component.dashboardSetState(edgeCaseState);
|
|
353
|
+
fixture.detectChanges();
|
|
354
|
+
const retrievedState = component.dashboardGetState();
|
|
355
|
+
|
|
356
|
+
expect(retrievedState).toEqual(edgeCaseState);
|
|
357
|
+
expect(retrievedState.minFontSize).toBe(8);
|
|
358
|
+
expect(retrievedState.maxFontSize).toBe(128);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it('should preserve all alignment options through serialization', () => {
|
|
362
|
+
const alignmentOptions: Array<'left' | 'center' | 'right'> = ['left', 'center', 'right'];
|
|
363
|
+
|
|
364
|
+
alignmentOptions.forEach(alignment => {
|
|
365
|
+
const testState: LabelWidgetState = {
|
|
366
|
+
label: `${alignment} aligned`,
|
|
367
|
+
fontSize: 16,
|
|
368
|
+
alignment: alignment,
|
|
369
|
+
fontWeight: 'normal',
|
|
370
|
+
opacity: 1,
|
|
371
|
+
hasBackground: true,
|
|
372
|
+
responsive: false,
|
|
373
|
+
minFontSize: 8,
|
|
374
|
+
maxFontSize: 64
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
component.dashboardSetState(testState);
|
|
378
|
+
fixture.detectChanges();
|
|
379
|
+
const retrievedState = component.dashboardGetState();
|
|
380
|
+
|
|
381
|
+
expect(retrievedState.alignment).toBe(alignment);
|
|
382
|
+
expect(retrievedState).toEqual(testState);
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
it('should preserve all font weight options through serialization', () => {
|
|
387
|
+
const fontWeightOptions: Array<'normal' | 'bold'> = ['normal', 'bold'];
|
|
388
|
+
|
|
389
|
+
fontWeightOptions.forEach(fontWeight => {
|
|
390
|
+
const testState: LabelWidgetState = {
|
|
391
|
+
label: `${fontWeight} text`,
|
|
392
|
+
fontSize: 16,
|
|
393
|
+
alignment: 'center',
|
|
394
|
+
fontWeight: fontWeight,
|
|
395
|
+
opacity: 1,
|
|
396
|
+
hasBackground: true,
|
|
397
|
+
responsive: false,
|
|
398
|
+
minFontSize: 8,
|
|
399
|
+
maxFontSize: 64
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
component.dashboardSetState(testState);
|
|
403
|
+
fixture.detectChanges();
|
|
404
|
+
const retrievedState = component.dashboardGetState();
|
|
405
|
+
|
|
406
|
+
expect(retrievedState.fontWeight).toBe(fontWeight);
|
|
407
|
+
expect(retrievedState).toEqual(testState);
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
describe('Custom Font Size Range Serialization', () => {
|
|
413
|
+
it('should serialize custom min/max font sizes correctly', () => {
|
|
414
|
+
const customRangeStates = [
|
|
415
|
+
{ minFontSize: 8, maxFontSize: 32 },
|
|
416
|
+
{ minFontSize: 12, maxFontSize: 48 },
|
|
417
|
+
{ minFontSize: 16, maxFontSize: 96 },
|
|
418
|
+
{ minFontSize: 8, maxFontSize: 128 }
|
|
419
|
+
];
|
|
420
|
+
|
|
421
|
+
customRangeStates.forEach(({ minFontSize, maxFontSize }) => {
|
|
422
|
+
const testState: LabelWidgetState = {
|
|
423
|
+
label: `Range ${minFontSize}-${maxFontSize}`,
|
|
424
|
+
fontSize: 16,
|
|
425
|
+
alignment: 'center',
|
|
426
|
+
fontWeight: 'normal',
|
|
427
|
+
opacity: 1,
|
|
428
|
+
hasBackground: true,
|
|
429
|
+
responsive: true,
|
|
430
|
+
minFontSize: minFontSize,
|
|
431
|
+
maxFontSize: maxFontSize
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
component.dashboardSetState(testState);
|
|
435
|
+
fixture.detectChanges();
|
|
436
|
+
const retrievedState = component.dashboardGetState();
|
|
437
|
+
|
|
438
|
+
expect(retrievedState.minFontSize).toBe(minFontSize);
|
|
439
|
+
expect(retrievedState.maxFontSize).toBe(maxFontSize);
|
|
440
|
+
expect(retrievedState).toEqual(testState);
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
it('should handle all combinations of responsive mode and custom font ranges', () => {
|
|
445
|
+
const testCombinations = [
|
|
446
|
+
{ responsive: true, minFontSize: 10, maxFontSize: 50 },
|
|
447
|
+
{ responsive: false, minFontSize: 10, maxFontSize: 50 },
|
|
448
|
+
{ responsive: true, minFontSize: 8, maxFontSize: 128 },
|
|
449
|
+
{ responsive: false, minFontSize: 8, maxFontSize: 128 }
|
|
450
|
+
];
|
|
451
|
+
|
|
452
|
+
testCombinations.forEach(({ responsive, minFontSize, maxFontSize }) => {
|
|
453
|
+
const testState: LabelWidgetState = {
|
|
454
|
+
label: `Combo ${responsive ? 'responsive' : 'fixed'} ${minFontSize}-${maxFontSize}`,
|
|
455
|
+
fontSize: 18,
|
|
456
|
+
alignment: 'left',
|
|
457
|
+
fontWeight: 'bold',
|
|
458
|
+
opacity: 0.9,
|
|
459
|
+
hasBackground: false,
|
|
460
|
+
responsive: responsive,
|
|
461
|
+
minFontSize: minFontSize,
|
|
462
|
+
maxFontSize: maxFontSize
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
component.dashboardSetState(testState);
|
|
466
|
+
fixture.detectChanges();
|
|
467
|
+
const retrievedState = component.dashboardGetState();
|
|
468
|
+
|
|
469
|
+
expect(retrievedState.responsive).toBe(responsive);
|
|
470
|
+
expect(retrievedState.minFontSize).toBe(minFontSize);
|
|
471
|
+
expect(retrievedState.maxFontSize).toBe(maxFontSize);
|
|
472
|
+
expect(retrievedState).toEqual(testState);
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
describe('State Object Type Safety', () => {
|
|
478
|
+
it('should handle unknown properties in state object gracefully', () => {
|
|
479
|
+
const stateWithExtraProps = {
|
|
480
|
+
label: 'Extra Props Test',
|
|
481
|
+
fontSize: 16,
|
|
482
|
+
alignment: 'center' as const,
|
|
483
|
+
fontWeight: 'normal' as const,
|
|
484
|
+
opacity: 1,
|
|
485
|
+
hasBackground: true,
|
|
486
|
+
responsive: false,
|
|
487
|
+
minFontSize: 8,
|
|
488
|
+
maxFontSize: 64,
|
|
489
|
+
unknownProperty: 'should be preserved',
|
|
490
|
+
anotherExtra: 123
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
// TypeScript won't allow this normally, but simulate receiving unknown props
|
|
494
|
+
component.dashboardSetState(stateWithExtraProps as any);
|
|
495
|
+
fixture.detectChanges();
|
|
496
|
+
|
|
497
|
+
const retrievedState = component.dashboardGetState();
|
|
498
|
+
|
|
499
|
+
// Should include all known properties with correct values
|
|
500
|
+
expect(retrievedState.label).toBe('Extra Props Test');
|
|
501
|
+
expect(retrievedState.fontSize).toBe(16);
|
|
502
|
+
expect(retrievedState.alignment).toBe('center');
|
|
503
|
+
expect(retrievedState.fontWeight).toBe('normal');
|
|
504
|
+
expect(retrievedState.opacity).toBe(1);
|
|
505
|
+
expect(retrievedState.hasBackground).toBe(true);
|
|
506
|
+
expect(retrievedState.responsive).toBe(false);
|
|
507
|
+
expect(retrievedState.minFontSize).toBe(8);
|
|
508
|
+
expect(retrievedState.maxFontSize).toBe(64);
|
|
509
|
+
|
|
510
|
+
// Unknown properties are preserved by the current implementation (this is acceptable behavior)
|
|
511
|
+
expect((retrievedState as any).unknownProperty).toBeDefined();
|
|
512
|
+
expect((retrievedState as any).anotherExtra).toBeDefined();
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
it('should return a new object instance on each call to dashboardGetState', () => {
|
|
516
|
+
const testState: LabelWidgetState = {
|
|
517
|
+
label: 'Instance Test',
|
|
518
|
+
fontSize: 16,
|
|
519
|
+
alignment: 'center',
|
|
520
|
+
fontWeight: 'normal',
|
|
521
|
+
opacity: 1,
|
|
522
|
+
hasBackground: true,
|
|
523
|
+
responsive: false,
|
|
524
|
+
minFontSize: 8,
|
|
525
|
+
maxFontSize: 64
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
component.dashboardSetState(testState);
|
|
529
|
+
fixture.detectChanges();
|
|
530
|
+
|
|
531
|
+
const firstCall = component.dashboardGetState();
|
|
532
|
+
const secondCall = component.dashboardGetState();
|
|
533
|
+
|
|
534
|
+
// Should be equal in content but different instances
|
|
535
|
+
expect(firstCall).toEqual(secondCall);
|
|
536
|
+
expect(firstCall).not.toBe(secondCall);
|
|
537
|
+
});
|
|
538
|
+
});
|
|
539
|
+
});
|