@cdx-ui/styles 0.0.1-beta.8 → 0.0.1-beta.80

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.
Files changed (66) hide show
  1. package/README.md +116 -20
  2. package/css/theme.css +201 -85
  3. package/css/vanilla.css +124 -54
  4. package/lib/commonjs/applyThemeOverride.js +154 -0
  5. package/lib/commonjs/applyThemeOverride.js.map +1 -0
  6. package/lib/commonjs/index.js +82 -0
  7. package/lib/commonjs/index.js.map +1 -1
  8. package/lib/commonjs/palette.js +262 -0
  9. package/lib/commonjs/palette.js.map +1 -0
  10. package/lib/commonjs/theming.js +255 -0
  11. package/lib/commonjs/theming.js.map +1 -0
  12. package/lib/commonjs/types.js +75 -0
  13. package/lib/commonjs/types.js.map +1 -0
  14. package/lib/commonjs/useCdxFonts.js +7 -231
  15. package/lib/commonjs/useCdxFonts.js.map +1 -1
  16. package/lib/commonjs/useForgeFonts.js +237 -0
  17. package/lib/commonjs/useForgeFonts.js.map +1 -0
  18. package/lib/module/applyThemeOverride.js +149 -0
  19. package/lib/module/applyThemeOverride.js.map +1 -0
  20. package/lib/module/index.js +11 -20
  21. package/lib/module/index.js.map +1 -1
  22. package/lib/module/palette.js +257 -0
  23. package/lib/module/palette.js.map +1 -0
  24. package/lib/module/theming.js +239 -0
  25. package/lib/module/theming.js.map +1 -0
  26. package/lib/module/types.js +71 -0
  27. package/lib/module/types.js.map +1 -0
  28. package/lib/module/useCdxFonts.js +2 -220
  29. package/lib/module/useCdxFonts.js.map +1 -1
  30. package/lib/module/useForgeFonts.js +223 -0
  31. package/lib/module/useForgeFonts.js.map +1 -0
  32. package/lib/runtime/prestige-vs-default.json +1 -0
  33. package/lib/runtime/pulse-vs-default.json +1 -0
  34. package/lib/runtime/token-to-css-var.json +672 -0
  35. package/lib/typescript/applyThemeOverride.d.ts +26 -0
  36. package/lib/typescript/applyThemeOverride.d.ts.map +1 -0
  37. package/lib/typescript/index.d.ts +8 -57
  38. package/lib/typescript/index.d.ts.map +1 -1
  39. package/lib/typescript/palette.d.ts +60 -0
  40. package/lib/typescript/palette.d.ts.map +1 -0
  41. package/lib/typescript/theming.d.ts +40 -0
  42. package/lib/typescript/theming.d.ts.map +1 -0
  43. package/lib/typescript/types.d.ts +90 -0
  44. package/lib/typescript/types.d.ts.map +1 -0
  45. package/lib/typescript/useCdxFonts.d.ts +2 -11
  46. package/lib/typescript/useCdxFonts.d.ts.map +1 -1
  47. package/lib/typescript/useForgeFonts.d.ts +12 -0
  48. package/lib/typescript/useForgeFonts.d.ts.map +1 -0
  49. package/package.json +27 -8
  50. package/runtime/prestige-vs-default.json +1 -0
  51. package/runtime/pulse-vs-default.json +1 -0
  52. package/runtime/token-to-css-var.json +672 -0
  53. package/src/__tests__/applyThemeOverride.test.ts +552 -0
  54. package/src/__tests__/generateColorScale.test.ts +296 -0
  55. package/src/__tests__/theming.test.ts +647 -0
  56. package/src/applyThemeOverride.ts +139 -0
  57. package/src/index.ts +36 -60
  58. package/src/palette.ts +307 -0
  59. package/src/theming.ts +268 -0
  60. package/src/types.ts +112 -0
  61. package/src/useCdxFonts.ts +2 -230
  62. package/src/useForgeFonts.ts +230 -0
  63. package/tokens/presets/.manifest.json +3 -3
  64. package/tokens/presets/poise.json +319 -39
  65. package/tokens/presets/prestige.json +1 -1
  66. package/tokens/presets/pulse.json +1 -1
@@ -0,0 +1,552 @@
1
+ import { applyThemeOverride, DEFAULT_PRESET } from '../applyThemeOverride';
2
+ import type { ApplyThemeOverrideResult } from '../applyThemeOverride';
3
+ import type { RuntimeMap } from '../theming';
4
+ import type { ThemeOverride } from '../types';
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // Mocks
8
+ // ---------------------------------------------------------------------------
9
+
10
+ const mockUpdateCSSVariables = jest.fn();
11
+
12
+ jest.mock('uniwind', () => ({
13
+ Uniwind: {
14
+ updateCSSVariables: (...args: unknown[]) => mockUpdateCSSVariables(...args),
15
+ },
16
+ }));
17
+
18
+ jest.mock('react-native', () => ({
19
+ Platform: { OS: 'ios' },
20
+ }));
21
+
22
+ jest.mock(
23
+ '../../runtime/prestige-vs-default.json',
24
+ () => ({
25
+ modes: {
26
+ light: {
27
+ color: {
28
+ surface: {
29
+ background: { $type: 'color', $value: '#faf8f5' },
30
+ },
31
+ },
32
+ },
33
+ dark: {
34
+ color: {
35
+ surface: {
36
+ background: { $type: 'color', $value: '#1c1917' },
37
+ },
38
+ },
39
+ },
40
+ },
41
+ platform: {
42
+ ios: {
43
+ font: {
44
+ sans: { $type: 'fontFamily', $value: 'SF Pro Display' },
45
+ },
46
+ },
47
+ web: {
48
+ font: {
49
+ sans: { $type: 'fontFamily', $value: 'Libre Franklin' },
50
+ },
51
+ },
52
+ },
53
+ }),
54
+ { virtual: true },
55
+ );
56
+
57
+ jest.mock(
58
+ '../../runtime/pulse-vs-default.json',
59
+ () => ({
60
+ modes: {
61
+ light: {
62
+ color: {
63
+ surface: {
64
+ background: { $type: 'color', $value: '#f0f4ff' },
65
+ },
66
+ },
67
+ },
68
+ dark: {
69
+ color: {
70
+ surface: {
71
+ background: { $type: 'color', $value: '#0a0e1a' },
72
+ },
73
+ },
74
+ },
75
+ },
76
+ }),
77
+ { virtual: true },
78
+ );
79
+
80
+ jest.mock(
81
+ '../../runtime/token-to-css-var.json',
82
+ () => ({
83
+ 'color.brand.50': '--color-brand-50',
84
+ 'color.brand.100': '--color-brand-100',
85
+ 'color.brand.200': '--color-brand-200',
86
+ 'color.brand.300': '--color-brand-300',
87
+ 'color.brand.400': '--color-brand-400',
88
+ 'color.brand.500': '--color-brand-500',
89
+ 'color.brand.600': '--color-brand-600',
90
+ 'color.brand.700': '--color-brand-700',
91
+ 'color.brand.800': '--color-brand-800',
92
+ 'color.brand.900': '--color-brand-900',
93
+ 'color.brand.950': '--color-brand-950',
94
+ 'color.brand.input': '--color-brand-input',
95
+ 'color.accent.50': '--color-accent-50',
96
+ 'color.accent.100': '--color-accent-100',
97
+ 'color.accent.500': '--color-accent-500',
98
+ 'color.accent.input': '--color-accent-input',
99
+ 'color.base.50': '--color-base-50',
100
+ 'color.base.500': '--color-base-500',
101
+ 'color.base.950': '--color-base-950',
102
+ 'font.display': '--font-display',
103
+ 'modes.light.color.surface.background': '--color-surface-background',
104
+ 'modes.dark.color.surface.background': '--color-surface-background',
105
+ 'modes.light.color.content.primary': '--color-content-primary',
106
+ 'modes.dark.color.content.primary': '--color-content-primary',
107
+ 'modes.light.font.display': '--font-display',
108
+ 'modes.dark.font.display': '--font-display',
109
+ 'platform.web.font.sans': '--font-sans',
110
+ 'platform.ios.font.sans': '--font-sans',
111
+ 'platform.android.font.sans': '--font-sans',
112
+ }),
113
+ { virtual: true },
114
+ );
115
+
116
+ // ---------------------------------------------------------------------------
117
+ // Test runtime map (used for explicit runtimeMap option tests)
118
+ // ---------------------------------------------------------------------------
119
+
120
+ const TEST_RUNTIME_MAP: RuntimeMap = {
121
+ 'color.brand.50': '--color-brand-50',
122
+ 'color.brand.100': '--color-brand-100',
123
+ 'color.brand.200': '--color-brand-200',
124
+ 'color.brand.300': '--color-brand-300',
125
+ 'color.brand.400': '--color-brand-400',
126
+ 'color.brand.500': '--color-brand-500',
127
+ 'color.brand.600': '--color-brand-600',
128
+ 'color.brand.700': '--color-brand-700',
129
+ 'color.brand.800': '--color-brand-800',
130
+ 'color.brand.900': '--color-brand-900',
131
+ 'color.brand.950': '--color-brand-950',
132
+ 'color.brand.input': '--color-brand-input',
133
+ 'color.accent.50': '--color-accent-50',
134
+ 'color.accent.100': '--color-accent-100',
135
+ 'color.accent.500': '--color-accent-500',
136
+ 'color.accent.input': '--color-accent-input',
137
+ 'color.base.50': '--color-base-50',
138
+ 'color.base.500': '--color-base-500',
139
+ 'color.base.950': '--color-base-950',
140
+ 'font.display': '--font-display',
141
+ 'modes.light.color.surface.background': '--color-surface-background',
142
+ 'modes.dark.color.surface.background': '--color-surface-background',
143
+ 'modes.light.color.content.primary': '--color-content-primary',
144
+ 'modes.dark.color.content.primary': '--color-content-primary',
145
+ 'modes.light.font.display': '--font-display',
146
+ 'modes.dark.font.display': '--font-display',
147
+ 'platform.web.font.sans': '--font-sans',
148
+ 'platform.ios.font.sans': '--font-sans',
149
+ 'platform.android.font.sans': '--font-sans',
150
+ };
151
+
152
+ // ---------------------------------------------------------------------------
153
+ // Helpers
154
+ // ---------------------------------------------------------------------------
155
+
156
+ beforeEach(() => {
157
+ mockUpdateCSSVariables.mockClear();
158
+ });
159
+
160
+ // ---------------------------------------------------------------------------
161
+ // DEFAULT_PRESET
162
+ // ---------------------------------------------------------------------------
163
+
164
+ describe('DEFAULT_PRESET', () => {
165
+ it('equals "poise"', () => {
166
+ expect(DEFAULT_PRESET).toBe('poise');
167
+ });
168
+ });
169
+
170
+ // ---------------------------------------------------------------------------
171
+ // applyThemeOverride
172
+ // ---------------------------------------------------------------------------
173
+
174
+ describe('applyThemeOverride', () => {
175
+ describe('successful apply (default preset + override)', () => {
176
+ it('applies brand colour override with default preset', () => {
177
+ const override: ThemeOverride = {
178
+ $extensions: {
179
+ 'com.forge.ui.themeOverride': {
180
+ basePreset: 'poise',
181
+ schemaVersion: '1.0.0',
182
+ },
183
+ },
184
+ inputs: { brandPrimary: '#0052cc' },
185
+ };
186
+
187
+ const result = applyThemeOverride(override, {
188
+ runtimeMap: TEST_RUNTIME_MAP,
189
+ runtimePlatform: 'web',
190
+ });
191
+
192
+ expect(result.applied).toBe(true);
193
+ if (result.applied) {
194
+ expect(result.light['--color-brand-input']).toBe('#0052cc');
195
+ expect(result.dark['--color-brand-input']).toBe('#0052cc');
196
+ expect(result.light['--color-brand-500']).toBeDefined();
197
+ }
198
+ expect(mockUpdateCSSVariables).toHaveBeenCalledTimes(2);
199
+ expect(mockUpdateCSSVariables).toHaveBeenCalledWith('light', expect.any(Object));
200
+ expect(mockUpdateCSSVariables).toHaveBeenCalledWith('dark', expect.any(Object));
201
+ });
202
+
203
+ it('applies a base palette from a basePrimary input', () => {
204
+ const override: ThemeOverride = {
205
+ $extensions: {
206
+ 'com.forge.ui.themeOverride': {
207
+ basePreset: 'poise',
208
+ schemaVersion: '1.0.0',
209
+ },
210
+ },
211
+ inputs: { brandPrimary: '#0052cc', basePrimary: '#61666c' },
212
+ };
213
+
214
+ const result = applyThemeOverride(override, {
215
+ runtimeMap: TEST_RUNTIME_MAP,
216
+ runtimePlatform: 'web',
217
+ });
218
+
219
+ expect(result.applied).toBe(true);
220
+ if (result.applied) {
221
+ expect(result.light['--color-base-50']).toBeDefined();
222
+ expect(result.light['--color-base-500']).toBeDefined();
223
+ expect(result.dark['--color-base-950']).toBeDefined();
224
+ }
225
+ });
226
+
227
+ it('applies font input override', () => {
228
+ const override: ThemeOverride = {
229
+ $extensions: {
230
+ 'com.forge.ui.themeOverride': {
231
+ basePreset: 'poise',
232
+ schemaVersion: '1.0.0',
233
+ },
234
+ },
235
+ inputs: { displayFont: 'Crimson Pro' },
236
+ };
237
+
238
+ const result = applyThemeOverride(override, {
239
+ runtimeMap: TEST_RUNTIME_MAP,
240
+ runtimePlatform: 'web',
241
+ });
242
+
243
+ expect(result.applied).toBe(true);
244
+ if (result.applied) {
245
+ expect(result.light['--font-display']).toBe('Crimson Pro');
246
+ expect(result.dark['--font-display']).toBe('Crimson Pro');
247
+ }
248
+ });
249
+
250
+ it('applies explicit per-mode overrides', () => {
251
+ const override: ThemeOverride = {
252
+ $extensions: {
253
+ 'com.forge.ui.themeOverride': {
254
+ basePreset: 'poise',
255
+ schemaVersion: '1.0.0',
256
+ },
257
+ },
258
+ overrides: {
259
+ light: { 'color.surface.background': '#fafafa' },
260
+ dark: { 'color.surface.background': '#1a1a1a' },
261
+ },
262
+ };
263
+
264
+ const result = applyThemeOverride(override, {
265
+ runtimeMap: TEST_RUNTIME_MAP,
266
+ runtimePlatform: 'web',
267
+ });
268
+
269
+ expect(result.applied).toBe(true);
270
+ if (result.applied) {
271
+ expect(result.light['--color-surface-background']).toBe('#fafafa');
272
+ expect(result.dark['--color-surface-background']).toBe('#1a1a1a');
273
+ }
274
+ });
275
+
276
+ it('resolves alias overrides to var() references end-to-end', () => {
277
+ const override: ThemeOverride = {
278
+ $extensions: {
279
+ 'com.forge.ui.themeOverride': {
280
+ basePreset: 'poise',
281
+ schemaVersion: '1.0.0',
282
+ },
283
+ },
284
+ inputs: { brandPrimary: '#0052cc' },
285
+ overrides: {
286
+ light: { 'color.surface.background': '{color.brand.700}' },
287
+ dark: { 'color.surface.background': '{color.brand.300}' },
288
+ },
289
+ };
290
+
291
+ const result = applyThemeOverride(override, {
292
+ runtimeMap: TEST_RUNTIME_MAP,
293
+ runtimePlatform: 'web',
294
+ });
295
+
296
+ expect(result.applied).toBe(true);
297
+ if (result.applied) {
298
+ expect(result.light['--color-surface-background']).toBe('var(--color-brand-700)');
299
+ expect(result.dark['--color-surface-background']).toBe('var(--color-brand-300)');
300
+ // The referenced primitive is present in the same batch (palette
301
+ // generation emitted it), so the var() reference resolves.
302
+ expect(result.light['--color-brand-700']).toBeDefined();
303
+ }
304
+ expect(mockUpdateCSSVariables).toHaveBeenCalledWith(
305
+ 'light',
306
+ expect.objectContaining({ '--color-surface-background': 'var(--color-brand-700)' }),
307
+ );
308
+ });
309
+ });
310
+
311
+ describe('non-default preset patch + override', () => {
312
+ it('applies prestige preset patch before FI override', () => {
313
+ const override: ThemeOverride = {
314
+ $extensions: {
315
+ 'com.forge.ui.themeOverride': {
316
+ basePreset: 'prestige',
317
+ schemaVersion: '1.0.0',
318
+ },
319
+ },
320
+ inputs: { brandPrimary: '#8b5cf6' },
321
+ };
322
+
323
+ const result = applyThemeOverride(override, {
324
+ runtimeMap: TEST_RUNTIME_MAP,
325
+ runtimePlatform: 'ios',
326
+ });
327
+
328
+ expect(result.applied).toBe(true);
329
+ if (result.applied) {
330
+ expect(result.light['--color-surface-background']).toBe('#faf8f5');
331
+ expect(result.dark['--color-surface-background']).toBe('#1c1917');
332
+ expect(result.light['--color-brand-input']).toBe('#8b5cf6');
333
+ expect(result.light['--font-sans']).toBe('SF Pro Display');
334
+ }
335
+ });
336
+
337
+ it('FI override wins over preset patch on collision', () => {
338
+ const override: ThemeOverride = {
339
+ $extensions: {
340
+ 'com.forge.ui.themeOverride': {
341
+ basePreset: 'prestige',
342
+ schemaVersion: '1.0.0',
343
+ },
344
+ },
345
+ overrides: {
346
+ light: { 'color.surface.background': '#custom1' },
347
+ dark: { 'color.surface.background': '#custom2' },
348
+ },
349
+ };
350
+
351
+ const result = applyThemeOverride(override, {
352
+ runtimeMap: TEST_RUNTIME_MAP,
353
+ runtimePlatform: 'web',
354
+ });
355
+
356
+ expect(result.applied).toBe(true);
357
+ if (result.applied) {
358
+ expect(result.light['--color-surface-background']).toBe('#custom1');
359
+ expect(result.dark['--color-surface-background']).toBe('#custom2');
360
+ }
361
+ });
362
+
363
+ it('applies pulse preset patch with metadata-only override', () => {
364
+ const override: ThemeOverride = {
365
+ $extensions: {
366
+ 'com.forge.ui.themeOverride': {
367
+ basePreset: 'pulse',
368
+ schemaVersion: '1.0.0',
369
+ },
370
+ },
371
+ };
372
+
373
+ const result = applyThemeOverride(override, {
374
+ runtimeMap: TEST_RUNTIME_MAP,
375
+ runtimePlatform: 'web',
376
+ });
377
+
378
+ expect(result.applied).toBe(true);
379
+ if (result.applied) {
380
+ expect(result.light['--color-surface-background']).toBe('#f0f4ff');
381
+ expect(result.dark['--color-surface-background']).toBe('#0a0e1a');
382
+ }
383
+ });
384
+ });
385
+
386
+ describe('schema version skip', () => {
387
+ it('returns early without calling Uniwind when schema version is unsupported', () => {
388
+ const override: ThemeOverride = {
389
+ $extensions: {
390
+ 'com.forge.ui.themeOverride': {
391
+ basePreset: 'poise',
392
+ schemaVersion: '99.0.0',
393
+ },
394
+ },
395
+ inputs: { brandPrimary: '#ff0000' },
396
+ };
397
+
398
+ const result = applyThemeOverride(override, {
399
+ runtimeMap: TEST_RUNTIME_MAP,
400
+ runtimePlatform: 'web',
401
+ });
402
+
403
+ expect(result.applied).toBe(false);
404
+ if (!result.applied) {
405
+ expect(result.reason).toBe('unsupported_schema_version');
406
+ }
407
+ expect(mockUpdateCSSVariables).not.toHaveBeenCalled();
408
+ });
409
+ });
410
+
411
+ describe('metadata-only override no-op', () => {
412
+ it('does not call Uniwind when override has only $extensions with default preset', () => {
413
+ const override: ThemeOverride = {
414
+ $extensions: {
415
+ 'com.forge.ui.themeOverride': {
416
+ basePreset: 'poise',
417
+ schemaVersion: '1.0.0',
418
+ },
419
+ },
420
+ };
421
+
422
+ const result = applyThemeOverride(override, {
423
+ runtimeMap: TEST_RUNTIME_MAP,
424
+ runtimePlatform: 'web',
425
+ });
426
+
427
+ expect(result.applied).toBe(false);
428
+ if (!result.applied) {
429
+ expect(result.reason).toBe('no_theme_changes');
430
+ }
431
+ expect(mockUpdateCSSVariables).not.toHaveBeenCalled();
432
+ });
433
+
434
+ it('does not call Uniwind when override has empty inputs/overrides with default preset', () => {
435
+ const override: ThemeOverride = {
436
+ $extensions: {
437
+ 'com.forge.ui.themeOverride': {
438
+ basePreset: 'poise',
439
+ schemaVersion: '1.0.0',
440
+ },
441
+ },
442
+ inputs: {},
443
+ overrides: {},
444
+ };
445
+
446
+ const result = applyThemeOverride(override, {
447
+ runtimeMap: TEST_RUNTIME_MAP,
448
+ runtimePlatform: 'web',
449
+ });
450
+
451
+ expect(result.applied).toBe(false);
452
+ if (!result.applied) {
453
+ expect(result.reason).toBe('no_theme_changes');
454
+ }
455
+ expect(mockUpdateCSSVariables).not.toHaveBeenCalled();
456
+ });
457
+ });
458
+
459
+ describe('default runtimeMap', () => {
460
+ it('uses bundled token-to-css-var.json when runtimeMap is not provided', () => {
461
+ const override: ThemeOverride = {
462
+ $extensions: {
463
+ 'com.forge.ui.themeOverride': {
464
+ basePreset: 'poise',
465
+ schemaVersion: '1.0.0',
466
+ },
467
+ },
468
+ inputs: { brandPrimary: '#0052cc' },
469
+ };
470
+
471
+ const result = applyThemeOverride(override, { runtimePlatform: 'web' });
472
+
473
+ expect(result.applied).toBe(true);
474
+ if (result.applied) {
475
+ expect(result.light['--color-brand-input']).toBe('#0052cc');
476
+ }
477
+ });
478
+ });
479
+
480
+ describe('platform auto-detection fallback', () => {
481
+ it('auto-detects platform from Platform.OS when runtimePlatform is not provided', () => {
482
+ const override: ThemeOverride = {
483
+ $extensions: {
484
+ 'com.forge.ui.themeOverride': {
485
+ basePreset: 'prestige',
486
+ schemaVersion: '1.0.0',
487
+ },
488
+ },
489
+ inputs: { brandPrimary: '#0052cc' },
490
+ };
491
+
492
+ const result = applyThemeOverride(override) as Extract<
493
+ ApplyThemeOverrideResult,
494
+ { applied: true }
495
+ >;
496
+
497
+ expect(result.applied).toBe(true);
498
+ expect(result.light['--font-sans']).toBe('SF Pro Display');
499
+ });
500
+
501
+ it('falls back to web when react-native is unavailable', () => {
502
+ jest.resetModules();
503
+ jest.doMock('react-native', () => {
504
+ throw new Error('Cannot find module');
505
+ });
506
+
507
+ // Re-import to get fresh module with the new mock
508
+ const { applyThemeOverride: freshApply } = jest.requireActual('../applyThemeOverride');
509
+
510
+ const override: ThemeOverride = {
511
+ $extensions: {
512
+ 'com.forge.ui.themeOverride': {
513
+ basePreset: 'prestige',
514
+ schemaVersion: '1.0.0',
515
+ },
516
+ },
517
+ inputs: { brandPrimary: '#0052cc' },
518
+ };
519
+
520
+ const result = freshApply(override, { runtimeMap: TEST_RUNTIME_MAP });
521
+
522
+ expect(result.applied).toBe(true);
523
+ if (result.applied) {
524
+ expect(result.light['--font-sans']).toBe('Libre Franklin');
525
+ }
526
+ });
527
+ });
528
+
529
+ describe('when default preset is skipped', () => {
530
+ it('does not apply preset patch when basePreset is poise', () => {
531
+ const override: ThemeOverride = {
532
+ $extensions: {
533
+ 'com.forge.ui.themeOverride': {
534
+ basePreset: 'poise',
535
+ schemaVersion: '1.0.0',
536
+ },
537
+ },
538
+ inputs: { brandPrimary: '#0052cc' },
539
+ };
540
+
541
+ const result = applyThemeOverride(override, {
542
+ runtimeMap: TEST_RUNTIME_MAP,
543
+ runtimePlatform: 'web',
544
+ });
545
+
546
+ expect(result.applied).toBe(true);
547
+ if (result.applied) {
548
+ expect(result.light['--color-surface-background']).toBeUndefined();
549
+ }
550
+ });
551
+ });
552
+ });