@happyvertical/smrt-ui 0.53.0 → 0.53.2
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,29 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import ThemeProvider from '../../../themes/ThemeProvider.svelte';
|
|
3
|
-
import DataTable from '../DataTable.svelte';
|
|
4
|
-
|
|
5
|
-
let { mode = 'hide-columns' }: { mode?: 'scroll' | 'hide-columns' } = $props();
|
|
6
|
-
const columns = Array.from({ length: 7 }, (_, index) => ({
|
|
7
|
-
id: `c${index}`,
|
|
8
|
-
label: `Column ${index}`,
|
|
9
|
-
sortable: true,
|
|
10
|
-
width: '200px',
|
|
11
|
-
minWidth: '180px',
|
|
12
|
-
responsive: { priority: index, keepVisible: index === 0 },
|
|
13
|
-
headerPath: [{ id: 'group', label: 'Group' }],
|
|
14
|
-
}));
|
|
15
|
-
const data = [
|
|
16
|
-
{
|
|
17
|
-
id: 'one',
|
|
18
|
-
...Object.fromEntries(
|
|
19
|
-
columns.map((column) => [
|
|
20
|
-
column.id,
|
|
21
|
-
`${column.label}LongUnbrokenTextThatMustWrap`,
|
|
22
|
-
]),
|
|
23
|
-
),
|
|
24
|
-
},
|
|
25
|
-
];
|
|
26
|
-
</script>
|
|
27
|
-
<ThemeProvider density="touch" persist={false} inlineVariables>
|
|
28
|
-
<DataTable {columns} {data} responsiveMode={mode} rowKey="id" sortable caption="Responsive table" />
|
|
29
|
-
</ThemeProvider>
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
type $$ComponentProps = {
|
|
2
|
-
mode?: 'scroll' | 'hide-columns';
|
|
3
|
-
};
|
|
4
|
-
declare const ResponsiveTable: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
5
|
-
type ResponsiveTable = ReturnType<typeof ResponsiveTable>;
|
|
6
|
-
export default ResponsiveTable;
|
|
7
|
-
//# sourceMappingURL=responsive-table.fixture.svelte.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"responsive-table.fixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/data/__tests__/responsive-table.fixture.svelte.ts"],"names":[],"mappings":"AAMC,KAAK,gBAAgB,GAAI;IAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,cAAc,CAAA;CAAE,CAAC;AAiC/D,QAAA,MAAM,eAAe,sDAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { createDataSurfaceRegistry } from '../data-surface.js';
|
|
3
|
-
import { registerLinkSurface } from '../link-surface.js';
|
|
4
|
-
import { hasPendingSurfaceNavigation, trackSurfaceNavigation, whenSurfaceNavigationSettled, } from '../surface-navigation.js';
|
|
5
|
-
const links = [{ id: 'events', label: 'Events', href: '/s/events' }];
|
|
6
|
-
function deferred() {
|
|
7
|
-
let resolve;
|
|
8
|
-
const promise = new Promise((r) => {
|
|
9
|
-
resolve = r;
|
|
10
|
-
});
|
|
11
|
-
return { promise, resolve };
|
|
12
|
-
}
|
|
13
|
-
function openCommand(revision = 1) {
|
|
14
|
-
return {
|
|
15
|
-
version: 1,
|
|
16
|
-
commandId: `open-${Math.random()}`,
|
|
17
|
-
identity: { surfaceId: 'site-sections', kind: 'list' },
|
|
18
|
-
expectedRevision: revision,
|
|
19
|
-
controlId: 'open',
|
|
20
|
-
payload: { target: 'Events' },
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
describe('whenSurfaceNavigationSettled', () => {
|
|
24
|
-
afterEach(() => {
|
|
25
|
-
vi.useRealTimers();
|
|
26
|
-
});
|
|
27
|
-
it('waits for a link surface navigation and the new page to register', async () => {
|
|
28
|
-
const registry = createDataSurfaceRegistry();
|
|
29
|
-
const navigation = deferred();
|
|
30
|
-
registerLinkSurface({
|
|
31
|
-
registry,
|
|
32
|
-
surfaceId: 'site-sections',
|
|
33
|
-
label: 'Site sections',
|
|
34
|
-
description: 'Pages',
|
|
35
|
-
links,
|
|
36
|
-
navigate: () => navigation.promise,
|
|
37
|
-
});
|
|
38
|
-
const result = await registry.execute(openCommand());
|
|
39
|
-
// The command answers at once; the page change is still running.
|
|
40
|
-
expect(result.ok).toBe(true);
|
|
41
|
-
expect(hasPendingSurfaceNavigation(registry)).toBe(true);
|
|
42
|
-
let settled = false;
|
|
43
|
-
const waiting = whenSurfaceNavigationSettled(registry, {
|
|
44
|
-
quietMs: 20,
|
|
45
|
-
}).then(() => {
|
|
46
|
-
settled = true;
|
|
47
|
-
});
|
|
48
|
-
await new Promise((r) => setTimeout(r, 30));
|
|
49
|
-
expect(settled).toBe(false);
|
|
50
|
-
// The new page mounts its surface as the navigation finishes.
|
|
51
|
-
navigation.resolve();
|
|
52
|
-
await Promise.resolve();
|
|
53
|
-
registry.register({
|
|
54
|
-
descriptor: {
|
|
55
|
-
version: 1,
|
|
56
|
-
identity: { surfaceId: 'events', kind: 'list' },
|
|
57
|
-
schemaVersion: 1,
|
|
58
|
-
label: 'Events',
|
|
59
|
-
rowKey: 'id',
|
|
60
|
-
columns: [
|
|
61
|
-
{ id: 'id', label: 'ID', capabilities: ['read'], role: 'row-key' },
|
|
62
|
-
],
|
|
63
|
-
query: { modes: ['rows'], projectableColumnIds: ['id'] },
|
|
64
|
-
controls: [],
|
|
65
|
-
actions: [],
|
|
66
|
-
limits: { maxQueryRows: 1, maxQueryBytes: 1000, maxSelectionSize: 1 },
|
|
67
|
-
},
|
|
68
|
-
getSnapshot: () => ({ revision: 1, state: {}, selection: null }),
|
|
69
|
-
});
|
|
70
|
-
await waiting;
|
|
71
|
-
expect(settled).toBe(true);
|
|
72
|
-
expect(hasPendingSurfaceNavigation(registry)).toBe(false);
|
|
73
|
-
});
|
|
74
|
-
it('resolves after a quiet period when nothing navigates', async () => {
|
|
75
|
-
const registry = createDataSurfaceRegistry();
|
|
76
|
-
const started = Date.now();
|
|
77
|
-
await whenSurfaceNavigationSettled(registry, { quietMs: 10 });
|
|
78
|
-
expect(Date.now() - started).toBeLessThan(1_000);
|
|
79
|
-
});
|
|
80
|
-
it('gives up after the timeout, and a failed navigation still settles', async () => {
|
|
81
|
-
const registry = createDataSurfaceRegistry();
|
|
82
|
-
void trackSurfaceNavigation(registry, new Promise(() => { }));
|
|
83
|
-
const started = Date.now();
|
|
84
|
-
await whenSurfaceNavigationSettled(registry, {
|
|
85
|
-
quietMs: 5,
|
|
86
|
-
timeoutMs: 40,
|
|
87
|
-
});
|
|
88
|
-
expect(Date.now() - started).toBeLessThan(1_000);
|
|
89
|
-
const other = createDataSurfaceRegistry();
|
|
90
|
-
const failing = trackSurfaceNavigation(other, Promise.reject(new Error('nope')));
|
|
91
|
-
await expect(failing).rejects.toThrow('nope');
|
|
92
|
-
await whenSurfaceNavigationSettled(other, { quietMs: 5 });
|
|
93
|
-
expect(hasPendingSurfaceNavigation(other)).toBe(false);
|
|
94
|
-
});
|
|
95
|
-
it('keeps waiting while a watched source keeps changing', async () => {
|
|
96
|
-
const registry = createDataSurfaceRegistry();
|
|
97
|
-
const listeners = new Set();
|
|
98
|
-
const tools = {
|
|
99
|
-
subscribe(listener) {
|
|
100
|
-
listeners.add(listener);
|
|
101
|
-
return () => listeners.delete(listener);
|
|
102
|
-
},
|
|
103
|
-
};
|
|
104
|
-
let settled = false;
|
|
105
|
-
const waiting = whenSurfaceNavigationSettled(registry, {
|
|
106
|
-
quietMs: 30,
|
|
107
|
-
alsoWatch: [tools],
|
|
108
|
-
}).then(() => {
|
|
109
|
-
settled = true;
|
|
110
|
-
});
|
|
111
|
-
for (let i = 0; i < 3; i += 1) {
|
|
112
|
-
await new Promise((r) => setTimeout(r, 15));
|
|
113
|
-
for (const listener of listeners)
|
|
114
|
-
listener({ type: 'registered' });
|
|
115
|
-
}
|
|
116
|
-
expect(settled).toBe(false);
|
|
117
|
-
await waiting;
|
|
118
|
-
expect(settled).toBe(true);
|
|
119
|
-
expect(listeners.size).toBe(0);
|
|
120
|
-
});
|
|
121
|
-
});
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Component tests for ConfidenceBadge (Sweep S11, #1416).
|
|
3
|
-
*
|
|
4
|
-
* ConfidenceBadge renders an ARIA meter for a 0-100 confidence score. Tests
|
|
5
|
-
* assert the real API from ConfidenceBadge.svelte — meter semantics
|
|
6
|
-
* (aria-valuenow/min/max/text), the >=80/>=50/else level→color mapping,
|
|
7
|
-
* clamping of out-of-range input, percent visibility, default vs custom
|
|
8
|
-
* aria-label, and axe-cleanliness across levels.
|
|
9
|
-
*/
|
|
10
|
-
import { render, screen } from '@testing-library/svelte';
|
|
11
|
-
import { describe, expect, it } from 'vitest';
|
|
12
|
-
import { expectNoA11yViolations } from '../../../test-support/a11y';
|
|
13
|
-
import ConfidenceBadge from '../ConfidenceBadge.svelte';
|
|
14
|
-
describe('ConfidenceBadge', () => {
|
|
15
|
-
it('exposes meter semantics with the confidence as aria-valuenow', () => {
|
|
16
|
-
render(ConfidenceBadge, { props: { confidence: 73 } });
|
|
17
|
-
const meter = screen.getByRole('meter');
|
|
18
|
-
expect(meter).toHaveAttribute('aria-valuenow', '73');
|
|
19
|
-
expect(meter).toHaveAttribute('aria-valuemin', '0');
|
|
20
|
-
expect(meter).toHaveAttribute('aria-valuemax', '100');
|
|
21
|
-
});
|
|
22
|
-
it('shows the rounded percentage by default', () => {
|
|
23
|
-
render(ConfidenceBadge, { props: { confidence: 73.4 } });
|
|
24
|
-
expect(screen.getByText('73%')).toBeInTheDocument();
|
|
25
|
-
});
|
|
26
|
-
it('hides the percentage text when showPercent is false', () => {
|
|
27
|
-
render(ConfidenceBadge, { props: { confidence: 73, showPercent: false } });
|
|
28
|
-
expect(screen.queryByText('73%')).not.toBeInTheDocument();
|
|
29
|
-
});
|
|
30
|
-
it('derives a default aria-label from the rounded confidence', () => {
|
|
31
|
-
render(ConfidenceBadge, { props: { confidence: 91.6 } });
|
|
32
|
-
expect(screen.getByRole('meter')).toHaveAttribute('aria-label', 'Confidence: 92%');
|
|
33
|
-
});
|
|
34
|
-
it('uses a custom aria-label when provided', () => {
|
|
35
|
-
render(ConfidenceBadge, {
|
|
36
|
-
props: { confidence: 50, 'aria-label': 'OCR certainty' },
|
|
37
|
-
});
|
|
38
|
-
expect(screen.getByRole('meter')).toHaveAttribute('aria-label', 'OCR certainty');
|
|
39
|
-
});
|
|
40
|
-
it.each([
|
|
41
|
-
[95, 'high'],
|
|
42
|
-
[80, 'high'],
|
|
43
|
-
[65, 'medium'],
|
|
44
|
-
[50, 'medium'],
|
|
45
|
-
[30, 'low'],
|
|
46
|
-
[0, 'low'],
|
|
47
|
-
])('reports "%s%%" as %s confidence in aria-valuetext', (value, level) => {
|
|
48
|
-
render(ConfidenceBadge, { props: { confidence: value } });
|
|
49
|
-
expect(screen.getByRole('meter')).toHaveAttribute('aria-valuetext', `${level} confidence (${value}%)`);
|
|
50
|
-
});
|
|
51
|
-
it('clamps confidence above 100 down to 100', () => {
|
|
52
|
-
render(ConfidenceBadge, { props: { confidence: 150 } });
|
|
53
|
-
const meter = screen.getByRole('meter');
|
|
54
|
-
expect(meter).toHaveAttribute('aria-valuenow', '100');
|
|
55
|
-
expect(screen.getByText('100%')).toBeInTheDocument();
|
|
56
|
-
});
|
|
57
|
-
it('clamps negative confidence up to 0', () => {
|
|
58
|
-
render(ConfidenceBadge, { props: { confidence: -20 } });
|
|
59
|
-
const meter = screen.getByRole('meter');
|
|
60
|
-
expect(meter).toHaveAttribute('aria-valuenow', '0');
|
|
61
|
-
expect(screen.getByText('0%')).toBeInTheDocument();
|
|
62
|
-
});
|
|
63
|
-
it.each([
|
|
64
|
-
[90, 'primary'],
|
|
65
|
-
[60, 'secondary'],
|
|
66
|
-
[20, 'error'],
|
|
67
|
-
])('maps %s%% to the %s color token for the bar', (value, token) => {
|
|
68
|
-
const { container } = render(ConfidenceBadge, {
|
|
69
|
-
props: { confidence: value },
|
|
70
|
-
});
|
|
71
|
-
const badge = container.querySelector('.confidence-badge');
|
|
72
|
-
expect(badge.style.getPropertyValue('--bar-color')).toContain(`smrt-color-${token}`);
|
|
73
|
-
});
|
|
74
|
-
it('emits bare design tokens with no literal hex fallback', () => {
|
|
75
|
-
// Regression for #1586: the old `var(--token, #hex)` fallbacks were the
|
|
76
|
-
// wrong colors (high → green #dcfce7 vs real material light blue #d3e3fd).
|
|
77
|
-
const { container } = render(ConfidenceBadge, {
|
|
78
|
-
props: { confidence: 90 },
|
|
79
|
-
});
|
|
80
|
-
const badge = container.querySelector('.confidence-badge');
|
|
81
|
-
for (const prop of ['--badge-bg', '--badge-text', '--bar-color']) {
|
|
82
|
-
const value = badge.style.getPropertyValue(prop);
|
|
83
|
-
expect(value).toMatch(/^var\(--smrt-color-[a-z-]+\)$/);
|
|
84
|
-
expect(value).not.toContain('#');
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
it('appends a custom class alongside the base class', () => {
|
|
88
|
-
const { container } = render(ConfidenceBadge, {
|
|
89
|
-
props: { confidence: 50, class: 'my-badge' },
|
|
90
|
-
});
|
|
91
|
-
const badge = container.querySelector('.confidence-badge');
|
|
92
|
-
expect(badge).toHaveClass('my-badge');
|
|
93
|
-
});
|
|
94
|
-
it.each([
|
|
95
|
-
['sm', 'sm'],
|
|
96
|
-
['lg', 'lg'],
|
|
97
|
-
])('applies the %s size class', (size, cls) => {
|
|
98
|
-
const { container } = render(ConfidenceBadge, {
|
|
99
|
-
props: { confidence: 50, size },
|
|
100
|
-
});
|
|
101
|
-
expect(container.querySelector('.confidence-badge')).toHaveClass(cls);
|
|
102
|
-
});
|
|
103
|
-
it.each([10, 60, 95])('is axe-clean at %s%% confidence', async (value) => {
|
|
104
|
-
const { container } = render(ConfidenceBadge, {
|
|
105
|
-
props: { confidence: value },
|
|
106
|
-
});
|
|
107
|
-
await expectNoA11yViolations(container);
|
|
108
|
-
});
|
|
109
|
-
});
|
|
@@ -1,304 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Component tests for CurrencyDisplay (Sweep S11, #1416).
|
|
3
|
-
*
|
|
4
|
-
* CurrencyDisplay formats a numeric amount (cents or dollars) into a currency
|
|
5
|
-
* string via Intl.NumberFormat('en-CA'). Expected strings are derived with the
|
|
6
|
-
* SAME formatter the component uses so assertions stay locale-robust. Tests
|
|
7
|
-
* assert the real API from CurrencyDisplay.svelte — unit conversion, currency
|
|
8
|
-
* code, sign handling (negative/zero/showSign), highlight classes, size
|
|
9
|
-
* classes, and axe-cleanliness.
|
|
10
|
-
*/
|
|
11
|
-
import { createHash } from 'node:crypto';
|
|
12
|
-
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
|
13
|
-
import { render, screen } from '@testing-library/svelte';
|
|
14
|
-
import { hydrate, unmount } from 'svelte';
|
|
15
|
-
import { createServer } from 'vite';
|
|
16
|
-
import { describe, expect, it } from 'vitest';
|
|
17
|
-
import { expectNoA11yViolations } from '../../../test-support/a11y';
|
|
18
|
-
import CurrencyDisplay from '../CurrencyDisplay.svelte';
|
|
19
|
-
import { ISO_4217_MINOR_UNITS } from '../currency-metadata.js';
|
|
20
|
-
import CurrencyDisplayI18nHarness from './CurrencyDisplayI18nHarness.svelte';
|
|
21
|
-
import CurrencyDisplaySsrHarness from './CurrencyDisplaySsrHarness.svelte';
|
|
22
|
-
function metadataDigest(metadata) {
|
|
23
|
-
const canonical = [...metadata.entries()]
|
|
24
|
-
.sort(([left], [right]) => left.localeCompare(right))
|
|
25
|
-
.map(([code, minorUnits]) => `${code}:${minorUnits ?? 'N.A.'}`)
|
|
26
|
-
.join('\n');
|
|
27
|
-
return createHash('sha256').update(canonical).digest('hex');
|
|
28
|
-
}
|
|
29
|
-
/** Mirror the component's absolute-value currency formatting. */
|
|
30
|
-
function money(absDollars, currency = 'CAD', minorUnitDigits) {
|
|
31
|
-
return new Intl.NumberFormat('en-CA', {
|
|
32
|
-
style: 'currency',
|
|
33
|
-
currency,
|
|
34
|
-
currencyDisplay: currency === 'CAD' || currency === 'USD' ? 'symbol' : 'code',
|
|
35
|
-
minimumFractionDigits: minorUnitDigits,
|
|
36
|
-
maximumFractionDigits: minorUnitDigits,
|
|
37
|
-
}).format(absDollars);
|
|
38
|
-
}
|
|
39
|
-
describe('CurrencyDisplay', () => {
|
|
40
|
-
it('matches the canonical digest of SIX List One 2026-01-01', () => {
|
|
41
|
-
expect(ISO_4217_MINOR_UNITS.size).toBe(178);
|
|
42
|
-
expect(metadataDigest(ISO_4217_MINOR_UNITS)).toBe('e1a3c502511fa784b38dd7ac2b4056d00f3f1a9f5781df93b0f2352f8eedc976');
|
|
43
|
-
});
|
|
44
|
-
it('formats cents into dollars by default', () => {
|
|
45
|
-
render(CurrencyDisplay, { props: { amount: 12345 } }); // cents → $123.45
|
|
46
|
-
expect(screen.getByText(money(123.45))).toBeInTheDocument();
|
|
47
|
-
});
|
|
48
|
-
it('treats the amount as dollars when unit=dollars', () => {
|
|
49
|
-
render(CurrencyDisplay, { props: { amount: 50, unit: 'dollars' } });
|
|
50
|
-
expect(screen.getByText(money(50))).toBeInTheDocument();
|
|
51
|
-
});
|
|
52
|
-
it('formats zero', () => {
|
|
53
|
-
render(CurrencyDisplay, { props: { amount: 0, unit: 'dollars' } });
|
|
54
|
-
expect(screen.getByText(money(0))).toBeInTheDocument();
|
|
55
|
-
});
|
|
56
|
-
it('prefixes a minus sign for negative amounts', () => {
|
|
57
|
-
render(CurrencyDisplay, { props: { amount: -2500 } }); // -$25.00
|
|
58
|
-
expect(screen.getByText(`-${money(25)}`)).toBeInTheDocument();
|
|
59
|
-
});
|
|
60
|
-
it('formats a USD amount with the USD currency code', () => {
|
|
61
|
-
render(CurrencyDisplay, {
|
|
62
|
-
props: { amount: 1000, unit: 'dollars', currency: 'USD' },
|
|
63
|
-
});
|
|
64
|
-
expect(screen.getByText(money(1000, 'USD'))).toBeInTheDocument();
|
|
65
|
-
});
|
|
66
|
-
it('formats an EUR amount through the public string currency prop', () => {
|
|
67
|
-
const commerceCurrency = 'EUR';
|
|
68
|
-
const { container } = render(CurrencyDisplay, {
|
|
69
|
-
props: { amount: 12345, currency: commerceCurrency },
|
|
70
|
-
});
|
|
71
|
-
expect(container.querySelector('span')?.textContent).toBe(money(123.45, 'EUR'));
|
|
72
|
-
});
|
|
73
|
-
it.each([
|
|
74
|
-
['JPY', 12345, '12,345'],
|
|
75
|
-
['BHD', 12345, '12.345'],
|
|
76
|
-
['IQD', 12345, '12.345'],
|
|
77
|
-
])('uses the ISO minor-unit scale for %s', (currency, amount, expected) => {
|
|
78
|
-
const { container } = render(CurrencyDisplay, {
|
|
79
|
-
props: { amount, currency },
|
|
80
|
-
});
|
|
81
|
-
expect(container.querySelector('span')?.textContent).toContain(expected);
|
|
82
|
-
});
|
|
83
|
-
it.each([
|
|
84
|
-
['IQD', 3, '9,007,199,254,740.991'],
|
|
85
|
-
['AFN', 2, '90,071,992,547,409.91'],
|
|
86
|
-
['CLF', 4, '900,719,925,474.0991'],
|
|
87
|
-
])('preserves the least-significant minor unit for large safe %s values', (currency, digits, expected) => {
|
|
88
|
-
const { container } = render(CurrencyDisplay, {
|
|
89
|
-
props: { amount: Number.MAX_SAFE_INTEGER, currency },
|
|
90
|
-
});
|
|
91
|
-
const text = container.querySelector('span')?.textContent;
|
|
92
|
-
expect(text).toContain(expected);
|
|
93
|
-
expect(text?.split('.').at(-1)).toHaveLength(digits);
|
|
94
|
-
});
|
|
95
|
-
it.each([
|
|
96
|
-
['positive fractional', 1.5],
|
|
97
|
-
['negative fractional', -1.5],
|
|
98
|
-
['unsafe positive integer', Number.MAX_SAFE_INTEGER + 1],
|
|
99
|
-
['unsafe negative integer', -(Number.MAX_SAFE_INTEGER + 1)],
|
|
100
|
-
['NaN', Number.NaN],
|
|
101
|
-
['positive infinity', Number.POSITIVE_INFINITY],
|
|
102
|
-
['negative infinity', Number.NEGATIVE_INFINITY],
|
|
103
|
-
])('rejects a %s amount in minor-unit mode', (_scenario, amount) => {
|
|
104
|
-
const { container } = render(CurrencyDisplay, {
|
|
105
|
-
props: { amount, currency: 'CAD' },
|
|
106
|
-
});
|
|
107
|
-
const display = container.querySelector('.currency-display');
|
|
108
|
-
expect(display).toHaveClass('invalid');
|
|
109
|
-
expect(display).toHaveTextContent('Invalid minor-unit amount');
|
|
110
|
-
});
|
|
111
|
-
it('preserves a negative safe integer through the exact string formatter path', () => {
|
|
112
|
-
const { container } = render(CurrencyDisplay, {
|
|
113
|
-
props: { amount: -Number.MAX_SAFE_INTEGER, currency: 'IQD' },
|
|
114
|
-
});
|
|
115
|
-
const text = container.querySelector('span')?.textContent;
|
|
116
|
-
expect(text).toContain('9,007,199,254,740.991');
|
|
117
|
-
expect(text?.startsWith('-IQD')).toBe(true);
|
|
118
|
-
});
|
|
119
|
-
it.each([
|
|
120
|
-
['cad', 'CAD'],
|
|
121
|
-
[' eur ', 'EUR'],
|
|
122
|
-
['ved', 'VED'],
|
|
123
|
-
['xad', 'XAD'],
|
|
124
|
-
])('normalizes the currency code %j to %s', (currency, normalized) => {
|
|
125
|
-
const { container } = render(CurrencyDisplay, {
|
|
126
|
-
props: { amount: 12345, currency },
|
|
127
|
-
});
|
|
128
|
-
expect(container.querySelector('span')?.textContent).toBe(money(123.45, normalized, 2));
|
|
129
|
-
});
|
|
130
|
-
it.each([
|
|
131
|
-
'US',
|
|
132
|
-
'AAA',
|
|
133
|
-
'ANG',
|
|
134
|
-
'BGN',
|
|
135
|
-
'CUC',
|
|
136
|
-
'HRK',
|
|
137
|
-
'SLL',
|
|
138
|
-
'ZWL',
|
|
139
|
-
'ZZZ',
|
|
140
|
-
'',
|
|
141
|
-
])('renders invalid code %j without throwing', (currency) => {
|
|
142
|
-
const { container } = render(CurrencyDisplay, {
|
|
143
|
-
props: { amount: 12345, currency },
|
|
144
|
-
});
|
|
145
|
-
const normalized = currency
|
|
146
|
-
.trim()
|
|
147
|
-
.replace(/[a-z]/g, (character) => character.toUpperCase()) || '(empty)';
|
|
148
|
-
const display = container.querySelector('.currency-display');
|
|
149
|
-
expect(display).toHaveClass('invalid');
|
|
150
|
-
expect(display).toHaveTextContent(`Invalid currency code: ${normalized}`);
|
|
151
|
-
});
|
|
152
|
-
it.each([
|
|
153
|
-
['uſd', 'U\\u{17F}D'],
|
|
154
|
-
['ıqd', '\\u{131}QD'],
|
|
155
|
-
['ßp', '\\u{DF}P'],
|
|
156
|
-
['U\u200bSD', 'U\\u{200B}SD'],
|
|
157
|
-
['USD\u202e', 'USD\\u{202E}'],
|
|
158
|
-
['U\u2066SD', 'U\\u{2066}SD'],
|
|
159
|
-
])('renders rejected non-ASCII input %j visibly as %s', (currency, diagnostic) => {
|
|
160
|
-
const { container } = render(CurrencyDisplay, {
|
|
161
|
-
props: { amount: 12345, currency },
|
|
162
|
-
});
|
|
163
|
-
expect(container.querySelector('.currency-display')).toHaveTextContent(`Invalid currency code: ${diagnostic}`);
|
|
164
|
-
});
|
|
165
|
-
it('bounds escaped astral input without splitting a code-point token', () => {
|
|
166
|
-
const { container } = render(CurrencyDisplay, {
|
|
167
|
-
props: { amount: 12345, currency: '😀😀' },
|
|
168
|
-
});
|
|
169
|
-
expect(container.querySelector('.currency-display')).toHaveTextContent('Invalid currency code: \\u{1F600}…');
|
|
170
|
-
});
|
|
171
|
-
it('bounds malformed currency text so one row cannot force table overflow', () => {
|
|
172
|
-
const { container } = render(CurrencyDisplay, {
|
|
173
|
-
props: { amount: 12345, currency: 'invalid-currency-code' },
|
|
174
|
-
});
|
|
175
|
-
expect(container.querySelector('.currency-display')).toHaveTextContent('Invalid currency code: INVALID-CURR…');
|
|
176
|
-
});
|
|
177
|
-
it('rejects a non-string currency from an untyped runtime caller without throwing', () => {
|
|
178
|
-
const { container } = render(CurrencyDisplay, {
|
|
179
|
-
// @ts-expect-error JavaScript callers can pass values outside the public type.
|
|
180
|
-
props: { amount: 12345, currency: null },
|
|
181
|
-
});
|
|
182
|
-
const display = container.querySelector('.currency-display');
|
|
183
|
-
expect(display).toHaveClass('invalid');
|
|
184
|
-
expect(display).toHaveTextContent('Invalid currency code: (non-string)');
|
|
185
|
-
});
|
|
186
|
-
it('requires major-unit input for ISO codes without a minor unit', async () => {
|
|
187
|
-
const { rerender } = render(CurrencyDisplay, {
|
|
188
|
-
props: { amount: 12.5, currency: 'XAU' },
|
|
189
|
-
});
|
|
190
|
-
const display = document.querySelector('.currency-display');
|
|
191
|
-
expect(display).toHaveClass('invalid');
|
|
192
|
-
expect(display).toHaveTextContent('Currency code has no minor unit: XAU');
|
|
193
|
-
await rerender({ amount: 12.5, currency: 'XAU', unit: 'dollars' });
|
|
194
|
-
expect(document.querySelector('.currency-display')?.textContent).toBe(money(12.5, 'XAU', 2));
|
|
195
|
-
});
|
|
196
|
-
it('resolves invalid-code prose through the active i18n snapshot', () => {
|
|
197
|
-
render(CurrencyDisplayI18nHarness);
|
|
198
|
-
expect(screen.getByText('Code monétaire invalide : ZZZ')).toBeVisible();
|
|
199
|
-
expect(screen.getByText('Devise sans unité mineure : XAU')).toBeVisible();
|
|
200
|
-
expect(screen.getByText('Montant en unité mineure invalide')).toBeVisible();
|
|
201
|
-
});
|
|
202
|
-
it('shows an explicit + sign for positive amounts when showSign is set', () => {
|
|
203
|
-
render(CurrencyDisplay, {
|
|
204
|
-
props: { amount: 1000, unit: 'dollars', showSign: true },
|
|
205
|
-
});
|
|
206
|
-
expect(screen.getByText(`+${money(1000)}`)).toBeInTheDocument();
|
|
207
|
-
});
|
|
208
|
-
it('shows a - sign for negatives when showSign is set', () => {
|
|
209
|
-
render(CurrencyDisplay, {
|
|
210
|
-
props: { amount: -1000, unit: 'dollars', showSign: true },
|
|
211
|
-
});
|
|
212
|
-
expect(screen.getByText(`-${money(1000)}`)).toBeInTheDocument();
|
|
213
|
-
});
|
|
214
|
-
it('does not add a sign to zero even when showSign is set', () => {
|
|
215
|
-
render(CurrencyDisplay, {
|
|
216
|
-
props: { amount: 0, unit: 'dollars', showSign: true },
|
|
217
|
-
});
|
|
218
|
-
const text = money(0);
|
|
219
|
-
expect(screen.getByText(text)).toBeInTheDocument();
|
|
220
|
-
expect(screen.queryByText(`+${text}`)).not.toBeInTheDocument();
|
|
221
|
-
});
|
|
222
|
-
it('applies the negative highlight class only when highlightNegative and amount<0', () => {
|
|
223
|
-
const { container } = render(CurrencyDisplay, {
|
|
224
|
-
props: { amount: -100, unit: 'dollars', highlightNegative: true },
|
|
225
|
-
});
|
|
226
|
-
expect(container.querySelector('span')).toHaveClass('negative');
|
|
227
|
-
});
|
|
228
|
-
it('does not apply the negative class to a positive amount', () => {
|
|
229
|
-
const { container } = render(CurrencyDisplay, {
|
|
230
|
-
props: { amount: 100, unit: 'dollars', highlightNegative: true },
|
|
231
|
-
});
|
|
232
|
-
expect(container.querySelector('span')).not.toHaveClass('negative');
|
|
233
|
-
});
|
|
234
|
-
it('applies the positive highlight class only when highlightPositive and amount>0', () => {
|
|
235
|
-
const { container } = render(CurrencyDisplay, {
|
|
236
|
-
props: { amount: 100, unit: 'dollars', highlightPositive: true },
|
|
237
|
-
});
|
|
238
|
-
expect(container.querySelector('span')).toHaveClass('positive');
|
|
239
|
-
});
|
|
240
|
-
it.each([
|
|
241
|
-
['sm', 'sm'],
|
|
242
|
-
['lg', 'lg'],
|
|
243
|
-
])('applies the %s size class', (size, cls) => {
|
|
244
|
-
const { container } = render(CurrencyDisplay, {
|
|
245
|
-
props: { amount: 100, unit: 'dollars', size },
|
|
246
|
-
});
|
|
247
|
-
expect(container.querySelector('span')).toHaveClass(cls);
|
|
248
|
-
});
|
|
249
|
-
it('appends a custom class alongside the base class', () => {
|
|
250
|
-
const { container } = render(CurrencyDisplay, {
|
|
251
|
-
props: { amount: 100, unit: 'dollars', class: 'my-money' },
|
|
252
|
-
});
|
|
253
|
-
const span = container.querySelector('span');
|
|
254
|
-
expect(span).toHaveClass('currency-display');
|
|
255
|
-
expect(span).toHaveClass('my-money');
|
|
256
|
-
});
|
|
257
|
-
it('is axe-clean', async () => {
|
|
258
|
-
const { container } = render(CurrencyDisplay, {
|
|
259
|
-
props: { amount: 12345 },
|
|
260
|
-
});
|
|
261
|
-
await expectNoA11yViolations(container);
|
|
262
|
-
});
|
|
263
|
-
it('is axe-clean for a highlighted negative value', async () => {
|
|
264
|
-
const { container } = render(CurrencyDisplay, {
|
|
265
|
-
props: { amount: -5000, highlightNegative: true },
|
|
266
|
-
});
|
|
267
|
-
await expectNoA11yViolations(container);
|
|
268
|
-
});
|
|
269
|
-
it('is axe-clean for an invalid currency code', async () => {
|
|
270
|
-
const { container } = render(CurrencyDisplay, {
|
|
271
|
-
props: { amount: 12345, currency: 'ZZZ' },
|
|
272
|
-
});
|
|
273
|
-
await expectNoA11yViolations(container);
|
|
274
|
-
});
|
|
275
|
-
it('renders and hydrates valid and invalid currencies safely', async () => {
|
|
276
|
-
const vite = await createServer({
|
|
277
|
-
appType: 'custom',
|
|
278
|
-
configFile: false,
|
|
279
|
-
plugins: [svelte()],
|
|
280
|
-
root: process.cwd(),
|
|
281
|
-
server: { middlewareMode: true },
|
|
282
|
-
});
|
|
283
|
-
try {
|
|
284
|
-
const { default: SsrHarness } = await vite.ssrLoadModule('/src/components/display/__tests__/CurrencyDisplaySsrHarness.svelte');
|
|
285
|
-
const { render: renderSsr } = await vite.ssrLoadModule('svelte/server');
|
|
286
|
-
const result = renderSsr(SsrHarness);
|
|
287
|
-
expect(result.body).toContain(money(123.45, 'EUR'));
|
|
288
|
-
expect(result.body).toContain('Invalid currency code: ZZZ');
|
|
289
|
-
expect(result.body).toContain('Currency code has no minor unit: XAU');
|
|
290
|
-
const host = document.createElement('div');
|
|
291
|
-
host.innerHTML = result.body;
|
|
292
|
-
document.body.append(host);
|
|
293
|
-
const instance = hydrate(CurrencyDisplaySsrHarness, { target: host });
|
|
294
|
-
expect(host.textContent).toContain(money(123.45, 'EUR'));
|
|
295
|
-
expect(host.textContent).toContain('Invalid currency code: ZZZ');
|
|
296
|
-
expect(host.textContent).toContain('Currency code has no minor unit: XAU');
|
|
297
|
-
await unmount(instance);
|
|
298
|
-
host.remove();
|
|
299
|
-
}
|
|
300
|
-
finally {
|
|
301
|
-
await vite.close();
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
});
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { createI18nContext, setI18nContext } from '../../../i18n/index.js';
|
|
3
|
-
import CurrencyDisplay from '../CurrencyDisplay.svelte';
|
|
4
|
-
|
|
5
|
-
setI18nContext(
|
|
6
|
-
createI18nContext({
|
|
7
|
-
locale: 'fr',
|
|
8
|
-
messages: {
|
|
9
|
-
'ui.currency_display.invalid_code': 'Code monétaire invalide : {code}',
|
|
10
|
-
'ui.currency_display.invalid_minor_unit_amount':
|
|
11
|
-
'Montant en unité mineure invalide',
|
|
12
|
-
'ui.currency_display.no_minor_unit': 'Devise sans unité mineure : {code}',
|
|
13
|
-
},
|
|
14
|
-
}),
|
|
15
|
-
);
|
|
16
|
-
</script>
|
|
17
|
-
|
|
18
|
-
<CurrencyDisplay amount={12345} currency="ZZZ" />
|
|
19
|
-
<CurrencyDisplay amount={12345} currency="XAU" />
|
|
20
|
-
<CurrencyDisplay amount={1.5} currency="CAD" />
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
-
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
-
$$bindings?: Bindings;
|
|
4
|
-
} & Exports;
|
|
5
|
-
(internal: unknown, props: {
|
|
6
|
-
$$events?: Events;
|
|
7
|
-
$$slots?: Slots;
|
|
8
|
-
}): Exports & {
|
|
9
|
-
$set?: any;
|
|
10
|
-
$on?: any;
|
|
11
|
-
};
|
|
12
|
-
z_$$bindings?: Bindings;
|
|
13
|
-
}
|
|
14
|
-
declare const CurrencyDisplayI18nHarness: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
-
[evt: string]: CustomEvent<any>;
|
|
16
|
-
}, {}, {}, string>;
|
|
17
|
-
type CurrencyDisplayI18nHarness = InstanceType<typeof CurrencyDisplayI18nHarness>;
|
|
18
|
-
export default CurrencyDisplayI18nHarness;
|
|
19
|
-
//# sourceMappingURL=CurrencyDisplayI18nHarness.svelte.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CurrencyDisplayI18nHarness.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/display/__tests__/CurrencyDisplayI18nHarness.svelte.ts"],"names":[],"mappings":"AA6BA,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,0BAA0B;;kBAA+E,CAAC;AAC9F,KAAK,0BAA0B,GAAG,YAAY,CAAC,OAAO,0BAA0B,CAAC,CAAC;AACpF,eAAe,0BAA0B,CAAC"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
-
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
-
$$bindings?: Bindings;
|
|
4
|
-
} & Exports;
|
|
5
|
-
(internal: unknown, props: {
|
|
6
|
-
$$events?: Events;
|
|
7
|
-
$$slots?: Slots;
|
|
8
|
-
}): Exports & {
|
|
9
|
-
$set?: any;
|
|
10
|
-
$on?: any;
|
|
11
|
-
};
|
|
12
|
-
z_$$bindings?: Bindings;
|
|
13
|
-
}
|
|
14
|
-
declare const CurrencyDisplaySsrHarness: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
-
[evt: string]: CustomEvent<any>;
|
|
16
|
-
}, {}, {}, string>;
|
|
17
|
-
type CurrencyDisplaySsrHarness = InstanceType<typeof CurrencyDisplaySsrHarness>;
|
|
18
|
-
export default CurrencyDisplaySsrHarness;
|
|
19
|
-
//# sourceMappingURL=CurrencyDisplaySsrHarness.svelte.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CurrencyDisplaySsrHarness.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/display/__tests__/CurrencyDisplaySsrHarness.svelte.ts"],"names":[],"mappings":"AAeA,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,yBAAyB;;kBAA+E,CAAC;AAC7F,KAAK,yBAAyB,GAAG,YAAY,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAClF,eAAe,yBAAyB,CAAC"}
|