@happyvertical/smrt-ui 0.53.1 → 0.53.3
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/package.json +3 -3
- package/dist/actions/__tests__/ripple.test.js +0 -82
- package/dist/actions/__tests__/swipe-dismiss.test.js +0 -69
- package/dist/components/calendar/__tests__/CalendarView.test.js +0 -226
- package/dist/components/calendar/__tests__/calendar-model.test.js +0 -138
- package/dist/components/chat/__tests__/chat-primitives.test.js +0 -118
- package/dist/components/data/__tests__/CollectionList.test.js +0 -37
- package/dist/components/data/__tests__/DataTable.test.js +0 -807
- package/dist/components/data/__tests__/DataTableConformance.test.js +0 -212
- package/dist/components/data/__tests__/DataTableController.test.js +0 -371
- package/dist/components/data/__tests__/DataTableIdentity.test.js +0 -29
- package/dist/components/data/__tests__/DataTableLayout.test.js +0 -195
- package/dist/components/data/__tests__/DataTablePerformance.test.js +0 -21
- package/dist/components/data/__tests__/DataTableResponsive.test.js +0 -80
- package/dist/components/data/__tests__/DataTableVirtualization.test.js +0 -80
- package/dist/components/data/__tests__/DataTableVirtualizationComponent.test.js +0 -255
- package/dist/components/data/__tests__/SortableHeader.test.js +0 -101
- package/dist/components/data/__tests__/data-surface.test.js +0 -746
- package/dist/components/data/__tests__/data-table-helpers.test.js +0 -36
- package/dist/components/data/__tests__/data-table-surface.test.js +0 -49
- package/dist/components/data/__tests__/link-step-surface.test.js +0 -172
- package/dist/components/data/__tests__/list-sort-state.svelte.test.js +0 -71
- package/dist/components/data/__tests__/list-sort.test.js +0 -91
- package/dist/components/data/__tests__/mounted-data-surface.test.js +0 -794
- package/dist/components/data/__tests__/responsive-table.fixture.svelte +0 -29
- package/dist/components/data/__tests__/responsive-table.fixture.svelte.d.ts +0 -7
- package/dist/components/data/__tests__/responsive-table.fixture.svelte.d.ts.map +0 -1
- package/dist/components/data/__tests__/surface-navigation.test.js +0 -121
- package/dist/components/display/__tests__/ConfidenceBadge.test.js +0 -109
- package/dist/components/display/__tests__/CurrencyDisplay.test.js +0 -304
- package/dist/components/display/__tests__/CurrencyDisplayI18nHarness.svelte +0 -20
- package/dist/components/display/__tests__/CurrencyDisplayI18nHarness.svelte.d.ts +0 -19
- package/dist/components/display/__tests__/CurrencyDisplayI18nHarness.svelte.d.ts.map +0 -1
- package/dist/components/display/__tests__/CurrencyDisplaySsrHarness.svelte +0 -7
- package/dist/components/display/__tests__/CurrencyDisplaySsrHarness.svelte.d.ts +0 -19
- package/dist/components/display/__tests__/CurrencyDisplaySsrHarness.svelte.d.ts.map +0 -1
- package/dist/components/display/__tests__/DateDisplay.test.js +0 -195
- package/dist/components/display/__tests__/Icon.test.js +0 -223
- package/dist/components/display/__tests__/StatusBadge.test.js +0 -191
- package/dist/components/feedback/__tests__/ConfirmDialog.test.js +0 -181
- package/dist/components/feedback/__tests__/LoadingOverlay.test.js +0 -113
- package/dist/components/feedback/__tests__/Modal.test.js +0 -72
- package/dist/components/feedback/__tests__/PhoneSheet.test.js +0 -101
- package/dist/components/feedback/__tests__/ProgressBar.test.js +0 -89
- package/dist/components/feedback/__tests__/WorkingStrip.test.js +0 -172
- package/dist/components/feedback/__tests__/confirm-message.fixture.svelte +0 -9
- package/dist/components/feedback/__tests__/confirm-message.fixture.svelte.d.ts +0 -19
- package/dist/components/feedback/__tests__/confirm-message.fixture.svelte.d.ts.map +0 -1
- package/dist/components/feedback/__tests__/toast.test.js +0 -190
- package/dist/components/forms/__tests__/CameraCapture.test.js +0 -504
- package/dist/components/forms/__tests__/Combobox.test.js +0 -354
- package/dist/components/forms/__tests__/ControlHitArea.test.js +0 -73
- package/dist/components/forms/__tests__/DictationButton.test.js +0 -176
- package/dist/components/forms/__tests__/Fieldset.test.js +0 -37
- package/dist/components/forms/__tests__/Form.test.js +0 -201
- package/dist/components/forms/__tests__/FormActionBar.test.js +0 -22
- package/dist/components/forms/__tests__/FormGroup.test.js +0 -48
- package/dist/components/forms/__tests__/Input.test.js +0 -49
- package/dist/components/forms/__tests__/Listbox.test.js +0 -303
- package/dist/components/forms/__tests__/MultiSelect.test.js +0 -281
- package/dist/components/forms/__tests__/SearchInput.test.js +0 -92
- package/dist/components/forms/__tests__/Select.test.js +0 -37
- package/dist/components/forms/__tests__/SignaturePad.test.js +0 -338
- package/dist/components/forms/__tests__/StagedControlReview.test.js +0 -702
- package/dist/components/forms/__tests__/Textarea.test.js +0 -39
- package/dist/components/forms/__tests__/Toggle.test.js +0 -87
- package/dist/components/forms/__tests__/camera-capture-session.test.js +0 -207
- package/dist/components/forms/__tests__/capture-form-retry.test.js +0 -166
- package/dist/components/forms/__tests__/capture-form.fixture.svelte +0 -38
- package/dist/components/forms/__tests__/capture-form.fixture.svelte.d.ts +0 -10
- package/dist/components/forms/__tests__/capture-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/capture-test-env.d.ts +0 -70
- package/dist/components/forms/__tests__/capture-test-env.d.ts.map +0 -1
- package/dist/components/forms/__tests__/capture-test-env.js +0 -122
- package/dist/components/forms/__tests__/capture-touch.fixture.svelte +0 -15
- package/dist/components/forms/__tests__/capture-touch.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/capture-touch.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/combobox-form.fixture.svelte +0 -29
- package/dist/components/forms/__tests__/combobox-form.fixture.svelte.d.ts +0 -14
- package/dist/components/forms/__tests__/combobox-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/combobox-labels.fixture.svelte +0 -19
- package/dist/components/forms/__tests__/combobox-labels.fixture.svelte.d.ts +0 -11
- package/dist/components/forms/__tests__/combobox-labels.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/composite-controls.fixture.svelte +0 -47
- package/dist/components/forms/__tests__/composite-controls.fixture.svelte.d.ts +0 -12
- package/dist/components/forms/__tests__/composite-controls.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/composite-controls.test.js +0 -128
- package/dist/components/forms/__tests__/composite-registration.fixture.svelte +0 -29
- package/dist/components/forms/__tests__/composite-registration.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/composite-registration.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/composite-user-edit.fixture.svelte +0 -41
- package/dist/components/forms/__tests__/composite-user-edit.fixture.svelte.d.ts +0 -13
- package/dist/components/forms/__tests__/composite-user-edit.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/control-interaction.test.js +0 -3421
- package/dist/components/forms/__tests__/control-proposals.test.js +0 -63
- package/dist/components/forms/__tests__/core-controls.fixture.svelte +0 -50
- package/dist/components/forms/__tests__/core-controls.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/core-controls.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/core-controls.test.js +0 -311
- package/dist/components/forms/__tests__/decimal-sliders.fixture.svelte +0 -25
- package/dist/components/forms/__tests__/decimal-sliders.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/decimal-sliders.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/dictation-recording.test.js +0 -582
- package/dist/components/forms/__tests__/dictation.test.js +0 -486
- package/dist/components/forms/__tests__/form-attachment.fixture.svelte +0 -28
- package/dist/components/forms/__tests__/form-attachment.fixture.svelte.d.ts +0 -11
- package/dist/components/forms/__tests__/form-attachment.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-group-input.fixture.svelte +0 -16
- package/dist/components/forms/__tests__/form-group-input.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/form-group-input.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-retry-form.fixture.svelte +0 -31
- package/dist/components/forms/__tests__/form-retry-form.fixture.svelte.d.ts +0 -13
- package/dist/components/forms/__tests__/form-retry-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-retry-form.test.js +0 -107
- package/dist/components/forms/__tests__/hidden-controls-form-retry.test.js +0 -69
- package/dist/components/forms/__tests__/hidden-controls-form.fixture.svelte +0 -29
- package/dist/components/forms/__tests__/hidden-controls-form.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/hidden-controls-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/listbox-form.fixture.svelte +0 -27
- package/dist/components/forms/__tests__/listbox-form.fixture.svelte.d.ts +0 -13
- package/dist/components/forms/__tests__/listbox-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/long-press.test.js +0 -175
- package/dist/components/forms/__tests__/multiselect-form.fixture.svelte +0 -27
- package/dist/components/forms/__tests__/multiselect-form.fixture.svelte.d.ts +0 -13
- package/dist/components/forms/__tests__/multiselect-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/native-file-field.test.js +0 -177
- package/dist/components/forms/__tests__/place-picker.fixture.svelte +0 -33
- package/dist/components/forms/__tests__/place-picker.fixture.svelte.d.ts +0 -12
- package/dist/components/forms/__tests__/place-picker.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/segmented-posting.fixture.svelte +0 -28
- package/dist/components/forms/__tests__/segmented-posting.fixture.svelte.d.ts +0 -12
- package/dist/components/forms/__tests__/segmented-posting.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/segmented-posting.test.js +0 -92
- package/dist/components/forms/__tests__/select-interaction.fixture.svelte +0 -25
- package/dist/components/forms/__tests__/select-interaction.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/select-interaction.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/signature-pad-logic.test.js +0 -54
- package/dist/components/forms/__tests__/staged-review-fieldset.fixture.svelte +0 -21
- package/dist/components/forms/__tests__/staged-review-fieldset.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/staged-review-fieldset.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/staged-review-outer-fieldset.fixture.svelte +0 -23
- package/dist/components/forms/__tests__/staged-review-outer-fieldset.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/staged-review-outer-fieldset.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/staged-review.fixture.svelte +0 -56
- package/dist/components/forms/__tests__/staged-review.fixture.svelte.d.ts +0 -12
- package/dist/components/forms/__tests__/staged-review.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/touch-density.fixture.svelte +0 -34
- package/dist/components/forms/__tests__/touch-density.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/touch-density.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/touch-density.test.js +0 -66
- package/dist/components/forms/form-retry/__tests__/boundaries.test.js +0 -23
- package/dist/components/forms/form-retry/__tests__/content-digest.test.js +0 -70
- package/dist/components/forms/form-retry/__tests__/controller.test.js +0 -802
- package/dist/components/forms/form-retry/__tests__/fake-kit.d.ts +0 -82
- package/dist/components/forms/form-retry/__tests__/fake-kit.d.ts.map +0 -1
- package/dist/components/forms/form-retry/__tests__/fake-kit.js +0 -180
- package/dist/components/forms/form-retry/__tests__/form-draft.test.js +0 -169
- package/dist/components/forms/form-retry/__tests__/ssr.test.js +0 -37
- package/dist/components/forms/form-retry/__tests__/storage.d.ts +0 -26
- package/dist/components/forms/form-retry/__tests__/storage.d.ts.map +0 -1
- package/dist/components/forms/form-retry/__tests__/storage.js +0 -63
- package/dist/components/forms/form-retry/__tests__/submission-key.test.js +0 -236
- package/dist/components/forms/form-retry/__tests__/submitted-draft.test.js +0 -334
- package/dist/components/layout/__tests__/Container.test.js +0 -62
- package/dist/components/layout/__tests__/EmptyState.test.js +0 -83
- package/dist/components/layout/__tests__/Footer.test.js +0 -50
- package/dist/components/layout/__tests__/Grid.test.js +0 -121
- package/dist/components/layout/__tests__/Header.test.js +0 -48
- package/dist/components/layout/__tests__/Masthead.test.js +0 -93
- package/dist/components/layout/__tests__/PageHeader.test.js +0 -166
- package/dist/components/layout/__tests__/SummaryCard.test.js +0 -104
- package/dist/components/nav/__tests__/FilterChips.test.js +0 -94
- package/dist/components/nav/__tests__/LinkTabs.test.js +0 -117
- package/dist/components/nav/__tests__/Tabs.test.js +0 -128
- package/dist/components/roles/__tests__/RoleSelector.test.js +0 -134
- package/dist/components/ui/__tests__/Badge.test.js +0 -76
- package/dist/components/ui/__tests__/Button.test.js +0 -166
- package/dist/components/ui/__tests__/Card.test.js +0 -103
- package/dist/components/ui/__tests__/IconToggle.test.js +0 -59
- package/dist/components/ui/__tests__/IconToggleGroup.test.js +0 -30
- package/dist/components/ui/__tests__/Pagination.test.js +0 -113
- package/dist/components/ui/__tests__/Popover.test.js +0 -44
- package/dist/components/ui/__tests__/dropdown-popover-icon.test.js +0 -125
- package/dist/components/ui/__tests__/gap-primitives-interactive.test.js +0 -112
- package/dist/components/ui/__tests__/gap-primitives.test.js +0 -84
- package/dist/components/ui/__tests__/interaction-primitives.fixture.svelte +0 -13
- package/dist/components/ui/__tests__/interaction-primitives.fixture.svelte.d.ts +0 -19
- package/dist/components/ui/__tests__/interaction-primitives.fixture.svelte.d.ts.map +0 -1
- package/dist/components/ui/__tests__/interaction-primitives.test.js +0 -31
- package/dist/components/ui/__tests__/phone-touch-targets.test.js +0 -39
- package/dist/i18n/__tests__/i18n.test.js +0 -74
- package/dist/i18n/__tests__/render-parity.spec.js +0 -37
- package/dist/svelte/__tests__/playground.test.js +0 -20
- package/dist/themes/__tests__/control-boundary-contrast.test.js +0 -112
- package/dist/themes/__tests__/create-theme.test.js +0 -79
- package/dist/themes/__tests__/css-generator.test.js +0 -129
- package/dist/themes/__tests__/happyvertical-theme.test.js +0 -231
- package/dist/themes/__tests__/registry.test.js +0 -43
- package/dist/themes/__tests__/styles-lockstep.test.js +0 -32
- package/dist/themes/__tests__/theme-provider.test.js +0 -147
- package/dist/themes/__tests__/theme-script.test.js +0 -130
- package/dist/themes/__tests__/token-aliases.test.js +0 -178
- package/dist/utils/forms/__tests__/formatters.test.js +0 -27
- package/dist/utils/theme/__tests__/color.test.js +0 -89
- package/dist/utils/theme/__tests__/typography.test.js +0 -11
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the themeScript() pre-paint bootstrap generator. The generated
|
|
3
|
-
* script must mirror ThemeProvider's persistence resolution so apps stop
|
|
4
|
-
* hand-duplicating it in app.html.
|
|
5
|
-
*/
|
|
6
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
7
|
-
import { createTheme, registerTheme } from '../create-theme.js';
|
|
8
|
-
import { themeScript } from '../theme-script.js';
|
|
9
|
-
function mockSystemDark(matches) {
|
|
10
|
-
window.matchMedia = vi.fn().mockImplementation((query) => ({
|
|
11
|
-
matches,
|
|
12
|
-
media: query,
|
|
13
|
-
}));
|
|
14
|
-
}
|
|
15
|
-
function run(script) {
|
|
16
|
-
// biome-ignore lint/security/noGlobalEval: the browser evals this inline bootstrap; testing that is the point
|
|
17
|
-
(0, eval)(script);
|
|
18
|
-
}
|
|
19
|
-
describe('themeScript', () => {
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
vi.restoreAllMocks();
|
|
22
|
-
localStorage.clear();
|
|
23
|
-
document.documentElement.removeAttribute('data-theme');
|
|
24
|
-
document.documentElement.removeAttribute('data-color-scheme');
|
|
25
|
-
document.documentElement.classList.remove('dark');
|
|
26
|
-
});
|
|
27
|
-
it("uses Vitest's original jsdom Storage rather than Node host storage", () => {
|
|
28
|
-
expect(localStorage).toBe(globalThis.jsdom
|
|
29
|
-
.window.localStorage);
|
|
30
|
-
});
|
|
31
|
-
it('resolves system preference when nothing is stored', () => {
|
|
32
|
-
mockSystemDark(true);
|
|
33
|
-
run(themeScript({ preset: 'material' }));
|
|
34
|
-
expect(document.documentElement.getAttribute('data-theme')).toBe('material');
|
|
35
|
-
expect(document.documentElement.getAttribute('data-color-scheme')).toBe('dark');
|
|
36
|
-
expect(document.documentElement.classList.contains('dark')).toBe(true);
|
|
37
|
-
});
|
|
38
|
-
it('honours a stored scheme and preset over system and defaults', () => {
|
|
39
|
-
mockSystemDark(true);
|
|
40
|
-
localStorage.setItem('smrt-theme', JSON.stringify({ preset: 'studio', colorScheme: 'light' }));
|
|
41
|
-
run(themeScript({ preset: 'material' }));
|
|
42
|
-
expect(document.documentElement.getAttribute('data-theme')).toBe('studio');
|
|
43
|
-
expect(document.documentElement.getAttribute('data-color-scheme')).toBe('light');
|
|
44
|
-
expect(document.documentElement.classList.contains('dark')).toBe(false);
|
|
45
|
-
});
|
|
46
|
-
it('ships no inline variable payload — static CSS owns the values', () => {
|
|
47
|
-
mockSystemDark(false);
|
|
48
|
-
const script = themeScript({ preset: 'studio' });
|
|
49
|
-
// The pre-paint script only stamps attributes; variable values come from
|
|
50
|
-
// the static per-preset stylesheets selected by those attributes.
|
|
51
|
-
expect(script).not.toContain('--smrt-');
|
|
52
|
-
expect(script).not.toContain('bootstrap');
|
|
53
|
-
expect(script.length).toBeLessThan(1024);
|
|
54
|
-
run(script);
|
|
55
|
-
for (const property of Array.from(document.documentElement.style)) {
|
|
56
|
-
expect(property.startsWith('--smrt-')).toBe(false);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
it('uses the custom storageKey', () => {
|
|
60
|
-
mockSystemDark(false);
|
|
61
|
-
localStorage.setItem('my-theme', JSON.stringify({ colorScheme: 'dark' }));
|
|
62
|
-
run(themeScript({ storageKey: 'my-theme' }));
|
|
63
|
-
expect(document.documentElement.getAttribute('data-color-scheme')).toBe('dark');
|
|
64
|
-
});
|
|
65
|
-
it('does not read stored preferences when persistence is disabled', () => {
|
|
66
|
-
mockSystemDark(false);
|
|
67
|
-
localStorage.setItem('smrt-theme', JSON.stringify({ preset: 'studio', colorScheme: 'dark' }));
|
|
68
|
-
run(themeScript({
|
|
69
|
-
persist: false,
|
|
70
|
-
preset: 'material',
|
|
71
|
-
defaultColorScheme: 'light',
|
|
72
|
-
}));
|
|
73
|
-
expect(document.documentElement.getAttribute('data-theme')).toBe('material');
|
|
74
|
-
expect(document.documentElement.getAttribute('data-color-scheme')).toBe('light');
|
|
75
|
-
});
|
|
76
|
-
it('ignores a raw (non-JSON) stored value like ThemeProvider', () => {
|
|
77
|
-
mockSystemDark(true);
|
|
78
|
-
localStorage.setItem('smrt-theme', 'light');
|
|
79
|
-
run(themeScript());
|
|
80
|
-
expect(document.documentElement.getAttribute('data-color-scheme')).toBe('dark');
|
|
81
|
-
expect(document.documentElement.classList.contains('dark')).toBe(true);
|
|
82
|
-
});
|
|
83
|
-
it('ignores invalid persisted enum values', () => {
|
|
84
|
-
mockSystemDark(false);
|
|
85
|
-
localStorage.setItem('smrt-theme', JSON.stringify({
|
|
86
|
-
preset: 'not-a-theme',
|
|
87
|
-
colorScheme: 'sepia',
|
|
88
|
-
}));
|
|
89
|
-
run(themeScript({ preset: 'material', defaultColorScheme: 'light' }));
|
|
90
|
-
expect(document.documentElement.getAttribute('data-theme')).toBe('material');
|
|
91
|
-
expect(document.documentElement.getAttribute('data-color-scheme')).toBe('light');
|
|
92
|
-
});
|
|
93
|
-
it('stamps a persisted registered custom theme pre-paint', () => {
|
|
94
|
-
const brandTheme = createTheme({
|
|
95
|
-
id: 'bootstrap-test-brand',
|
|
96
|
-
name: 'Bootstrap Test Brand',
|
|
97
|
-
light: { primary: '#336699', background: '#fefefe' },
|
|
98
|
-
dark: { primary: '#99ccff', background: '#101820' },
|
|
99
|
-
});
|
|
100
|
-
registerTheme(brandTheme);
|
|
101
|
-
mockSystemDark(false);
|
|
102
|
-
localStorage.setItem('smrt-theme', JSON.stringify({
|
|
103
|
-
preset: 'bootstrap-test-brand',
|
|
104
|
-
colorScheme: 'dark',
|
|
105
|
-
}));
|
|
106
|
-
run(themeScript());
|
|
107
|
-
expect(document.documentElement.getAttribute('data-theme')).toBe('bootstrap-test-brand');
|
|
108
|
-
expect(document.documentElement.getAttribute('data-color-scheme')).toBe('dark');
|
|
109
|
-
expect(document.documentElement.classList.contains('dark')).toBe(true);
|
|
110
|
-
});
|
|
111
|
-
it('still applies the fallback when localStorage access throws', () => {
|
|
112
|
-
mockSystemDark(true);
|
|
113
|
-
vi.spyOn(Storage.prototype, 'getItem').mockImplementation(() => {
|
|
114
|
-
throw new DOMException('denied', 'SecurityError');
|
|
115
|
-
});
|
|
116
|
-
run(themeScript({ preset: 'studio' }));
|
|
117
|
-
expect(document.documentElement.getAttribute('data-theme')).toBe('studio');
|
|
118
|
-
expect(document.documentElement.getAttribute('data-color-scheme')).toBe('dark');
|
|
119
|
-
expect(document.documentElement.classList.contains('dark')).toBe(true);
|
|
120
|
-
});
|
|
121
|
-
it('escapes executable inline-script terminators and separators', () => {
|
|
122
|
-
const script = themeScript({
|
|
123
|
-
storageKey: '</script><script>alert(1)</script>\u2028\u2029',
|
|
124
|
-
});
|
|
125
|
-
expect(script.toLowerCase()).not.toContain('</script');
|
|
126
|
-
expect(script).not.toContain('\u2028');
|
|
127
|
-
expect(script).not.toContain('\u2029');
|
|
128
|
-
expect(script).toContain('\\u003c/script>');
|
|
129
|
-
});
|
|
130
|
-
});
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Design-token alias contract (issue #1431).
|
|
3
|
-
*
|
|
4
|
-
* Components consume a Material-3 token vocabulary (`radius-small`,
|
|
5
|
-
* `duration-short2`, `spacing-md`, `typography-*-font`, …) that must resolve to
|
|
6
|
-
* real values across every preset. These tests pin the additive aliases emitted
|
|
7
|
-
* by the canonical preset generator (`css-generator.ts`) and the simple
|
|
8
|
-
* `src/theme/` ThemeProvider so a regression that drops a consumed alias fails
|
|
9
|
-
* here as well as in scripts/check-svelte-tokens.mjs.
|
|
10
|
-
*/
|
|
11
|
-
import { readFileSync } from 'node:fs';
|
|
12
|
-
import { join } from 'node:path';
|
|
13
|
-
import { describe, expect, it } from 'vitest';
|
|
14
|
-
import { generateThemeVariables as generateSimpleThemeVariables } from '../../theme/tokens.js';
|
|
15
|
-
import { generateThemeVariables } from '../css-generator.js';
|
|
16
|
-
import { themes } from '../registry.js';
|
|
17
|
-
/** Material-3 + helper aliases that components consume and expect emitted. */
|
|
18
|
-
const REQUIRED_ALIASES = [
|
|
19
|
-
// Radius (Material-3 named scale)
|
|
20
|
-
'--smrt-radius-extra-small',
|
|
21
|
-
'--smrt-radius-small',
|
|
22
|
-
'--smrt-radius-medium',
|
|
23
|
-
'--smrt-radius-large',
|
|
24
|
-
'--smrt-radius-extra-large',
|
|
25
|
-
// Spacing (named aliases)
|
|
26
|
-
'--smrt-spacing-xs',
|
|
27
|
-
'--smrt-spacing-sm',
|
|
28
|
-
'--smrt-spacing-md',
|
|
29
|
-
'--smrt-spacing-lg',
|
|
30
|
-
'--smrt-spacing-xl',
|
|
31
|
-
'--smrt-spacing-2xl',
|
|
32
|
-
'--smrt-spacing-3xl',
|
|
33
|
-
// Motion (Material-3 duration scale)
|
|
34
|
-
'--smrt-duration-short1',
|
|
35
|
-
'--smrt-duration-short2',
|
|
36
|
-
'--smrt-duration-short3',
|
|
37
|
-
'--smrt-duration-short4',
|
|
38
|
-
'--smrt-duration-medium1',
|
|
39
|
-
'--smrt-duration-medium2',
|
|
40
|
-
'--smrt-duration-medium3',
|
|
41
|
-
'--smrt-duration-medium4',
|
|
42
|
-
'--smrt-duration-long1',
|
|
43
|
-
'--smrt-duration-long2',
|
|
44
|
-
'--smrt-duration-long3',
|
|
45
|
-
'--smrt-duration-long4',
|
|
46
|
-
// Helper tokens (theme-independent)
|
|
47
|
-
'--smrt-font-family-mono',
|
|
48
|
-
'--smrt-typography-weight-normal',
|
|
49
|
-
'--smrt-typography-weight-medium',
|
|
50
|
-
'--smrt-typography-weight-semibold',
|
|
51
|
-
'--smrt-typography-weight-bold',
|
|
52
|
-
'--smrt-z-index-dialog',
|
|
53
|
-
'--smrt-z-index-loading',
|
|
54
|
-
];
|
|
55
|
-
const SPACING_NUMERIC_TOKENS = [
|
|
56
|
-
'--smrt-spacing-0',
|
|
57
|
-
'--smrt-spacing-0_5',
|
|
58
|
-
'--smrt-spacing-1',
|
|
59
|
-
'--smrt-spacing-1_5',
|
|
60
|
-
'--smrt-spacing-2',
|
|
61
|
-
'--smrt-spacing-2_5',
|
|
62
|
-
'--smrt-spacing-3',
|
|
63
|
-
'--smrt-spacing-3_5',
|
|
64
|
-
'--smrt-spacing-4',
|
|
65
|
-
'--smrt-spacing-5',
|
|
66
|
-
'--smrt-spacing-6',
|
|
67
|
-
'--smrt-spacing-7',
|
|
68
|
-
'--smrt-spacing-8',
|
|
69
|
-
'--smrt-spacing-9',
|
|
70
|
-
'--smrt-spacing-10',
|
|
71
|
-
'--smrt-spacing-11',
|
|
72
|
-
'--smrt-spacing-12',
|
|
73
|
-
'--smrt-spacing-14',
|
|
74
|
-
'--smrt-spacing-16',
|
|
75
|
-
'--smrt-spacing-20',
|
|
76
|
-
'--smrt-spacing-24',
|
|
77
|
-
];
|
|
78
|
-
const TYPOGRAPHY_FONT_SHORTHANDS = [
|
|
79
|
-
'--smrt-typography-body-large-font',
|
|
80
|
-
'--smrt-typography-body-medium-font',
|
|
81
|
-
'--smrt-typography-body-small-font',
|
|
82
|
-
'--smrt-typography-label-large-font',
|
|
83
|
-
'--smrt-typography-label-medium-font',
|
|
84
|
-
'--smrt-typography-label-small-font',
|
|
85
|
-
'--smrt-typography-title-large-font',
|
|
86
|
-
'--smrt-typography-title-medium-font',
|
|
87
|
-
'--smrt-typography-title-small-font',
|
|
88
|
-
'--smrt-typography-headline-small-font',
|
|
89
|
-
'--smrt-typography-headline-medium-font',
|
|
90
|
-
];
|
|
91
|
-
const BASE_COMPONENT_COLOR_TOKENS = [
|
|
92
|
-
'--smrt-color-surface-container-highest',
|
|
93
|
-
'--smrt-color-surface-container-lowest',
|
|
94
|
-
'--smrt-color-surface-dim',
|
|
95
|
-
'--smrt-color-surface-bright',
|
|
96
|
-
'--smrt-color-shadow',
|
|
97
|
-
];
|
|
98
|
-
const packageRoot = process.cwd().endsWith('packages/smrt-ui')
|
|
99
|
-
? process.cwd()
|
|
100
|
-
: join(process.cwd(), 'packages/smrt-ui');
|
|
101
|
-
const STATIC_STYLE_PATHS = {
|
|
102
|
-
material: join(packageRoot, 'src/themes/styles/material.css'),
|
|
103
|
-
glass: join(packageRoot, 'src/themes/styles/glass.css'),
|
|
104
|
-
studio: join(packageRoot, 'src/themes/styles/studio.css'),
|
|
105
|
-
smrt: join(packageRoot, 'src/themes/styles/smrt.css'),
|
|
106
|
-
happyvertical: join(packageRoot, 'src/themes/styles/happyvertical.css'),
|
|
107
|
-
};
|
|
108
|
-
function collectDefinedTokens(css) {
|
|
109
|
-
return new Set([...css.matchAll(/(--smrt-[a-z0-9_-]+)\s*:/gi)].map((match) => match[1]));
|
|
110
|
-
}
|
|
111
|
-
describe('preset generator alias emission (#1431)', () => {
|
|
112
|
-
for (const theme of Object.values(themes)) {
|
|
113
|
-
for (const isDark of [false, true]) {
|
|
114
|
-
it(`${theme.id} ${isDark ? 'dark' : 'light'} emits every consumed alias`, () => {
|
|
115
|
-
const vars = generateThemeVariables(theme, isDark);
|
|
116
|
-
for (const token of [
|
|
117
|
-
...REQUIRED_ALIASES,
|
|
118
|
-
...SPACING_NUMERIC_TOKENS,
|
|
119
|
-
...TYPOGRAPHY_FONT_SHORTHANDS,
|
|
120
|
-
]) {
|
|
121
|
-
expect(vars[token], `${token} should be emitted`).toBeDefined();
|
|
122
|
-
expect(vars[token]).not.toBe('');
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
it('maps Material-3 radius aliases onto canonical t-shirt values', () => {
|
|
128
|
-
const vars = generateThemeVariables(themes.material, false);
|
|
129
|
-
expect(vars['--smrt-radius-small']).toBe(vars['--smrt-radius-sm']);
|
|
130
|
-
expect(vars['--smrt-radius-medium']).toBe(vars['--smrt-radius-md']);
|
|
131
|
-
expect(vars['--smrt-radius-large']).toBe(vars['--smrt-radius-lg']);
|
|
132
|
-
});
|
|
133
|
-
it('maps named spacing aliases onto numeric-scale values', () => {
|
|
134
|
-
const vars = generateThemeVariables(themes.material, false);
|
|
135
|
-
expect(vars['--smrt-spacing-sm']).toBe(vars['--smrt-spacing-2']);
|
|
136
|
-
expect(vars['--smrt-spacing-md']).toBe(vars['--smrt-spacing-4']);
|
|
137
|
-
expect(vars['--smrt-spacing-xl']).toBe(vars['--smrt-spacing-8']);
|
|
138
|
-
});
|
|
139
|
-
it('builds the typography `font` shorthand from the emitted longhands', () => {
|
|
140
|
-
const vars = generateThemeVariables(themes.material, false);
|
|
141
|
-
const shorthand = vars['--smrt-typography-body-medium-font'];
|
|
142
|
-
expect(shorthand).toContain(vars['--smrt-typography-body-medium-size']);
|
|
143
|
-
// weight size/line-height family
|
|
144
|
-
expect(shorthand).toMatch(/^\d+\s+\S+\/\S+\s+.+$/);
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
describe('static preset CSS token surface (#1431)', () => {
|
|
148
|
-
for (const theme of Object.values(themes)) {
|
|
149
|
-
it(`${theme.id} stylesheet contains the generated token surface`, () => {
|
|
150
|
-
const css = readFileSync(STATIC_STYLE_PATHS[theme.id], 'utf8');
|
|
151
|
-
const defined = collectDefinedTokens(css);
|
|
152
|
-
const generatedTokens = new Set([
|
|
153
|
-
...Object.keys(generateThemeVariables(theme, false)),
|
|
154
|
-
...Object.keys(generateThemeVariables(theme, true)),
|
|
155
|
-
]);
|
|
156
|
-
const missing = [...generatedTokens]
|
|
157
|
-
.filter((token) => !defined.has(token))
|
|
158
|
-
.sort();
|
|
159
|
-
expect(missing).toEqual([]);
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
describe('simple ThemeProvider alias emission (#1431)', () => {
|
|
164
|
-
for (const isDark of [false, true]) {
|
|
165
|
-
it(`${isDark ? 'dark' : 'light'} emits shared aliases and component scale tokens`, () => {
|
|
166
|
-
const vars = generateSimpleThemeVariables(isDark);
|
|
167
|
-
for (const token of [
|
|
168
|
-
...REQUIRED_ALIASES,
|
|
169
|
-
...SPACING_NUMERIC_TOKENS,
|
|
170
|
-
...TYPOGRAPHY_FONT_SHORTHANDS,
|
|
171
|
-
...BASE_COMPONENT_COLOR_TOKENS,
|
|
172
|
-
]) {
|
|
173
|
-
expect(vars[token], `${token} should be emitted`).toBeDefined();
|
|
174
|
-
expect(vars[token]).not.toBe('');
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { formatEmail, formatText, matchOption, parseSpokenBoolean, } from '../formatters';
|
|
3
|
-
describe('Form Formatters', () => {
|
|
4
|
-
it('should format email correctly', () => {
|
|
5
|
-
expect(formatEmail('john at example dot com')).toBe('john@example.com');
|
|
6
|
-
expect(formatEmail('JOHN DOT DOE AT GMAIL DOT COM')).toBe('john.doe@gmail.com');
|
|
7
|
-
});
|
|
8
|
-
it('should format text correctly', () => {
|
|
9
|
-
expect(formatText('my name is John')).toBe('John');
|
|
10
|
-
expect(formatText('um so well hello')).toBe('hello');
|
|
11
|
-
});
|
|
12
|
-
it('should parse spoken boolean correctly', () => {
|
|
13
|
-
expect(parseSpokenBoolean('yes please')).toBe(true);
|
|
14
|
-
expect(parseSpokenBoolean('no way')).toBe(false);
|
|
15
|
-
expect(parseSpokenBoolean('maybe')).toBe(null);
|
|
16
|
-
});
|
|
17
|
-
it('should match options correctly', () => {
|
|
18
|
-
const options = [
|
|
19
|
-
{ label: 'Red', value: 'red' },
|
|
20
|
-
{ label: 'Green', value: 'green' },
|
|
21
|
-
{ label: 'Blue', value: 'blue' },
|
|
22
|
-
];
|
|
23
|
-
expect(matchOption('red', options)).toBe('red');
|
|
24
|
-
expect(matchOption('I want green', options)).toBe('green');
|
|
25
|
-
expect(matchOption('yellow', options)).toBe(null);
|
|
26
|
-
});
|
|
27
|
-
});
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { generateTheme, getContrastRatio, getLuminance, hexToRgb, meetsContrastAA, meetsContrastAAA, rgbToHex, } from '../color';
|
|
3
|
-
describe('Theme Color Utilities', () => {
|
|
4
|
-
it('should convert hex to rgb correctly', () => {
|
|
5
|
-
expect(hexToRgb('#000000')).toEqual({ r: 0, g: 0, b: 0 });
|
|
6
|
-
expect(hexToRgb('#ffffff')).toEqual({ r: 255, g: 255, b: 255 });
|
|
7
|
-
expect(hexToRgb('#FF5733')).toEqual({ r: 255, g: 87, b: 51 });
|
|
8
|
-
});
|
|
9
|
-
it('expands 3-digit shorthand hex (#abc -> #aabbcc) (#1586)', () => {
|
|
10
|
-
// Regression: shorthand hex used to NaN-poison the b channel (only the first
|
|
11
|
-
// 2 chars were read), corrupting any palette generated from a 3-digit seed.
|
|
12
|
-
expect(hexToRgb('#abc')).toEqual({ r: 170, g: 187, b: 204 });
|
|
13
|
-
expect(hexToRgb('#000')).toEqual({ r: 0, g: 0, b: 0 });
|
|
14
|
-
expect(hexToRgb('#fff')).toEqual({ r: 255, g: 255, b: 255 });
|
|
15
|
-
});
|
|
16
|
-
it('parses functional rgb()/rgba() notation (#1586)', () => {
|
|
17
|
-
expect(hexToRgb('rgb(0, 122, 255)')).toEqual({ r: 0, g: 122, b: 255 });
|
|
18
|
-
expect(hexToRgb('rgb(0 122 255)')).toEqual({ r: 0, g: 122, b: 255 });
|
|
19
|
-
expect(hexToRgb('rgba(0, 122, 255, 0.5)')).toEqual({
|
|
20
|
-
r: 0,
|
|
21
|
-
g: 122,
|
|
22
|
-
b: 255,
|
|
23
|
-
});
|
|
24
|
-
expect(hexToRgb('rgb(100%, 0%, 50%)')).toEqual({ r: 255, g: 0, b: 128 });
|
|
25
|
-
});
|
|
26
|
-
it('should convert rgb to hex correctly', () => {
|
|
27
|
-
expect(rgbToHex(0, 0, 0)).toBe('#000000');
|
|
28
|
-
expect(rgbToHex(255, 255, 255)).toBe('#ffffff');
|
|
29
|
-
expect(rgbToHex(255, 87, 51)).toBe('#ff5733');
|
|
30
|
-
});
|
|
31
|
-
it('should generate a theme palette from a seed color', () => {
|
|
32
|
-
const seed = '#6750A4'; // M3 Baseline Purple
|
|
33
|
-
const theme = generateTheme(seed);
|
|
34
|
-
// Check for critical M3 keys
|
|
35
|
-
expect(theme).toHaveProperty('primary');
|
|
36
|
-
expect(theme).toHaveProperty('onPrimary');
|
|
37
|
-
expect(theme).toHaveProperty('primaryContainer');
|
|
38
|
-
expect(theme).toHaveProperty('onPrimaryContainer');
|
|
39
|
-
expect(theme).toHaveProperty('secondary');
|
|
40
|
-
expect(theme).toHaveProperty('surface');
|
|
41
|
-
expect(theme).toHaveProperty('background');
|
|
42
|
-
expect(theme).toHaveProperty('error');
|
|
43
|
-
// Basic validity check (strings should be hex colors)
|
|
44
|
-
expect(theme.primary).toMatch(/^#[0-9a-fA-F]{6}$/);
|
|
45
|
-
});
|
|
46
|
-
it('should generate different palettes for light and dark modes', () => {
|
|
47
|
-
const seed = '#6750A4';
|
|
48
|
-
const lightTheme = generateTheme(seed, 'light');
|
|
49
|
-
const darkTheme = generateTheme(seed, 'dark');
|
|
50
|
-
expect(lightTheme.primary).not.toBe(darkTheme.primary);
|
|
51
|
-
// In M3, dark mode primary is usually lighter/desaturated compared to light mode
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
describe('Color Contrast Utilities', () => {
|
|
55
|
-
it('should calculate luminance correctly', () => {
|
|
56
|
-
// Black has luminance 0
|
|
57
|
-
expect(getLuminance({ r: 0, g: 0, b: 0 })).toBe(0);
|
|
58
|
-
// White has luminance 1
|
|
59
|
-
expect(getLuminance({ r: 255, g: 255, b: 255 })).toBe(1);
|
|
60
|
-
// Mid gray should be around 0.2
|
|
61
|
-
const midGray = getLuminance({ r: 128, g: 128, b: 128 });
|
|
62
|
-
expect(midGray).toBeGreaterThan(0.1);
|
|
63
|
-
expect(midGray).toBeLessThan(0.3);
|
|
64
|
-
});
|
|
65
|
-
it('should calculate contrast ratio correctly', () => {
|
|
66
|
-
const black = { r: 0, g: 0, b: 0 };
|
|
67
|
-
const white = { r: 255, g: 255, b: 255 };
|
|
68
|
-
// Black on white should be 21:1 (maximum contrast)
|
|
69
|
-
expect(getContrastRatio(black, white)).toBeCloseTo(21, 0);
|
|
70
|
-
// Same color should be 1:1 (no contrast)
|
|
71
|
-
expect(getContrastRatio(black, black)).toBe(1);
|
|
72
|
-
});
|
|
73
|
-
it('should validate WCAG AA contrast requirements', () => {
|
|
74
|
-
// Black on white passes AA
|
|
75
|
-
expect(meetsContrastAA('#000000', '#ffffff')).toBe(true);
|
|
76
|
-
// Light gray on white fails AA for normal text
|
|
77
|
-
expect(meetsContrastAA('#999999', '#ffffff')).toBe(false);
|
|
78
|
-
// Light gray on white passes AA for large text (3:1 threshold)
|
|
79
|
-
expect(meetsContrastAA('#767676', '#ffffff', true)).toBe(true);
|
|
80
|
-
});
|
|
81
|
-
it('should validate WCAG AAA contrast requirements', () => {
|
|
82
|
-
// Black on white passes AAA
|
|
83
|
-
expect(meetsContrastAAA('#000000', '#ffffff')).toBe(true);
|
|
84
|
-
// Medium gray on white fails AAA for normal text (needs 7:1)
|
|
85
|
-
expect(meetsContrastAAA('#666666', '#ffffff')).toBe(false);
|
|
86
|
-
// Darker gray passes AAA for large text (4.5:1 threshold)
|
|
87
|
-
expect(meetsContrastAAA('#595959', '#ffffff', true)).toBe(true);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { elevationTokens, typographyTokens } from '../typography';
|
|
3
|
-
describe('Typography & Elevation Tokens', () => {
|
|
4
|
-
it('should have valid typography tokens', () => {
|
|
5
|
-
expect(typographyTokens['--md-sys-typescale-body-large-font']).toBeDefined();
|
|
6
|
-
expect(typographyTokens['--md-sys-typescale-display-large-font']).toContain('Roboto');
|
|
7
|
-
});
|
|
8
|
-
it('should have valid elevation tokens', () => {
|
|
9
|
-
expect(elevationTokens['--md-sys-elevation-level1']).toBeDefined();
|
|
10
|
-
});
|
|
11
|
-
});
|