@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,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Component test for FilterChips (Sweep S11, #1416).
|
|
3
|
-
*
|
|
4
|
-
* FilterChips is a single-select filter: a `role="radiogroup"` of
|
|
5
|
-
* `role="radio"` buttons where the selected option carries `aria-checked`.
|
|
6
|
-
* (There is no per-chip remove/dismiss affordance in the source — selection is
|
|
7
|
-
* the only interaction.) This suite asserts that structure/state, drives
|
|
8
|
-
* selection via click, and proves axe-cleanliness, including the optional
|
|
9
|
-
* "All" option.
|
|
10
|
-
*/
|
|
11
|
-
import { render, screen, within } from '@testing-library/svelte';
|
|
12
|
-
import userEvent from '@testing-library/user-event';
|
|
13
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
14
|
-
import { expectNoA11yViolations } from '../../../test-support/a11y';
|
|
15
|
-
import FilterChips from '../FilterChips.svelte';
|
|
16
|
-
const OPTIONS = [
|
|
17
|
-
{ value: 'all-news', label: 'News', count: 12 },
|
|
18
|
-
{ value: 'sports', label: 'Sports', count: 5 },
|
|
19
|
-
{ value: 'tech', label: 'Tech' },
|
|
20
|
-
];
|
|
21
|
-
describe('FilterChips', () => {
|
|
22
|
-
it('renders a radiogroup with one radio per option', () => {
|
|
23
|
-
render(FilterChips, { props: { options: OPTIONS, selected: 'all-news' } });
|
|
24
|
-
const group = screen.getByRole('radiogroup');
|
|
25
|
-
expect(within(group).getAllByRole('radio')).toHaveLength(3);
|
|
26
|
-
});
|
|
27
|
-
it('marks the selected option with aria-checked=true and others false', () => {
|
|
28
|
-
render(FilterChips, { props: { options: OPTIONS, selected: 'sports' } });
|
|
29
|
-
expect(screen.getByRole('radio', { name: /Sports/ })).toHaveAttribute('aria-checked', 'true');
|
|
30
|
-
expect(screen.getByRole('radio', { name: /News/ })).toHaveAttribute('aria-checked', 'false');
|
|
31
|
-
});
|
|
32
|
-
it('renders the optional count alongside its chip label', () => {
|
|
33
|
-
render(FilterChips, { props: { options: OPTIONS, selected: 'all-news' } });
|
|
34
|
-
expect(screen.getByRole('radio', { name: /News/ })).toHaveTextContent('12');
|
|
35
|
-
});
|
|
36
|
-
it('fires onchange with the clicked option value', async () => {
|
|
37
|
-
const onchange = vi.fn();
|
|
38
|
-
render(FilterChips, {
|
|
39
|
-
props: { options: OPTIONS, selected: 'all-news', onchange },
|
|
40
|
-
});
|
|
41
|
-
await userEvent.click(screen.getByRole('radio', { name: /Tech/ }));
|
|
42
|
-
expect(onchange).toHaveBeenCalledWith('tech');
|
|
43
|
-
});
|
|
44
|
-
it('does not fire onchange when the already-selected chip is clicked', async () => {
|
|
45
|
-
const onchange = vi.fn();
|
|
46
|
-
render(FilterChips, {
|
|
47
|
-
props: { options: OPTIONS, selected: 'sports', onchange },
|
|
48
|
-
});
|
|
49
|
-
await userEvent.click(screen.getByRole('radio', { name: /Sports/ }));
|
|
50
|
-
expect(onchange).not.toHaveBeenCalled();
|
|
51
|
-
});
|
|
52
|
-
it('does not fire onchange for a disabled option', async () => {
|
|
53
|
-
const onchange = vi.fn();
|
|
54
|
-
const options = [
|
|
55
|
-
{ value: 'a', label: 'A' },
|
|
56
|
-
{ value: 'b', label: 'B', disabled: true },
|
|
57
|
-
];
|
|
58
|
-
render(FilterChips, { props: { options, selected: 'a', onchange } });
|
|
59
|
-
const disabled = screen.getByRole('radio', { name: 'B' });
|
|
60
|
-
expect(disabled).toBeDisabled();
|
|
61
|
-
await userEvent.click(disabled);
|
|
62
|
-
expect(onchange).not.toHaveBeenCalled();
|
|
63
|
-
});
|
|
64
|
-
it('prepends an "All" option (empty value) when showAll is set', async () => {
|
|
65
|
-
const onchange = vi.fn();
|
|
66
|
-
render(FilterChips, {
|
|
67
|
-
props: {
|
|
68
|
-
options: OPTIONS,
|
|
69
|
-
selected: 'sports',
|
|
70
|
-
showAll: true,
|
|
71
|
-
allLabel: 'Everything',
|
|
72
|
-
onchange,
|
|
73
|
-
},
|
|
74
|
-
});
|
|
75
|
-
const radios = screen.getAllByRole('radio');
|
|
76
|
-
expect(radios).toHaveLength(4);
|
|
77
|
-
const all = screen.getByRole('radio', { name: /Everything/ });
|
|
78
|
-
expect(all).toHaveAttribute('aria-checked', 'false');
|
|
79
|
-
await userEvent.click(all);
|
|
80
|
-
expect(onchange).toHaveBeenCalledWith('');
|
|
81
|
-
});
|
|
82
|
-
it('is axe-clean for a default selected group', async () => {
|
|
83
|
-
const { container } = render(FilterChips, {
|
|
84
|
-
props: { options: OPTIONS, selected: 'all-news' },
|
|
85
|
-
});
|
|
86
|
-
await expectNoA11yViolations(container);
|
|
87
|
-
});
|
|
88
|
-
it('is axe-clean with the "All" option enabled', async () => {
|
|
89
|
-
const { container } = render(FilterChips, {
|
|
90
|
-
props: { options: OPTIONS, selected: '', showAll: true },
|
|
91
|
-
});
|
|
92
|
-
await expectNoA11yViolations(container);
|
|
93
|
-
});
|
|
94
|
-
});
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
/** Link tabs: a navigation row of URLs with overflow, badges, active-in-view. */
|
|
2
|
-
import { render, screen, within } from '@testing-library/svelte';
|
|
3
|
-
import userEvent from '@testing-library/user-event';
|
|
4
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
5
|
-
import { expectNoA11yViolations } from '../../../test-support/a11y';
|
|
6
|
-
import Tabs from '../Tabs.svelte';
|
|
7
|
-
import { splitTabs } from '../tabs-overflow.js';
|
|
8
|
-
const TABS = [
|
|
9
|
-
{ id: 'article', label: 'Article', href: '/c/1' },
|
|
10
|
-
{ id: 'images', label: 'Images', href: '/c/1/images', badge: 3 },
|
|
11
|
-
{ id: 'videos', label: 'Videos', href: '/c/1/videos' },
|
|
12
|
-
{ id: 'social', label: 'Social', href: '/c/1/social' },
|
|
13
|
-
{ id: 'review', label: 'Review', href: '/c/1/review', badge: '!' },
|
|
14
|
-
{ id: 'jobs', label: 'Background work', href: '/c/1/jobs' },
|
|
15
|
-
];
|
|
16
|
-
describe('splitTabs', () => {
|
|
17
|
-
it('keeps everything in the row under the limit', () => {
|
|
18
|
-
expect(splitTabs(TABS, 'article', 10).overflow).toEqual([]);
|
|
19
|
-
expect(splitTabs(TABS, 'article', undefined).overflow).toEqual([]);
|
|
20
|
-
});
|
|
21
|
-
it('promotes the active tab into the row', () => {
|
|
22
|
-
const { visible, overflow } = splitTabs(TABS, 'jobs', 4);
|
|
23
|
-
expect(visible.map((tab) => tab.id)).toEqual([
|
|
24
|
-
'article',
|
|
25
|
-
'images',
|
|
26
|
-
'videos',
|
|
27
|
-
'jobs',
|
|
28
|
-
]);
|
|
29
|
-
expect(overflow.map((tab) => tab.id)).toEqual(['social', 'review']);
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
describe('Tabs with hrefs', () => {
|
|
33
|
-
it('renders navigation links, not a tablist, with aria-current on the active tab', () => {
|
|
34
|
-
render(Tabs, {
|
|
35
|
-
props: { tabs: TABS, active: 'images', 'aria-label': 'Content sections' },
|
|
36
|
-
});
|
|
37
|
-
const nav = screen.getByRole('navigation', { name: 'Content sections' });
|
|
38
|
-
expect(nav).toHaveAttribute('data-shell-tabs');
|
|
39
|
-
expect(screen.queryByRole('tablist')).not.toBeInTheDocument();
|
|
40
|
-
const active = within(nav).getByRole('link', { name: /Images/ });
|
|
41
|
-
expect(active).toHaveAttribute('href', '/c/1/images');
|
|
42
|
-
expect(active).toHaveAttribute('aria-current', 'page');
|
|
43
|
-
expect(active).toHaveTextContent('3');
|
|
44
|
-
expect(within(nav).getByRole('link', { name: 'Article' })).not.toHaveAttribute('aria-current');
|
|
45
|
-
});
|
|
46
|
-
it('moves extra tabs under "More", keeps the active one visible, and dots the menu for a hidden badge', async () => {
|
|
47
|
-
const { container } = render(Tabs, {
|
|
48
|
-
props: {
|
|
49
|
-
tabs: TABS,
|
|
50
|
-
active: 'jobs',
|
|
51
|
-
maxVisible: 4,
|
|
52
|
-
'aria-label': 'Content sections',
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
const row = container.querySelector('.tabs-links-row');
|
|
56
|
-
expect(within(row)
|
|
57
|
-
.getAllByRole('link')
|
|
58
|
-
.map((link) => link.dataset.tabId)).toEqual(['article', 'images', 'videos', 'jobs']);
|
|
59
|
-
const more = container.querySelector('details.tabs-more');
|
|
60
|
-
expect(within(more).getByText('More')).toBeInTheDocument();
|
|
61
|
-
expect(within(more).getByText('(has updates)')).toBeInTheDocument();
|
|
62
|
-
await userEvent.click(within(more).getByText('More'));
|
|
63
|
-
expect(more.open).toBe(true);
|
|
64
|
-
expect(within(more).getByRole('link', { name: /Review/ })).toHaveAttribute('href', '/c/1/review');
|
|
65
|
-
});
|
|
66
|
-
it('a disabled link tab never fires onchange', async () => {
|
|
67
|
-
const onchange = vi.fn();
|
|
68
|
-
render(Tabs, {
|
|
69
|
-
props: {
|
|
70
|
-
tabs: [
|
|
71
|
-
{ id: 'article', label: 'Article', href: '/c/1' },
|
|
72
|
-
{
|
|
73
|
-
id: 'locked',
|
|
74
|
-
label: 'Locked',
|
|
75
|
-
href: '/c/1/locked',
|
|
76
|
-
disabled: true,
|
|
77
|
-
},
|
|
78
|
-
],
|
|
79
|
-
active: 'article',
|
|
80
|
-
onchange,
|
|
81
|
-
'aria-label': 'Content sections',
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
const locked = screen.getByText('Locked').closest('a');
|
|
85
|
-
await userEvent.click(locked);
|
|
86
|
-
expect(onchange).not.toHaveBeenCalled();
|
|
87
|
-
});
|
|
88
|
-
it('does not dot "More" for an empty-string badge, matching the tab itself', () => {
|
|
89
|
-
const { container } = render(Tabs, {
|
|
90
|
-
props: {
|
|
91
|
-
tabs: [
|
|
92
|
-
{ id: 'a', label: 'A', href: '/a' },
|
|
93
|
-
{ id: 'b', label: 'B', href: '/b' },
|
|
94
|
-
{ id: 'c', label: 'C', href: '/c', badge: '' },
|
|
95
|
-
],
|
|
96
|
-
active: 'a',
|
|
97
|
-
maxVisible: 2,
|
|
98
|
-
'aria-label': 'Sections',
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
const more = container.querySelector('details.tabs-more');
|
|
102
|
-
expect(more).not.toBeNull();
|
|
103
|
-
expect(more.querySelector('.tab-dot')).toBeNull();
|
|
104
|
-
expect(more.querySelector('.tab-badge')).toBeNull();
|
|
105
|
-
});
|
|
106
|
-
it('is axe-clean', async () => {
|
|
107
|
-
const { container } = render(Tabs, {
|
|
108
|
-
props: {
|
|
109
|
-
tabs: TABS,
|
|
110
|
-
active: 'article',
|
|
111
|
-
maxVisible: 4,
|
|
112
|
-
'aria-label': 'Content sections',
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
await expectNoA11yViolations(container);
|
|
116
|
-
});
|
|
117
|
-
});
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Component test for Tabs (Sweep S11, #1416).
|
|
3
|
-
*
|
|
4
|
-
* Tabs renders an ARIA tablist of `role="tab"` buttons with roving tabindex,
|
|
5
|
-
* `aria-selected` on the active tab, and a `role="tabpanel"` for children.
|
|
6
|
-
* This suite asserts that structure/state, drives click + Arrow/Home/End
|
|
7
|
-
* keyboard navigation (which fire `onchange`), and proves axe-cleanliness.
|
|
8
|
-
*/
|
|
9
|
-
import { render, screen, within } from '@testing-library/svelte';
|
|
10
|
-
import userEvent from '@testing-library/user-event';
|
|
11
|
-
import { createRawSnippet } from 'svelte';
|
|
12
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
13
|
-
import { expectNoA11yViolations } from '../../../test-support/a11y';
|
|
14
|
-
import Tabs from '../Tabs.svelte';
|
|
15
|
-
const TABS = [
|
|
16
|
-
{ id: 'overview', label: 'Overview' },
|
|
17
|
-
{ id: 'activity', label: 'Activity', count: 4 },
|
|
18
|
-
{ id: 'settings', label: 'Settings' },
|
|
19
|
-
];
|
|
20
|
-
/** Build a text Snippet for the Tabs `children` (panel) prop. */
|
|
21
|
-
function panelSnippet(text) {
|
|
22
|
-
return createRawSnippet(() => ({ render: () => `<span>${text}</span>` }));
|
|
23
|
-
}
|
|
24
|
-
describe('Tabs', () => {
|
|
25
|
-
it('renders a tablist with one tab button per tab', () => {
|
|
26
|
-
render(Tabs, {
|
|
27
|
-
props: { tabs: TABS, active: 'overview', 'aria-label': 'Sections' },
|
|
28
|
-
});
|
|
29
|
-
const tablist = screen.getByRole('tablist', { name: 'Sections' });
|
|
30
|
-
expect(within(tablist).getAllByRole('tab')).toHaveLength(3);
|
|
31
|
-
});
|
|
32
|
-
it('marks the active tab with aria-selected and a tabindex of 0', () => {
|
|
33
|
-
render(Tabs, { props: { tabs: TABS, active: 'activity' } });
|
|
34
|
-
const active = screen.getByRole('tab', { name: /Activity/ });
|
|
35
|
-
expect(active).toHaveAttribute('aria-selected', 'true');
|
|
36
|
-
expect(active).toHaveAttribute('tabindex', '0');
|
|
37
|
-
const inactive = screen.getByRole('tab', { name: 'Overview' });
|
|
38
|
-
expect(inactive).toHaveAttribute('aria-selected', 'false');
|
|
39
|
-
expect(inactive).toHaveAttribute('tabindex', '-1');
|
|
40
|
-
});
|
|
41
|
-
it('renders the optional count alongside its tab label', () => {
|
|
42
|
-
render(Tabs, { props: { tabs: TABS, active: 'overview' } });
|
|
43
|
-
expect(screen.getByRole('tab', { name: /Activity/ })).toHaveTextContent('4');
|
|
44
|
-
});
|
|
45
|
-
it('renders children inside a tabpanel labelled by the active tab', () => {
|
|
46
|
-
render(Tabs, {
|
|
47
|
-
props: {
|
|
48
|
-
tabs: TABS,
|
|
49
|
-
active: 'overview',
|
|
50
|
-
children: panelSnippet('Overview content'),
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
const panel = screen.getByRole('tabpanel');
|
|
54
|
-
expect(within(panel).getByText('Overview content')).toBeInTheDocument();
|
|
55
|
-
});
|
|
56
|
-
it('fires onchange with the clicked tab id', async () => {
|
|
57
|
-
const onchange = vi.fn();
|
|
58
|
-
render(Tabs, { props: { tabs: TABS, active: 'overview', onchange } });
|
|
59
|
-
await userEvent.click(screen.getByRole('tab', { name: 'Settings' }));
|
|
60
|
-
expect(onchange).toHaveBeenCalledWith('settings');
|
|
61
|
-
});
|
|
62
|
-
it('does not fire onchange when the already-active tab is clicked', async () => {
|
|
63
|
-
const onchange = vi.fn();
|
|
64
|
-
render(Tabs, { props: { tabs: TABS, active: 'overview', onchange } });
|
|
65
|
-
await userEvent.click(screen.getByRole('tab', { name: 'Overview' }));
|
|
66
|
-
expect(onchange).not.toHaveBeenCalled();
|
|
67
|
-
});
|
|
68
|
-
// ArrowRight/ArrowLeft are asserted in separate renders rather than chained:
|
|
69
|
-
// the component moves focus to the newly-activated tab, so a second arrow key
|
|
70
|
-
// in the same render would target whichever tab focus landed on — racy across
|
|
71
|
-
// suite ordering. Each test focuses one known tab and asserts a single hop.
|
|
72
|
-
it('moves to the next tab with ArrowRight', async () => {
|
|
73
|
-
const onchange = vi.fn();
|
|
74
|
-
render(Tabs, { props: { tabs: TABS, active: 'overview', onchange } });
|
|
75
|
-
screen.getByRole('tab', { name: 'Overview' }).focus();
|
|
76
|
-
await userEvent.keyboard('{ArrowRight}');
|
|
77
|
-
expect(onchange).toHaveBeenLastCalledWith('activity');
|
|
78
|
-
});
|
|
79
|
-
it('moves to the previous tab with ArrowLeft', async () => {
|
|
80
|
-
const onchange = vi.fn();
|
|
81
|
-
// Render with Activity active so it owns the roving tabindex and is focusable.
|
|
82
|
-
// Activity carries a count badge, so its accessible name is "Activity 4".
|
|
83
|
-
render(Tabs, { props: { tabs: TABS, active: 'activity', onchange } });
|
|
84
|
-
screen.getByRole('tab', { name: /Activity/ }).focus();
|
|
85
|
-
await userEvent.keyboard('{ArrowLeft}');
|
|
86
|
-
expect(onchange).toHaveBeenLastCalledWith('overview');
|
|
87
|
-
});
|
|
88
|
-
it('wraps from the first tab to the last with ArrowLeft', async () => {
|
|
89
|
-
const onchange = vi.fn();
|
|
90
|
-
render(Tabs, { props: { tabs: TABS, active: 'overview', onchange } });
|
|
91
|
-
screen.getByRole('tab', { name: 'Overview' }).focus();
|
|
92
|
-
await userEvent.keyboard('{ArrowLeft}');
|
|
93
|
-
expect(onchange).toHaveBeenLastCalledWith('settings');
|
|
94
|
-
});
|
|
95
|
-
it('jumps to the first/last tab with Home/End', async () => {
|
|
96
|
-
const onchange = vi.fn();
|
|
97
|
-
render(Tabs, { props: { tabs: TABS, active: 'activity', onchange } });
|
|
98
|
-
screen.getByRole('tab', { name: /Activity/ }).focus();
|
|
99
|
-
await userEvent.keyboard('{End}');
|
|
100
|
-
expect(onchange).toHaveBeenLastCalledWith('settings');
|
|
101
|
-
await userEvent.keyboard('{Home}');
|
|
102
|
-
expect(onchange).toHaveBeenLastCalledWith('overview');
|
|
103
|
-
});
|
|
104
|
-
it('skips disabled tabs during keyboard navigation', async () => {
|
|
105
|
-
const onchange = vi.fn();
|
|
106
|
-
const tabs = [
|
|
107
|
-
{ id: 'a', label: 'A' },
|
|
108
|
-
{ id: 'b', label: 'B', disabled: true },
|
|
109
|
-
{ id: 'c', label: 'C' },
|
|
110
|
-
];
|
|
111
|
-
render(Tabs, { props: { tabs, active: 'a', onchange } });
|
|
112
|
-
expect(screen.getByRole('tab', { name: 'B' })).toBeDisabled();
|
|
113
|
-
screen.getByRole('tab', { name: 'A' }).focus();
|
|
114
|
-
await userEvent.keyboard('{ArrowRight}');
|
|
115
|
-
expect(onchange).toHaveBeenLastCalledWith('c');
|
|
116
|
-
});
|
|
117
|
-
it('is axe-clean with a labelled tablist and panel', async () => {
|
|
118
|
-
const { container } = render(Tabs, {
|
|
119
|
-
props: {
|
|
120
|
-
tabs: TABS,
|
|
121
|
-
active: 'overview',
|
|
122
|
-
'aria-label': 'Sections',
|
|
123
|
-
children: panelSnippet('Panel content'),
|
|
124
|
-
},
|
|
125
|
-
});
|
|
126
|
-
await expectNoA11yViolations(container);
|
|
127
|
-
});
|
|
128
|
-
});
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Component test for RoleSelector (#1586 remediation, epic #1354).
|
|
3
|
-
*
|
|
4
|
-
* RoleSelector is a single-select listbox: a trigger button (`aria-haspopup`/
|
|
5
|
-
* `aria-expanded`) opens a `role="listbox"` of `role="option"` buttons. This
|
|
6
|
-
* suite covers the keyboard support added to match the WAI-ARIA listbox pattern
|
|
7
|
-
* (mirroring `ui/Dropdown.svelte`): open on Enter/ArrowDown, focus-into-list,
|
|
8
|
-
* Arrow/Home/End roving focus, Enter to select, and Escape to close + refocus
|
|
9
|
-
* the trigger. Axe-cleanliness is asserted for both open and closed states.
|
|
10
|
-
*/
|
|
11
|
-
import { render, screen } from '@testing-library/svelte';
|
|
12
|
-
import userEvent from '@testing-library/user-event';
|
|
13
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
14
|
-
import { expectNoA11yViolations } from '../../../test-support/a11y';
|
|
15
|
-
import RoleSelector from '../RoleSelector.svelte';
|
|
16
|
-
function role(id, name, isSystem = false) {
|
|
17
|
-
return {
|
|
18
|
-
id,
|
|
19
|
-
slug: id,
|
|
20
|
-
created_at: null,
|
|
21
|
-
updated_at: null,
|
|
22
|
-
tenantId: null,
|
|
23
|
-
name,
|
|
24
|
-
description: `${name} role`,
|
|
25
|
-
isSystem,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
const ROLES = [
|
|
29
|
-
role('admin', 'Admin', true),
|
|
30
|
-
role('editor', 'Editor'),
|
|
31
|
-
role('viewer', 'Viewer'),
|
|
32
|
-
];
|
|
33
|
-
describe('RoleSelector', () => {
|
|
34
|
-
it('exposes a collapsed listbox trigger by default', () => {
|
|
35
|
-
render(RoleSelector, { props: { roles: ROLES, onchange: vi.fn() } });
|
|
36
|
-
const trigger = screen.getByRole('button');
|
|
37
|
-
expect(trigger).toHaveAttribute('aria-haspopup', 'listbox');
|
|
38
|
-
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
39
|
-
expect(screen.queryByRole('listbox')).toBeNull();
|
|
40
|
-
});
|
|
41
|
-
it('shows the placeholder when no role is selected', () => {
|
|
42
|
-
render(RoleSelector, {
|
|
43
|
-
props: { roles: ROLES, onchange: vi.fn(), placeholder: 'Pick one' },
|
|
44
|
-
});
|
|
45
|
-
expect(screen.getByText('Pick one')).toBeInTheDocument();
|
|
46
|
-
});
|
|
47
|
-
it('opens via click and exposes the options as a listbox', async () => {
|
|
48
|
-
render(RoleSelector, { props: { roles: ROLES, onchange: vi.fn() } });
|
|
49
|
-
await userEvent.click(screen.getByRole('button'));
|
|
50
|
-
expect(screen.getByRole('listbox')).toBeInTheDocument();
|
|
51
|
-
expect(screen.getAllByRole('option')).toHaveLength(3);
|
|
52
|
-
});
|
|
53
|
-
it('opens on Enter and moves focus onto the first option', async () => {
|
|
54
|
-
render(RoleSelector, { props: { roles: ROLES, onchange: vi.fn() } });
|
|
55
|
-
screen.getByRole('button').focus();
|
|
56
|
-
await userEvent.keyboard('{Enter}');
|
|
57
|
-
const options = screen.getAllByRole('option');
|
|
58
|
-
expect(options[0]).toHaveFocus();
|
|
59
|
-
});
|
|
60
|
-
it('opens on ArrowDown and focuses the already-selected option', async () => {
|
|
61
|
-
render(RoleSelector, {
|
|
62
|
-
props: { roles: ROLES, value: 'viewer', onchange: vi.fn() },
|
|
63
|
-
});
|
|
64
|
-
screen.getByRole('button').focus();
|
|
65
|
-
await userEvent.keyboard('{ArrowDown}');
|
|
66
|
-
const viewer = screen.getByRole('option', { name: /Viewer/ });
|
|
67
|
-
expect(viewer).toHaveFocus();
|
|
68
|
-
});
|
|
69
|
-
it('roves focus with ArrowDown/ArrowUp and wraps at the ends', async () => {
|
|
70
|
-
render(RoleSelector, { props: { roles: ROLES, onchange: vi.fn() } });
|
|
71
|
-
screen.getByRole('button').focus();
|
|
72
|
-
await userEvent.keyboard('{Enter}'); // focuses option 0 (Admin)
|
|
73
|
-
const options = screen.getAllByRole('option');
|
|
74
|
-
await userEvent.keyboard('{ArrowDown}');
|
|
75
|
-
expect(options[1]).toHaveFocus();
|
|
76
|
-
await userEvent.keyboard('{ArrowDown}');
|
|
77
|
-
expect(options[2]).toHaveFocus();
|
|
78
|
-
await userEvent.keyboard('{ArrowDown}'); // wraps to first
|
|
79
|
-
expect(options[0]).toHaveFocus();
|
|
80
|
-
await userEvent.keyboard('{ArrowUp}'); // wraps to last
|
|
81
|
-
expect(options[2]).toHaveFocus();
|
|
82
|
-
});
|
|
83
|
-
it('jumps to the first/last option with Home/End', async () => {
|
|
84
|
-
render(RoleSelector, { props: { roles: ROLES, onchange: vi.fn() } });
|
|
85
|
-
screen.getByRole('button').focus();
|
|
86
|
-
await userEvent.keyboard('{Enter}');
|
|
87
|
-
const options = screen.getAllByRole('option');
|
|
88
|
-
await userEvent.keyboard('{End}');
|
|
89
|
-
expect(options[2]).toHaveFocus();
|
|
90
|
-
await userEvent.keyboard('{Home}');
|
|
91
|
-
expect(options[0]).toHaveFocus();
|
|
92
|
-
});
|
|
93
|
-
it('selects the focused option with Enter and fires onchange', async () => {
|
|
94
|
-
const onchange = vi.fn();
|
|
95
|
-
render(RoleSelector, { props: { roles: ROLES, onchange } });
|
|
96
|
-
screen.getByRole('button').focus();
|
|
97
|
-
await userEvent.keyboard('{Enter}'); // open, focus Admin
|
|
98
|
-
await userEvent.keyboard('{ArrowDown}'); // focus Editor
|
|
99
|
-
await userEvent.keyboard('{Enter}'); // select Editor
|
|
100
|
-
expect(onchange).toHaveBeenCalledWith('editor');
|
|
101
|
-
expect(screen.queryByRole('listbox')).toBeNull();
|
|
102
|
-
});
|
|
103
|
-
it('closes on Escape and restores focus to the trigger', async () => {
|
|
104
|
-
render(RoleSelector, { props: { roles: ROLES, onchange: vi.fn() } });
|
|
105
|
-
const trigger = screen.getByRole('button');
|
|
106
|
-
trigger.focus();
|
|
107
|
-
await userEvent.keyboard('{Enter}');
|
|
108
|
-
expect(screen.getByRole('listbox')).toBeInTheDocument();
|
|
109
|
-
await userEvent.keyboard('{Escape}');
|
|
110
|
-
expect(screen.queryByRole('listbox')).toBeNull();
|
|
111
|
-
expect(trigger).toHaveFocus();
|
|
112
|
-
});
|
|
113
|
-
it('does not open when disabled', async () => {
|
|
114
|
-
render(RoleSelector, {
|
|
115
|
-
props: { roles: ROLES, onchange: vi.fn(), disabled: true },
|
|
116
|
-
});
|
|
117
|
-
const trigger = screen.getByRole('button');
|
|
118
|
-
await userEvent.click(trigger);
|
|
119
|
-
expect(screen.queryByRole('listbox')).toBeNull();
|
|
120
|
-
});
|
|
121
|
-
it('is axe-clean when closed', async () => {
|
|
122
|
-
const { container } = render(RoleSelector, {
|
|
123
|
-
props: { roles: ROLES, value: 'admin', onchange: vi.fn() },
|
|
124
|
-
});
|
|
125
|
-
await expectNoA11yViolations(container);
|
|
126
|
-
});
|
|
127
|
-
it('is axe-clean when open', async () => {
|
|
128
|
-
const { container } = render(RoleSelector, {
|
|
129
|
-
props: { roles: ROLES, onchange: vi.fn(), showDescription: true },
|
|
130
|
-
});
|
|
131
|
-
await userEvent.click(screen.getByRole('button'));
|
|
132
|
-
await expectNoA11yViolations(container);
|
|
133
|
-
});
|
|
134
|
-
});
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Component test for Badge (Sweep S11, #1416).
|
|
3
|
-
*
|
|
4
|
-
* Badge is a presentational `<span>` — it renders children plus variant/size
|
|
5
|
-
* classes and forwards rest attributes. This suite asserts that real API
|
|
6
|
-
* (props from Badge.svelte) and proves the output is axe-clean.
|
|
7
|
-
*/
|
|
8
|
-
import { render, screen } from '@testing-library/svelte';
|
|
9
|
-
import { createRawSnippet } from 'svelte';
|
|
10
|
-
import { describe, expect, it } from 'vitest';
|
|
11
|
-
import { expectNoA11yViolations } from '../../../test-support/a11y';
|
|
12
|
-
import Badge from '../Badge.svelte';
|
|
13
|
-
/** Build a text Snippet for the Badge's `children` prop. */
|
|
14
|
-
function textSnippet(text) {
|
|
15
|
-
return createRawSnippet(() => ({ render: () => `<span>${text}</span>` }));
|
|
16
|
-
}
|
|
17
|
-
describe('Badge', () => {
|
|
18
|
-
it('renders its children content', () => {
|
|
19
|
-
render(Badge, { props: { children: textSnippet('New') } });
|
|
20
|
-
expect(screen.getByText('New')).toBeInTheDocument();
|
|
21
|
-
});
|
|
22
|
-
it('applies the default variant and md size classes', () => {
|
|
23
|
-
const { container } = render(Badge, {
|
|
24
|
-
props: { children: textSnippet('Default') },
|
|
25
|
-
});
|
|
26
|
-
const badge = container.querySelector('.badge');
|
|
27
|
-
expect(badge).toHaveClass('default');
|
|
28
|
-
expect(badge).toHaveClass('md');
|
|
29
|
-
});
|
|
30
|
-
it.each([
|
|
31
|
-
'primary',
|
|
32
|
-
'success',
|
|
33
|
-
'warning',
|
|
34
|
-
'error',
|
|
35
|
-
'info',
|
|
36
|
-
])('reflects the %s variant as a class', (variant) => {
|
|
37
|
-
const { container } = render(Badge, {
|
|
38
|
-
props: { variant, children: textSnippet('Status') },
|
|
39
|
-
});
|
|
40
|
-
expect(container.querySelector('.badge')).toHaveClass(variant);
|
|
41
|
-
});
|
|
42
|
-
it('reflects the sm size as a class', () => {
|
|
43
|
-
const { container } = render(Badge, {
|
|
44
|
-
props: { size: 'sm', children: textSnippet('Small') },
|
|
45
|
-
});
|
|
46
|
-
expect(container.querySelector('.badge')).toHaveClass('sm');
|
|
47
|
-
});
|
|
48
|
-
it('forwards rest attributes (e.g. aria-label, data-testid) to the span', () => {
|
|
49
|
-
const { container } = render(Badge, {
|
|
50
|
-
props: {
|
|
51
|
-
'aria-label': 'Unread count: 3',
|
|
52
|
-
'data-testid': 'unread-badge',
|
|
53
|
-
children: textSnippet('3'),
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
const badge = container.querySelector('.badge');
|
|
57
|
-
expect(badge).toHaveAttribute('aria-label', 'Unread count: 3');
|
|
58
|
-
expect(badge).toHaveAttribute('data-testid', 'unread-badge');
|
|
59
|
-
});
|
|
60
|
-
it('is axe-clean for a default badge', async () => {
|
|
61
|
-
const { container } = render(Badge, {
|
|
62
|
-
props: { children: textSnippet('Accessible') },
|
|
63
|
-
});
|
|
64
|
-
await expectNoA11yViolations(container);
|
|
65
|
-
});
|
|
66
|
-
it('is axe-clean for a variant badge with an accessible label', async () => {
|
|
67
|
-
const { container } = render(Badge, {
|
|
68
|
-
props: {
|
|
69
|
-
variant: 'error',
|
|
70
|
-
'aria-label': '5 errors',
|
|
71
|
-
children: textSnippet('5'),
|
|
72
|
-
},
|
|
73
|
-
});
|
|
74
|
-
await expectNoA11yViolations(container);
|
|
75
|
-
});
|
|
76
|
-
});
|