@usertour/helpers 0.0.59 → 0.0.60

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.
@@ -0,0 +1,754 @@
1
+ import {
2
+ convertSettings,
3
+ convertToCssVars,
4
+ mergeThemeDefaultSettings
5
+ } from "../chunk-77ALLS35.js";
6
+ import "../chunk-5C3J4DM2.js";
7
+ import "../chunk-FZFHBCB6.js";
8
+ import "../chunk-GFH3VWOC.js";
9
+ import "../chunk-XEO3YXBM.js";
10
+
11
+ // src/__tests__/convert-settings.test.ts
12
+ import { defaultSettings } from "@usertour/types";
13
+ var originalDefaultMainColorHover = defaultSettings.mainColor.hover;
14
+ var originalDefaultBrandColorHover = defaultSettings.brandColor.hover;
15
+ describe("convert-settings", () => {
16
+ const completeSettings = {
17
+ mainColor: {
18
+ background: "#FFFFFF",
19
+ color: "#0f172a",
20
+ hover: "Auto",
21
+ active: "Auto",
22
+ autoHover: "#e7eefd",
23
+ autoActive: "#cedcfb"
24
+ },
25
+ brandColor: {
26
+ background: "#2563eb",
27
+ color: "#ffffff",
28
+ hover: "Auto",
29
+ active: "Auto",
30
+ autoHover: "#4b7eee",
31
+ autoActive: "#2055c9"
32
+ },
33
+ font: {
34
+ fontFamily: "System font",
35
+ fontSize: 16,
36
+ lineHeight: 24,
37
+ fontWeightNormal: 400,
38
+ fontWeightBold: 600,
39
+ h1FontSize: 24,
40
+ h2FontSize: 20,
41
+ linkColor: "Auto"
42
+ },
43
+ border: {
44
+ borderRadius: "10",
45
+ borderWidthEnabled: false,
46
+ borderWidth: 1,
47
+ borderColor: "Auto"
48
+ },
49
+ xbutton: {
50
+ color: "Auto"
51
+ },
52
+ progress: {
53
+ enabled: true,
54
+ color: "Auto",
55
+ height: 2,
56
+ type: "full-width",
57
+ position: "top",
58
+ narrowHeight: 5,
59
+ chainSquaredHeight: 4,
60
+ chainRoundedHeight: 6,
61
+ dotsHeight: 6,
62
+ numberedHeight: 12
63
+ },
64
+ survey: {
65
+ color: "Auto"
66
+ },
67
+ launcherBeacon: {
68
+ color: "Auto",
69
+ size: 16
70
+ },
71
+ launcherIcon: {
72
+ color: {
73
+ color: "Auto",
74
+ hover: "Auto",
75
+ active: "Auto",
76
+ background: "#1d4ed8"
77
+ },
78
+ opacity: 100,
79
+ size: 16
80
+ },
81
+ checklist: {
82
+ checkmarkColor: "#4ade80",
83
+ width: 360,
84
+ placement: {
85
+ position: "rightBottom",
86
+ positionOffsetX: 20,
87
+ positionOffsetY: 20
88
+ }
89
+ },
90
+ checklistLauncher: {
91
+ borderRadius: 30,
92
+ height: 60,
93
+ fontWeight: 600,
94
+ placement: {
95
+ position: "rightBottom",
96
+ positionOffsetX: 100,
97
+ positionOffsetY: 20
98
+ },
99
+ color: {
100
+ color: "Auto",
101
+ hover: "Auto",
102
+ active: "Auto",
103
+ background: "Auto"
104
+ },
105
+ counter: {
106
+ color: "Auto",
107
+ background: "Auto"
108
+ }
109
+ },
110
+ buttons: {
111
+ height: 32,
112
+ minWidth: 0,
113
+ px: 16,
114
+ borderRadius: 8,
115
+ primary: {
116
+ fontWeight: 600,
117
+ textColor: {
118
+ color: "Auto",
119
+ hover: "Auto",
120
+ active: "Auto",
121
+ background: "#FFFFFF"
122
+ },
123
+ backgroundColor: {
124
+ color: "#FFFFFF",
125
+ hover: "Auto",
126
+ active: "Auto",
127
+ background: "Auto"
128
+ },
129
+ border: {
130
+ enabled: false,
131
+ borderWidth: 1,
132
+ color: {
133
+ color: "Auto",
134
+ hover: "Auto",
135
+ active: "Auto",
136
+ background: "#FFFFFF"
137
+ }
138
+ }
139
+ },
140
+ secondary: {
141
+ fontWeight: 600,
142
+ textColor: {
143
+ color: "Auto",
144
+ hover: "Auto",
145
+ active: "Auto",
146
+ background: "#FFFFFF"
147
+ },
148
+ backgroundColor: {
149
+ color: "#FFFFFF",
150
+ hover: "Auto",
151
+ active: "Auto",
152
+ background: "Auto"
153
+ },
154
+ border: {
155
+ enabled: true,
156
+ borderWidth: 1,
157
+ color: {
158
+ color: "Auto",
159
+ hover: "Auto",
160
+ active: "Auto",
161
+ background: "#FFFFFF"
162
+ }
163
+ }
164
+ }
165
+ },
166
+ tooltip: {
167
+ width: 300,
168
+ notchSize: 20
169
+ },
170
+ modal: {
171
+ width: 600,
172
+ padding: 40
173
+ },
174
+ backdrop: {
175
+ color: "#000000",
176
+ opacity: 40,
177
+ highlight: {
178
+ type: "outside",
179
+ radius: 4,
180
+ spread: 0,
181
+ color: "#ffffff",
182
+ opacity: 50
183
+ }
184
+ }
185
+ };
186
+ describe("mergeThemeDefaultSettings", () => {
187
+ it("should merge with defaultSettings for empty input", () => {
188
+ const result = mergeThemeDefaultSettings({});
189
+ expect(result.mainColor).toBeDefined();
190
+ expect(result.brandColor).toBeDefined();
191
+ expect(result.buttons).toBeDefined();
192
+ expect(result.font).toBeDefined();
193
+ });
194
+ it("should override defaultSettings with provided values", () => {
195
+ const customSettings = {
196
+ mainColor: {
197
+ background: "#000000",
198
+ color: "#ffffff",
199
+ hover: "#333333",
200
+ active: "#666666"
201
+ }
202
+ };
203
+ const result = mergeThemeDefaultSettings(customSettings);
204
+ expect(result.mainColor.background).toBe("#000000");
205
+ expect(result.mainColor.color).toBe("#ffffff");
206
+ });
207
+ });
208
+ describe("convertSettings - Auto value resolution", () => {
209
+ describe("mainColor Auto values", () => {
210
+ it("should resolve mainColor.hover from autoHover when set to Auto", () => {
211
+ const result = convertSettings(completeSettings);
212
+ expect(result.mainColor.hover).toBe(completeSettings.mainColor.autoHover);
213
+ });
214
+ it("should resolve mainColor.active from autoActive when set to Auto", () => {
215
+ const result = convertSettings(completeSettings);
216
+ expect(result.mainColor.active).toBe(completeSettings.mainColor.autoActive);
217
+ });
218
+ it("should keep custom hover value when not Auto", () => {
219
+ const settings = {
220
+ ...completeSettings,
221
+ mainColor: {
222
+ ...completeSettings.mainColor,
223
+ hover: "#custom123"
224
+ }
225
+ };
226
+ const result = convertSettings(settings);
227
+ expect(result.mainColor.hover).toBe("#custom123");
228
+ });
229
+ });
230
+ describe("brandColor Auto values", () => {
231
+ it("should resolve brandColor.hover from autoHover when set to Auto", () => {
232
+ const result = convertSettings(completeSettings);
233
+ expect(result.brandColor.hover).toBe(completeSettings.brandColor.autoHover);
234
+ });
235
+ it("should resolve brandColor.active from autoActive when set to Auto", () => {
236
+ const result = convertSettings(completeSettings);
237
+ expect(result.brandColor.active).toBe(completeSettings.brandColor.autoActive);
238
+ });
239
+ });
240
+ describe("border Auto values", () => {
241
+ it("should resolve border.borderColor from mainColor.color when set to Auto", () => {
242
+ const result = convertSettings(completeSettings);
243
+ expect(result.border.borderColor).toBe(completeSettings.mainColor.color);
244
+ });
245
+ });
246
+ describe("primary button Auto values", () => {
247
+ it("should resolve primary button textColor from brandColor.color when set to Auto", () => {
248
+ const result = convertSettings(completeSettings);
249
+ expect(result.buttons.primary.textColor.color).toBe(completeSettings.brandColor.color);
250
+ expect(result.buttons.primary.textColor.hover).toBe(completeSettings.brandColor.color);
251
+ expect(result.buttons.primary.textColor.active).toBe(completeSettings.brandColor.color);
252
+ });
253
+ it("should resolve primary button backgroundColor from brandColor when set to Auto", () => {
254
+ const result = convertSettings(completeSettings);
255
+ expect(result.buttons.primary.backgroundColor.background).toBe(
256
+ completeSettings.brandColor.background
257
+ );
258
+ expect(result.buttons.primary.backgroundColor.hover).toBe(
259
+ completeSettings.brandColor.autoHover
260
+ );
261
+ expect(result.buttons.primary.backgroundColor.active).toBe(
262
+ completeSettings.brandColor.autoActive
263
+ );
264
+ });
265
+ it("should resolve primary button border.color from brandColor when set to Auto", () => {
266
+ const result = convertSettings(completeSettings);
267
+ expect(result.buttons.primary.border.color.color).toBe(
268
+ completeSettings.brandColor.background
269
+ );
270
+ expect(result.buttons.primary.border.color.hover).toBe(
271
+ completeSettings.brandColor.autoHover
272
+ );
273
+ expect(result.buttons.primary.border.color.active).toBe(
274
+ completeSettings.brandColor.autoActive
275
+ );
276
+ });
277
+ });
278
+ describe("secondary button Auto values", () => {
279
+ it("should resolve secondary button textColor from brandColor.background when set to Auto", () => {
280
+ const result = convertSettings(completeSettings);
281
+ expect(result.buttons.secondary.textColor.color).toBe(
282
+ completeSettings.brandColor.background
283
+ );
284
+ expect(result.buttons.secondary.textColor.hover).toBe(
285
+ completeSettings.brandColor.background
286
+ );
287
+ expect(result.buttons.secondary.textColor.active).toBe(
288
+ completeSettings.brandColor.background
289
+ );
290
+ });
291
+ it("should resolve secondary button backgroundColor from mainColor when set to Auto", () => {
292
+ const result = convertSettings(completeSettings);
293
+ expect(result.buttons.secondary.backgroundColor.background).toBe(
294
+ completeSettings.mainColor.background
295
+ );
296
+ expect(result.buttons.secondary.backgroundColor.hover).toBe(
297
+ completeSettings.mainColor.autoHover
298
+ );
299
+ expect(result.buttons.secondary.backgroundColor.active).toBe(
300
+ completeSettings.mainColor.autoActive
301
+ );
302
+ });
303
+ it("should resolve secondary button border.color from brandColor.background when set to Auto", () => {
304
+ const result = convertSettings(completeSettings);
305
+ expect(result.buttons.secondary.border.color.color).toBe(
306
+ completeSettings.brandColor.background
307
+ );
308
+ expect(result.buttons.secondary.border.color.hover).toBe(
309
+ completeSettings.brandColor.background
310
+ );
311
+ expect(result.buttons.secondary.border.color.active).toBe(
312
+ completeSettings.brandColor.background
313
+ );
314
+ });
315
+ });
316
+ describe("font Auto values", () => {
317
+ it("should resolve font.linkColor from brandColor.background when set to Auto", () => {
318
+ const result = convertSettings(completeSettings);
319
+ expect(result.font.linkColor).toBe(completeSettings.brandColor.background);
320
+ });
321
+ });
322
+ describe("xbutton Auto values", () => {
323
+ it("should resolve xbutton.color from mainColor.color when set to Auto", () => {
324
+ const result = convertSettings(completeSettings);
325
+ expect(result.xbutton.color).toBe(completeSettings.mainColor.color);
326
+ });
327
+ });
328
+ describe("progress Auto values", () => {
329
+ it("should resolve progress.color from brandColor.background when set to Auto", () => {
330
+ const result = convertSettings(completeSettings);
331
+ expect(result.progress.color).toBe(completeSettings.brandColor.background);
332
+ });
333
+ });
334
+ describe("launcherBeacon Auto values", () => {
335
+ it("should resolve launcherBeacon.color from brandColor.background when set to Auto", () => {
336
+ const settings = {
337
+ ...completeSettings,
338
+ launcherBeacon: {
339
+ ...completeSettings.launcherBeacon,
340
+ color: "Auto"
341
+ }
342
+ };
343
+ const result = convertSettings(settings);
344
+ expect(result.launcherBeacon.color).toBe(completeSettings.brandColor.background);
345
+ });
346
+ });
347
+ describe("launcherIcon Auto values", () => {
348
+ it("should resolve launcherIcon.color values from brandColor when set to Auto", () => {
349
+ const result = convertSettings(completeSettings);
350
+ expect(result.launcherIcon.color.color).toBe(completeSettings.brandColor.background);
351
+ expect(result.launcherIcon.color.hover).toBe(completeSettings.brandColor.autoHover);
352
+ expect(result.launcherIcon.color.active).toBe(completeSettings.brandColor.autoActive);
353
+ });
354
+ });
355
+ describe("checklistLauncher Auto values", () => {
356
+ it("should resolve checklistLauncher.color values from brandColor when set to Auto", () => {
357
+ const result = convertSettings(completeSettings);
358
+ expect(result.checklistLauncher.color.color).toBe(completeSettings.brandColor.color);
359
+ expect(result.checklistLauncher.color.background).toBe(
360
+ completeSettings.brandColor.background
361
+ );
362
+ expect(result.checklistLauncher.color.hover).toBe(completeSettings.brandColor.autoHover);
363
+ expect(result.checklistLauncher.color.active).toBe(completeSettings.brandColor.autoActive);
364
+ });
365
+ it("should resolve checklistLauncher.counter values from brandColor when set to Auto", () => {
366
+ const result = convertSettings(completeSettings);
367
+ expect(result.checklistLauncher.counter.color).toBe(completeSettings.brandColor.background);
368
+ expect(result.checklistLauncher.counter.background).toBe(completeSettings.brandColor.color);
369
+ });
370
+ });
371
+ describe("survey Auto values", () => {
372
+ it("should resolve survey.color from brandColor.background when set to Auto", () => {
373
+ const result = convertSettings(completeSettings);
374
+ expect(result.survey.color).toBe(completeSettings.brandColor.background);
375
+ });
376
+ });
377
+ describe("font family handling", () => {
378
+ it("should convert System font to full font family string", () => {
379
+ const result = convertSettings(completeSettings);
380
+ expect(result.font.fontFamily).toContain("apple-system");
381
+ expect(result.font.fontFamily).toContain("Segoe UI");
382
+ });
383
+ it("should append sans-serif to custom font family", () => {
384
+ const settings = {
385
+ ...completeSettings,
386
+ font: {
387
+ ...completeSettings.font,
388
+ fontFamily: "CustomFont"
389
+ }
390
+ };
391
+ const result = convertSettings(settings);
392
+ expect(result.font.fontFamily).toContain("CustomFont");
393
+ expect(result.font.fontFamily).toContain("sans-serif");
394
+ });
395
+ });
396
+ });
397
+ describe("convertSettings - Missing data fallback (defaultSettings layer)", () => {
398
+ it("should handle empty settings object with defaultSettings fallback", () => {
399
+ const result = convertSettings({});
400
+ expect(result.mainColor).toBeDefined();
401
+ expect(result.brandColor).toBeDefined();
402
+ expect(result.buttons).toBeDefined();
403
+ expect(result.font).toBeDefined();
404
+ expect(result.border).toBeDefined();
405
+ });
406
+ it("should handle missing mainColor with defaultSettings fallback", () => {
407
+ const settings = { brandColor: completeSettings.brandColor };
408
+ const result = convertSettings(settings);
409
+ expect(result.mainColor.background).toBe(defaultSettings.mainColor.background);
410
+ });
411
+ it("should handle missing buttons with defaultSettings fallback", () => {
412
+ const settings = {
413
+ mainColor: completeSettings.mainColor,
414
+ brandColor: completeSettings.brandColor
415
+ };
416
+ const result = convertSettings(settings);
417
+ expect(result.buttons.height).toBe(defaultSettings.buttons.height);
418
+ expect(result.buttons.primary).toBeDefined();
419
+ expect(result.buttons.secondary).toBeDefined();
420
+ });
421
+ it("should handle missing nested properties with defaultSettings fallback", () => {
422
+ const settings = {
423
+ buttons: {
424
+ height: 40
425
+ // missing primary and secondary
426
+ }
427
+ };
428
+ const result = convertSettings(settings);
429
+ expect(result.buttons.height).toBe(40);
430
+ expect(result.buttons.primary).toBeDefined();
431
+ expect(result.buttons.secondary).toBeDefined();
432
+ });
433
+ it("should handle missing progress with defaultSettings fallback", () => {
434
+ const settings = {
435
+ mainColor: completeSettings.mainColor,
436
+ brandColor: completeSettings.brandColor
437
+ };
438
+ const result = convertSettings(settings);
439
+ expect(result.progress).toBeDefined();
440
+ expect(result.progress.height).toBe(defaultSettings.progress.height);
441
+ });
442
+ it("should handle missing checklistLauncher with defaultSettings fallback", () => {
443
+ const settings = {
444
+ mainColor: completeSettings.mainColor,
445
+ brandColor: completeSettings.brandColor
446
+ };
447
+ const result = convertSettings(settings);
448
+ expect(result.checklistLauncher).toBeDefined();
449
+ expect(result.checklistLauncher.borderRadius).toBe(
450
+ defaultSettings.checklistLauncher.borderRadius
451
+ );
452
+ });
453
+ it("should handle missing launcherIcon with defaultSettings fallback", () => {
454
+ const settings = {
455
+ mainColor: completeSettings.mainColor,
456
+ brandColor: completeSettings.brandColor
457
+ };
458
+ const result = convertSettings(settings);
459
+ expect(result.launcherIcon).toBeDefined();
460
+ expect(result.launcherIcon.size).toBe(defaultSettings.launcherIcon.size);
461
+ });
462
+ });
463
+ describe("convertSettings - Combined fallback (missing data + Auto resolution)", () => {
464
+ it("should apply both defaultSettings fallback and Auto resolution for empty input", () => {
465
+ const result = convertSettings({});
466
+ expect(result.mainColor.background).toBe(defaultSettings.mainColor.background);
467
+ expect(result.mainColor.hover).toBe(defaultSettings.mainColor.autoHover);
468
+ expect(result.mainColor.active).toBe(defaultSettings.mainColor.autoActive);
469
+ expect(result.brandColor.hover).toBe(defaultSettings.brandColor.autoHover);
470
+ expect(result.brandColor.active).toBe(defaultSettings.brandColor.autoActive);
471
+ });
472
+ it("should resolve Auto values using defaultSettings when source settings are missing", () => {
473
+ const result = convertSettings({});
474
+ expect(result.border.borderColor).toBe(defaultSettings.mainColor.color);
475
+ expect(result.xbutton.color).toBe(defaultSettings.mainColor.color);
476
+ expect(result.font.linkColor).toBe(defaultSettings.brandColor.background);
477
+ expect(result.progress.color).toBe(defaultSettings.brandColor.background);
478
+ });
479
+ it("should resolve button Auto values using defaultSettings when settings are missing", () => {
480
+ const result = convertSettings({});
481
+ expect(result.buttons.primary.textColor.color).toBe(defaultSettings.brandColor.color);
482
+ expect(result.buttons.primary.backgroundColor.background).toBe(
483
+ defaultSettings.brandColor.background
484
+ );
485
+ expect(result.buttons.primary.backgroundColor.hover).toBe(
486
+ defaultSettings.brandColor.autoHover
487
+ );
488
+ expect(result.buttons.secondary.textColor.color).toBe(defaultSettings.brandColor.background);
489
+ expect(result.buttons.secondary.backgroundColor.background).toBe(
490
+ defaultSettings.mainColor.background
491
+ );
492
+ });
493
+ it("should handle partial settings with correct fallback chain", () => {
494
+ const partialSettings = {
495
+ mainColor: {
496
+ background: "#FF0000",
497
+ color: "#00FF00",
498
+ hover: "Auto",
499
+ active: "Auto",
500
+ autoHover: "#FF5555",
501
+ autoActive: "#FF9999"
502
+ }
503
+ };
504
+ const result = convertSettings(partialSettings);
505
+ expect(result.mainColor.background).toBe("#FF0000");
506
+ expect(result.mainColor.hover).toBe("#FF5555");
507
+ expect(result.mainColor.active).toBe("#FF9999");
508
+ expect(result.brandColor.background).toBe(defaultSettings.brandColor.background);
509
+ expect(result.border.borderColor).not.toBe("Auto");
510
+ expect(result.border.borderColor).toMatch(/^#[0-9a-fA-F]{6}$/);
511
+ });
512
+ });
513
+ describe("convertToCssVars", () => {
514
+ it("should generate CSS variables string for complete settings", () => {
515
+ const convertedSettings = convertSettings(completeSettings);
516
+ const css = convertToCssVars(convertedSettings);
517
+ expect(css).toContain("--usertour-background:");
518
+ expect(css).toContain("--usertour-foreground:");
519
+ expect(css).toContain("--usertour-primary:");
520
+ expect(css).toContain("--usertour-secondary:");
521
+ expect(css).toContain("--usertour-font-family:");
522
+ });
523
+ it("should include button CSS variables", () => {
524
+ const convertedSettings = convertSettings(completeSettings);
525
+ const css = convertToCssVars(convertedSettings);
526
+ expect(css).toContain("--usertour-primary-hover:");
527
+ expect(css).toContain("--usertour-primary-active:");
528
+ expect(css).toContain("--usertour-primary-foreground:");
529
+ expect(css).toContain("--usertour-secondary-hover:");
530
+ expect(css).toContain("--usertour-secondary-active:");
531
+ expect(css).toContain("--usertour-secondary-foreground:");
532
+ });
533
+ it("should include backdrop CSS variables", () => {
534
+ const convertedSettings = convertSettings(completeSettings);
535
+ const css = convertToCssVars(convertedSettings);
536
+ expect(css).toContain("--usertour-backdrop-color-rgb:");
537
+ expect(css).toContain("--usertour-backdrop-opacity:");
538
+ expect(css).toContain("--usertour-backdrop-highlight-opacity:");
539
+ });
540
+ it("should include progress bar CSS variables", () => {
541
+ const convertedSettings = convertSettings(completeSettings);
542
+ const css = convertToCssVars(convertedSettings);
543
+ expect(css).toContain("--usertour-progress-bar-color:");
544
+ expect(css).toContain("--usertour-progress-bar-height:");
545
+ });
546
+ it("should include checklist launcher CSS variables", () => {
547
+ const convertedSettings = convertSettings(completeSettings);
548
+ const css = convertToCssVars(convertedSettings);
549
+ expect(css).toContain("--usertour-checklist-trigger-background-color:");
550
+ expect(css).toContain("--usertour-checklist-trigger-font-color:");
551
+ expect(css).toContain("--usertour-checklist-trigger-counter-background-color:");
552
+ });
553
+ it("should include launcher icon CSS variables", () => {
554
+ const convertedSettings = convertSettings(completeSettings);
555
+ const css = convertToCssVars(convertedSettings);
556
+ expect(css).toContain("--usertour-widget-launcher-icon-color:");
557
+ expect(css).toContain("--usertour-widget-launcher-icon-hover-color:");
558
+ expect(css).toContain("--usertour-widget-beacon-color:");
559
+ });
560
+ it("should add modal padding for modal type", () => {
561
+ const convertedSettings = convertSettings(completeSettings);
562
+ const css = convertToCssVars(convertedSettings, "modal");
563
+ expect(css).toContain("--usertour-widget-popper-padding:");
564
+ expect(css).toContain("40px");
565
+ });
566
+ it("should not add modal padding for tooltip type", () => {
567
+ const convertedSettings = convertSettings(completeSettings);
568
+ const css = convertToCssVars(convertedSettings, "tooltip");
569
+ const modalPaddingMatch = css.match(/--usertour-widget-popper-padding:[^;]+;/);
570
+ expect(modalPaddingMatch).toBeNull();
571
+ });
572
+ it("should add backdrop inset for inside highlight type", () => {
573
+ const settings = {
574
+ ...completeSettings,
575
+ backdrop: {
576
+ ...completeSettings.backdrop,
577
+ highlight: {
578
+ ...completeSettings.backdrop.highlight,
579
+ type: "inside"
580
+ }
581
+ }
582
+ };
583
+ const convertedSettings = convertSettings(settings);
584
+ const css = convertToCssVars(convertedSettings);
585
+ expect(css).toContain("--usertour-backdrop-highlight-inset:inset");
586
+ });
587
+ it("should work correctly with defaultSettings fallback for empty input", () => {
588
+ const convertedSettings = convertSettings({});
589
+ const css = convertToCssVars(convertedSettings);
590
+ expect(css).toContain("--usertour-background:");
591
+ expect(css).toContain("--usertour-primary:");
592
+ expect(css.length).toBeGreaterThan(0);
593
+ });
594
+ });
595
+ describe("Edge cases and error handling", () => {
596
+ it("should handle undefined values in nested objects gracefully", () => {
597
+ const settings = {
598
+ mainColor: {
599
+ background: "#FFFFFF",
600
+ color: "#000000"
601
+ // hover, active, autoHover, autoActive are undefined
602
+ },
603
+ brandColor: {
604
+ background: "#2563eb",
605
+ color: "#ffffff"
606
+ }
607
+ };
608
+ expect(() => convertSettings(settings)).not.toThrow();
609
+ const result = convertSettings(settings);
610
+ expect(result.mainColor).toBeDefined();
611
+ });
612
+ it("should handle partial settings without throwing", () => {
613
+ const settings = {
614
+ mainColor: completeSettings.mainColor,
615
+ brandColor: completeSettings.brandColor
616
+ // progress is missing, not null
617
+ };
618
+ expect(() => convertSettings(settings)).not.toThrow();
619
+ const result = convertSettings(settings);
620
+ expect(result.progress).toBeDefined();
621
+ expect(result.progress.color).toBe(completeSettings.brandColor.background);
622
+ });
623
+ it("should preserve non-Auto values throughout the conversion", () => {
624
+ const settings = {
625
+ ...completeSettings,
626
+ mainColor: {
627
+ ...completeSettings.mainColor,
628
+ hover: "#custom-hover",
629
+ active: "#custom-active"
630
+ },
631
+ buttons: {
632
+ ...completeSettings.buttons,
633
+ primary: {
634
+ ...completeSettings.buttons.primary,
635
+ textColor: {
636
+ ...completeSettings.buttons.primary.textColor,
637
+ color: "#custom-text"
638
+ }
639
+ }
640
+ }
641
+ };
642
+ const result = convertSettings(settings);
643
+ expect(result.mainColor.hover).toBe("#custom-hover");
644
+ expect(result.mainColor.active).toBe("#custom-active");
645
+ expect(result.buttons.primary.textColor.color).toBe("#custom-text");
646
+ });
647
+ it("should handle deeply nested missing properties", () => {
648
+ const settings = {
649
+ brandColor: completeSettings.brandColor,
650
+ buttons: {
651
+ primary: {
652
+ textColor: {
653
+ // only color is provided as non-Auto value
654
+ color: "#FF0000",
655
+ hover: "Auto",
656
+ active: "Auto",
657
+ background: "#FFFFFF"
658
+ }
659
+ }
660
+ }
661
+ };
662
+ const result = convertSettings(settings);
663
+ expect(result.buttons.primary.textColor.color).toBe("#FF0000");
664
+ expect(result.buttons.primary.textColor.hover).toBe(completeSettings.brandColor.color);
665
+ expect(result.buttons.primary.backgroundColor).toBeDefined();
666
+ });
667
+ it("should fallback to defaultSettings when values are explicitly null", () => {
668
+ const settings = {
669
+ mainColor: {
670
+ background: null,
671
+ color: "#00FF00",
672
+ hover: "Auto",
673
+ active: "Auto",
674
+ autoHover: null,
675
+ autoActive: "#FF9999"
676
+ },
677
+ font: {
678
+ fontSize: null,
679
+ linkColor: "Auto"
680
+ }
681
+ };
682
+ const result = convertSettings(settings);
683
+ expect(result.mainColor.background).toBe(defaultSettings.mainColor.background);
684
+ expect(result.mainColor.autoHover).toBe(defaultSettings.mainColor.autoHover);
685
+ expect(result.font.fontSize).toBe(defaultSettings.font.fontSize);
686
+ expect(result.mainColor.color).toBe("#00FF00");
687
+ expect(result.mainColor.autoActive).toBe("#FF9999");
688
+ });
689
+ it("should fallback to defaultSettings when values are explicitly undefined", () => {
690
+ const settings = {
691
+ mainColor: {
692
+ background: void 0,
693
+ color: "#00FF00",
694
+ hover: "Auto",
695
+ active: "Auto"
696
+ },
697
+ buttons: {
698
+ height: void 0,
699
+ borderRadius: 16
700
+ }
701
+ };
702
+ const result = convertSettings(settings);
703
+ expect(result.mainColor.background).toBe(defaultSettings.mainColor.background);
704
+ expect(result.buttons.height).toBe(defaultSettings.buttons.height);
705
+ expect(result.mainColor.color).toBe("#00FF00");
706
+ expect(result.buttons.borderRadius).toBe(16);
707
+ });
708
+ it("should handle mixed null, undefined, and valid values correctly", () => {
709
+ const settings = {
710
+ mainColor: {
711
+ background: null,
712
+ color: void 0,
713
+ hover: "Auto",
714
+ active: "#custom-active",
715
+ autoHover: "#custom-auto-hover",
716
+ autoActive: null
717
+ },
718
+ progress: {
719
+ enabled: true,
720
+ color: null,
721
+ height: void 0
722
+ }
723
+ };
724
+ const result = convertSettings(settings);
725
+ expect(result.mainColor.background).toBe(defaultSettings.mainColor.background);
726
+ expect(result.mainColor.color).toBe(defaultSettings.mainColor.color);
727
+ expect(result.mainColor.autoActive).toBe(defaultSettings.mainColor.autoActive);
728
+ expect(result.progress.height).toBe(defaultSettings.progress.height);
729
+ expect(result.mainColor.active).toBe("#custom-active");
730
+ expect(result.mainColor.autoHover).toBe("#custom-auto-hover");
731
+ expect(result.progress.enabled).toBe(true);
732
+ expect(result.mainColor.hover).toBe("#custom-auto-hover");
733
+ expect(result.progress.color).toBe(defaultSettings.brandColor.background);
734
+ });
735
+ it("should NOT mutate defaultSettings when converting settings", () => {
736
+ convertSettings({});
737
+ convertSettings({});
738
+ convertSettings({});
739
+ expect(defaultSettings.mainColor.hover).toBe(originalDefaultMainColorHover);
740
+ expect(defaultSettings.brandColor.hover).toBe(originalDefaultBrandColorHover);
741
+ expect(defaultSettings.mainColor.hover).toBe("Auto");
742
+ expect(defaultSettings.brandColor.hover).toBe("Auto");
743
+ });
744
+ it("should return independent objects on each call", () => {
745
+ const result1 = convertSettings({});
746
+ const result2 = convertSettings({});
747
+ expect(result1).not.toBe(result2);
748
+ expect(result1.mainColor).not.toBe(result2.mainColor);
749
+ expect(result1.brandColor).not.toBe(result2.brandColor);
750
+ result1.mainColor.color = "#MODIFIED";
751
+ expect(result2.mainColor.color).not.toBe("#MODIFIED");
752
+ });
753
+ });
754
+ });