@dile/ui 3.18.0 → 3.18.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/components/floating-menu/src/DileFloatingMenu.js +195 -61
- package/components/floating-menu/src/DileFloatingMenuItem.js +12 -5
- package/components/toast/src/DileToast.js +2 -1
- package/components/toast/src/DileToastPersistent.js +1 -1
- package/package.json +4 -4
- package/components/accordion/accordion.spec.js +0 -253
- package/components/app-drawer/app-drawer.spec.js +0 -262
- package/components/avatar/avatar.spec.js +0 -25
- package/components/bottom-nav/__screenshots__/bottom-nav.spec.js/dile-bottom-nav-places-the-sheet-and-the-overlay-above-the-bar-1.png +0 -0
- package/components/bottom-nav/bottom-nav.spec.js +0 -340
- package/components/box-selector/box-selector-item.spec.js +0 -27
- package/components/box-selector/box-selector.spec.js +0 -27
- package/components/breadcrumbs/breadcrumbs-item.spec.js +0 -28
- package/components/breadcrumbs/breadcrumbs.spec.js +0 -33
- package/components/button/button.spec.js +0 -234
- package/components/card/card-slide.spec.js +0 -30
- package/components/card/card.spec.js +0 -26
- package/components/checkbox/checkbox.spec.js +0 -235
- package/components/chip/chip.spec.js +0 -31
- package/components/color-picker/color-picker.spec.js +0 -133
- package/components/confirm/confirm.spec.js +0 -57
- package/components/confirm-text/confirm-text.spec.js +0 -29
- package/components/copy-markdown-url/copy-markdown-url.spec.js +0 -27
- package/components/copy-text/copy-text.spec.js +0 -38
- package/components/data-grid/__screenshots__/data-grid.spec.js/dile-data-grid-dispatches-item-checkbox-changed-and-dile-data-grid-item-selected-when-a-checkbox-is-toggled-1.png +0 -0
- package/components/data-grid/data-grid.spec.js +0 -421
- package/components/drop-file/drop-file.spec.js +0 -214
- package/components/drop-file/file-preview.spec.js +0 -35
- package/components/floating-feedback/floating-feedback.spec.js +0 -30
- package/components/floating-menu/floating-menu-item.spec.js +0 -27
- package/components/floating-menu/floating-menu.spec.js +0 -31
- package/components/form-separator/form-separator.spec.js +0 -28
- package/components/hamburger/hamburger.spec.js +0 -28
- package/components/icon/icon.spec.js +0 -31
- package/components/icon-switch/icon-switch-group.spec.js +0 -46
- package/components/icon-switch/icon-switch.spec.js +0 -35
- package/components/info-box/info-box.spec.js +0 -38
- package/components/inline-feedback/inline-feedback.spec.js +0 -46
- package/components/input/input-contact.spec.js +0 -32
- package/components/input/input-icon.spec.js +0 -166
- package/components/input/input-integer.spec.js +0 -31
- package/components/input/input-mask.spec.js +0 -314
- package/components/input/input-message.spec.js +0 -27
- package/components/input/input-money.spec.js +0 -30
- package/components/input/input-number-mask.spec.js +0 -48
- package/components/input/input-number.spec.js +0 -109
- package/components/input/input-percentage.spec.js +0 -31
- package/components/input/input-search.spec.js +0 -91
- package/components/input/input.spec.js +0 -47
- package/components/light-mode-switch/light-mode-switch.spec.js +0 -34
- package/components/menu-hamburger/menu-hamburger.spec.js +0 -34
- package/components/menu-overlay/menu-overlay.spec.js +0 -44
- package/components/message/message.spec.js +0 -42
- package/components/modal/__screenshots__/modal.spec.js/dile-modal-closes-only-the-topmost-modal-when-Esc-is-pressed-1.png +0 -0
- package/components/modal/__screenshots__/modal.spec.js/dile-modal-dispatches-dile-modal-closed-and-animates-when-the-opened-property-is-set-to-false-1.png +0 -0
- package/components/modal/__screenshots__/modal.spec.js/dile-modal-does-not-close-a-blocking-modal-when-Esc-is-pressed-1.png +0 -0
- package/components/modal/__screenshots__/modal.spec.js/dile-modal-does-not-close-the-modal-below-when-the-topmost-modal-is-blocking-1.png +0 -0
- package/components/modal/__screenshots__/modal.spec.js/dile-modal-ignores-transitionend-events-coming-from-inner-elements-1.png +0 -0
- package/components/modal/__screenshots__/modal.spec.js/dile-modal-keeps-the-focus-on-content-focused-by-the-user-when-opening-1.png +0 -0
- package/components/modal/__screenshots__/modal.spec.js/dile-modal-opens-and-closes-through-the-opened-attribute-1.png +0 -0
- package/components/modal/__screenshots__/modal.spec.js/dile-modal-reflects-the-opened-property-to-the-attribute-1.png +0 -0
- package/components/modal/__screenshots__/modal.spec.js/dile-modal-releases-the-background-layer-after-the-close-animation-even-without-transitionend-1.png +0 -0
- package/components/modal/__screenshots__/modal.spec.js/dile-modal-releases-the-background-layer-immediately-when-the-animation-duration-is-0s-1.png +0 -0
- package/components/modal/modal-help.spec.js +0 -32
- package/components/modal/modal.spec.js +0 -250
- package/components/nav/nav.spec.js +0 -33
- package/components/number-picker/number-picker-element.spec.js +0 -30
- package/components/number-picker/number-picker.spec.js +0 -30
- package/components/order-switch/__screenshots__/order-switch.spec.js/dile-order-switch-clicking-the-label-re-announces-the-current-value-without-toggling-when-not-selected-1.png +0 -0
- package/components/order-switch/__screenshots__/order-switch.spec.js/dile-order-switch-clicking-the-label-toggles-the-order-when-selected-1.png +0 -0
- package/components/order-switch/__screenshots__/order-switch.spec.js/dile-order-switch-defaults-to-ascending-order-1.png +0 -0
- package/components/order-switch/order-switch.spec.js +0 -57
- package/components/otp-input/otp-input.spec.js +0 -41
- package/components/pages/pages.spec.js +0 -44
- package/components/password/password.spec.js +0 -35
- package/components/progress-bar/progress-bar.spec.js +0 -28
- package/components/radio-group/__screenshots__/radio-group-dialog.spec.js/dile-radio-group-dialog-renders-dialog-items-with-labels-and-values-1.png +0 -0
- package/components/radio-group/__screenshots__/radio-group-dialog.spec.js/dile-radio-group-dialog-renders-items-with-optional-description-1.png +0 -0
- package/components/radio-group/__screenshots__/radio-group-dialog.spec.js/dile-radio-group-dialog-updates-value-when-an-option-is-selected-1.png +0 -0
- package/components/radio-group/radio-group-dialog.spec.js +0 -126
- package/components/radio-group/radio-group.spec.js +0 -128
- package/components/radio-group/radio.spec.js +0 -32
- package/components/range/range.spec.js +0 -36
- package/components/rating/rating.spec.js +0 -34
- package/components/rating/star.spec.js +0 -30
- package/components/rating-scale-question/rating-scale-option.spec.js +0 -32
- package/components/rating-scale-question/rating-scale-question.spec.js +0 -35
- package/components/select/__screenshots__/select-search.spec.js/dile-select-search-Value-API-uses-the-label-as-accessible-name-of-the-selected-field-1.png +0 -0
- package/components/select/select-ajax-overlay.spec.js +0 -469
- package/components/select/select-overlay.spec.js +0 -612
- package/components/select/select-search.spec.js +0 -318
- package/components/select/select.spec.js +0 -574
- package/components/selector/selector-item.spec.js +0 -40
- package/components/selector/selector-overlay.spec.js +0 -139
- package/components/selector/selector.spec.js +0 -45
- package/components/slide-menu/slide-menu.spec.js +0 -38
- package/components/slide-show/slide-show.spec.js +0 -34
- package/components/social-icon/social-icon.spec.js +0 -26
- package/components/spinner/spinner-bar.spec.js +0 -26
- package/components/spinner/spinner-block.spec.js +0 -21
- package/components/spinner/spinner-horizontal.spec.js +0 -25
- package/components/spinner/spinner-icon.spec.js +0 -25
- package/components/spinner/spinner-modal.spec.js +0 -26
- package/components/spinner/spinner.spec.js +0 -26
- package/components/steps/steps.spec.js +0 -84
- package/components/switch/switch.spec.js +0 -33
- package/components/tabs/tabs.spec.js +0 -85
- package/components/textarea/textarea.spec.js +0 -39
- package/components/time-picker/time-picker.spec.js +0 -26
- package/components/timer/timer.spec.js +0 -31
- package/components/toast/toast.spec.js +0 -86
- package/components/tooltip/chip-tooltip.spec.js +0 -29
- package/components/tooltip/tooltip.spec.js +0 -32
- package/components/web-visor/web-visor.spec.js +0 -32
- package/mixins/form/src/DileForm.spec.js +0 -29
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
-
import './button.js';
|
|
3
|
-
|
|
4
|
-
describe('dile-button', () => {
|
|
5
|
-
afterEach(() => {
|
|
6
|
-
document.body.innerHTML = '';
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
async function renderButton(html) {
|
|
10
|
-
document.body.innerHTML = html;
|
|
11
|
-
const el = document.body.querySelector('dile-button');
|
|
12
|
-
await el.updateComplete;
|
|
13
|
-
return el;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
it('renders the slotted content inside a native button', async () => {
|
|
17
|
-
const el = await renderButton('<dile-button>Click me</dile-button>');
|
|
18
|
-
|
|
19
|
-
expect(el.shadowRoot.querySelector('button')).toBeTruthy();
|
|
20
|
-
expect(el.textContent.trim()).toBe('Click me');
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('reflects the disabled property onto the native button', async () => {
|
|
24
|
-
const el = await renderButton('<dile-button disabled>Click me</dile-button>');
|
|
25
|
-
|
|
26
|
-
expect(el.shadowRoot.querySelector('button').disabled).toBe(true);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('dispatches a click event when enabled', async () => {
|
|
30
|
-
const el = await renderButton('<dile-button>Click me</dile-button>');
|
|
31
|
-
let clicked = false;
|
|
32
|
-
el.addEventListener('click', () => { clicked = true; });
|
|
33
|
-
|
|
34
|
-
el.shadowRoot.querySelector('button').click();
|
|
35
|
-
|
|
36
|
-
expect(clicked).toBe(true);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('shows a spinner icon while loading', async () => {
|
|
40
|
-
const el = await renderButton('<dile-button>Save</dile-button>');
|
|
41
|
-
expect(el.shadowRoot.querySelector('dile-spinner-icon')).toBeNull();
|
|
42
|
-
|
|
43
|
-
el.loading = true;
|
|
44
|
-
await el.updateComplete;
|
|
45
|
-
|
|
46
|
-
expect(el.shadowRoot.querySelector('dile-spinner-icon')).toBeTruthy();
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('renders the loading spinner after the label (far right)', async () => {
|
|
50
|
-
const el = await renderButton('<dile-button loading>Save</dile-button>');
|
|
51
|
-
const children = [...el.shadowRoot.querySelector('button').children].map(n => n.tagName.toLowerCase());
|
|
52
|
-
expect(children.indexOf('dile-spinner-icon')).toBeGreaterThan(children.indexOf('slot'));
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
describe('icon support', () => {
|
|
56
|
-
it('does not render an icon element when no icon is provided (backwards compatible)', async () => {
|
|
57
|
-
const el = await renderButton('<dile-button>Plain</dile-button>');
|
|
58
|
-
expect(el.shadowRoot.querySelector('dile-iconlib')).toBeNull();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('renders a dile-iconlib icon from a "family.name" string', async () => {
|
|
62
|
-
const el = await renderButton('<dile-button icon="lucide.rocket">Launch</dile-button>');
|
|
63
|
-
const icon = el.shadowRoot.querySelector('dile-iconlib');
|
|
64
|
-
expect(icon).toBeTruthy();
|
|
65
|
-
expect(icon.getAttribute('icon')).toBe('lucide.rocket');
|
|
66
|
-
expect(icon.getAttribute('aria-hidden')).toBe('true');
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('places the icon before the label by default and after it when iconPosition is "right"', async () => {
|
|
70
|
-
const el = await renderButton('<dile-button icon="lucide.rocket">Launch</dile-button>');
|
|
71
|
-
let children = [...el.shadowRoot.querySelector('button').children].map(n => n.tagName.toLowerCase());
|
|
72
|
-
expect(children.indexOf('dile-iconlib')).toBeLessThan(children.indexOf('slot'));
|
|
73
|
-
|
|
74
|
-
el.iconPosition = 'right';
|
|
75
|
-
await el.updateComplete;
|
|
76
|
-
children = [...el.shadowRoot.querySelector('button').children].map(n => n.tagName.toLowerCase());
|
|
77
|
-
expect(children.indexOf('dile-iconlib')).toBeGreaterThan(children.indexOf('slot'));
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('reads the icon position from the "icon-position" attribute', async () => {
|
|
81
|
-
const el = await renderButton('<dile-button icon="lucide.rocket" icon-position="right">Continue</dile-button>');
|
|
82
|
-
expect(el.iconPosition).toBe('right');
|
|
83
|
-
const children = [...el.shadowRoot.querySelector('button').children].map(n => n.tagName.toLowerCase());
|
|
84
|
-
expect(children.indexOf('dile-iconlib')).toBeGreaterThan(children.indexOf('slot'));
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('marks the button as having text only when the slot has content', async () => {
|
|
88
|
-
const withText = await renderButton('<dile-button icon="lucide.rocket">Launch</dile-button>');
|
|
89
|
-
expect(withText.shadowRoot.querySelector('button').classList.contains('has-text')).toBe(true);
|
|
90
|
-
|
|
91
|
-
const iconOnly = await renderButton('<dile-button icon="lucide.rocket" label="Launch"></dile-button>');
|
|
92
|
-
expect(iconOnly.shadowRoot.querySelector('button').classList.contains('has-text')).toBe(false);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('exposes the label as the accessible name of the inner button', async () => {
|
|
96
|
-
const el = await renderButton('<dile-button icon="lucide.rocket" label="Launch rocket"></dile-button>');
|
|
97
|
-
expect(el.shadowRoot.querySelector('button').getAttribute('aria-label')).toBe('Launch rocket');
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
describe('Native form submission', () => {
|
|
102
|
-
it('includes name/value in the FormData when clicked', async () => {
|
|
103
|
-
document.body.innerHTML = `
|
|
104
|
-
<form id="testForm">
|
|
105
|
-
<dile-button type="submit" name="action" value="save">Save</dile-button>
|
|
106
|
-
</form>
|
|
107
|
-
`;
|
|
108
|
-
const form = document.getElementById('testForm');
|
|
109
|
-
const el = document.body.querySelector('dile-button');
|
|
110
|
-
await el.updateComplete;
|
|
111
|
-
|
|
112
|
-
let capturedFormData = null;
|
|
113
|
-
form.addEventListener('submit', (e) => {
|
|
114
|
-
e.preventDefault();
|
|
115
|
-
capturedFormData = new FormData(form);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
el.shadowRoot.querySelector('button').click();
|
|
119
|
-
|
|
120
|
-
expect(capturedFormData.get('action')).toBe('save');
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('does not submit a name/value pair when the button has no value', async () => {
|
|
124
|
-
document.body.innerHTML = `
|
|
125
|
-
<form id="testForm">
|
|
126
|
-
<dile-button type="submit" name="action">Save</dile-button>
|
|
127
|
-
</form>
|
|
128
|
-
`;
|
|
129
|
-
const form = document.getElementById('testForm');
|
|
130
|
-
const el = document.body.querySelector('dile-button');
|
|
131
|
-
await el.updateComplete;
|
|
132
|
-
|
|
133
|
-
let capturedFormData = null;
|
|
134
|
-
form.addEventListener('submit', (e) => {
|
|
135
|
-
e.preventDefault();
|
|
136
|
-
capturedFormData = new FormData(form);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
el.shadowRoot.querySelector('button').click();
|
|
140
|
-
|
|
141
|
-
expect(capturedFormData.has('action')).toBe(false);
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it('participates in FormData when name is set as a JS property', async () => {
|
|
145
|
-
document.body.innerHTML = `
|
|
146
|
-
<form id="testForm">
|
|
147
|
-
<dile-button type="submit" value="save">Save</dile-button>
|
|
148
|
-
</form>
|
|
149
|
-
`;
|
|
150
|
-
const form = document.getElementById('testForm');
|
|
151
|
-
const el = document.body.querySelector('dile-button');
|
|
152
|
-
el.name = 'action';
|
|
153
|
-
await el.updateComplete;
|
|
154
|
-
|
|
155
|
-
expect(el.getAttribute('name')).toBe('action');
|
|
156
|
-
|
|
157
|
-
let capturedFormData = null;
|
|
158
|
-
form.addEventListener('submit', (e) => {
|
|
159
|
-
e.preventDefault();
|
|
160
|
-
capturedFormData = new FormData(form);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
el.shadowRoot.querySelector('button').click();
|
|
164
|
-
|
|
165
|
-
expect(capturedFormData.get('action')).toBe('save');
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it('only includes the clicked button among two submit buttons with different values', async () => {
|
|
169
|
-
document.body.innerHTML = `
|
|
170
|
-
<form id="testForm">
|
|
171
|
-
<dile-button type="submit" name="action" value="save">Save</dile-button>
|
|
172
|
-
<dile-button type="submit" name="action" value="delete">Delete</dile-button>
|
|
173
|
-
</form>
|
|
174
|
-
`;
|
|
175
|
-
const form = document.getElementById('testForm');
|
|
176
|
-
const buttons = document.body.querySelectorAll('dile-button');
|
|
177
|
-
for (const b of buttons) await b.updateComplete;
|
|
178
|
-
|
|
179
|
-
let capturedFormData = null;
|
|
180
|
-
form.addEventListener('submit', (e) => {
|
|
181
|
-
e.preventDefault();
|
|
182
|
-
capturedFormData = new FormData(form);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
buttons[1].shadowRoot.querySelector('button').click();
|
|
186
|
-
|
|
187
|
-
expect(capturedFormData.getAll('action')).toEqual(['delete']);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
it('does not leak a stale value when the form is submitted again without a button click', async () => {
|
|
191
|
-
document.body.innerHTML = `
|
|
192
|
-
<form id="testForm">
|
|
193
|
-
<input name="text" value="hello" />
|
|
194
|
-
<dile-button type="submit" name="action" value="save">Save</dile-button>
|
|
195
|
-
</form>
|
|
196
|
-
`;
|
|
197
|
-
const form = document.getElementById('testForm');
|
|
198
|
-
const el = document.body.querySelector('dile-button');
|
|
199
|
-
await el.updateComplete;
|
|
200
|
-
|
|
201
|
-
let capturedFormData = null;
|
|
202
|
-
form.addEventListener('submit', (e) => {
|
|
203
|
-
e.preventDefault();
|
|
204
|
-
capturedFormData = new FormData(form);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
// First submit via the button click - action=save should be present.
|
|
208
|
-
el.shadowRoot.querySelector('button').click();
|
|
209
|
-
expect(capturedFormData.get('action')).toBe('save');
|
|
210
|
-
|
|
211
|
-
// Second submit programmatically, with no submitter clicked - action should NOT leak.
|
|
212
|
-
form.requestSubmit();
|
|
213
|
-
expect(capturedFormData.get('action')).toBeNull();
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('does not submit when the button is disabled', async () => {
|
|
217
|
-
document.body.innerHTML = `
|
|
218
|
-
<form id="testForm">
|
|
219
|
-
<dile-button type="submit" name="action" value="save" disabled>Save</dile-button>
|
|
220
|
-
</form>
|
|
221
|
-
`;
|
|
222
|
-
const form = document.getElementById('testForm');
|
|
223
|
-
const el = document.body.querySelector('dile-button');
|
|
224
|
-
await el.updateComplete;
|
|
225
|
-
|
|
226
|
-
let submitted = false;
|
|
227
|
-
form.addEventListener('submit', (e) => { e.preventDefault(); submitted = true; });
|
|
228
|
-
|
|
229
|
-
el.shadowRoot.querySelector('button').click();
|
|
230
|
-
|
|
231
|
-
expect(submitted).toBe(false);
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
});
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
-
import './card-slide.js';
|
|
3
|
-
|
|
4
|
-
describe('dile-card-slide', () => {
|
|
5
|
-
afterEach(() => {
|
|
6
|
-
document.body.innerHTML = '';
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
async function renderCardSlide(html) {
|
|
10
|
-
document.body.innerHTML = html;
|
|
11
|
-
const el = document.body.querySelector('dile-card-slide');
|
|
12
|
-
await el.updateComplete;
|
|
13
|
-
return el;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
it('renders the title as a toggle button', async () => {
|
|
17
|
-
const el = await renderCardSlide('<dile-card-slide title="My title">Content</dile-card-slide>');
|
|
18
|
-
const button = el.shadowRoot.querySelector('.card-title button');
|
|
19
|
-
expect(button).toBeTruthy();
|
|
20
|
-
expect(el.opened).toBe(false);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('toggles opened state when clicked', async () => {
|
|
24
|
-
const el = await renderCardSlide('<dile-card-slide title="My title">Content</dile-card-slide>');
|
|
25
|
-
el.shadowRoot.querySelector('.card-title button').click();
|
|
26
|
-
await el.updateComplete;
|
|
27
|
-
|
|
28
|
-
expect(el.opened).toBe(true);
|
|
29
|
-
});
|
|
30
|
-
});
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
-
import './card.js';
|
|
3
|
-
|
|
4
|
-
describe('dile-card', () => {
|
|
5
|
-
afterEach(() => {
|
|
6
|
-
document.body.innerHTML = '';
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
async function renderCard(html) {
|
|
10
|
-
document.body.innerHTML = html;
|
|
11
|
-
const el = document.body.querySelector('dile-card');
|
|
12
|
-
await el.updateComplete;
|
|
13
|
-
return el;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
it('renders the title and slotted content', async () => {
|
|
17
|
-
const el = await renderCard('<dile-card title="My title">Content</dile-card>');
|
|
18
|
-
expect(el.shadowRoot.querySelector('.card-title').textContent.trim()).toBe('My title');
|
|
19
|
-
expect(el.textContent.trim()).toBe('Content');
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('does not render a title element when title is not set', async () => {
|
|
23
|
-
const el = await renderCard('<dile-card>Content</dile-card>');
|
|
24
|
-
expect(el.shadowRoot.querySelector('.card-title')).toBeNull();
|
|
25
|
-
});
|
|
26
|
-
});
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
-
import './checkbox.js';
|
|
3
|
-
|
|
4
|
-
describe('dile-checkbox', () => {
|
|
5
|
-
afterEach(() => {
|
|
6
|
-
document.body.innerHTML = '';
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
async function renderCheckbox(html) {
|
|
10
|
-
document.body.innerHTML = html;
|
|
11
|
-
const el = document.body.querySelector('dile-checkbox');
|
|
12
|
-
await el.updateComplete;
|
|
13
|
-
return el;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function getControl(el) {
|
|
17
|
-
return el.shadowRoot.querySelector('[role="checkbox"]');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
describe('Rendering', () => {
|
|
21
|
-
it('starts unchecked by default', async () => {
|
|
22
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
23
|
-
expect(el.checked).toBe(false);
|
|
24
|
-
expect(getControl(el).getAttribute('aria-checked')).toBe('false');
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it('renders the slotted label content', async () => {
|
|
28
|
-
const el = await renderCheckbox('<dile-checkbox name="terms">Accept terms</dile-checkbox>');
|
|
29
|
-
const label = el.shadowRoot.querySelector('label.label');
|
|
30
|
-
expect(label).toBeTruthy();
|
|
31
|
-
expect(el.textContent.trim()).toBe('Accept terms');
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('does not render a label element when there is no slotted content', async () => {
|
|
35
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
36
|
-
expect(el.shadowRoot.querySelector('label.label')).toBeNull();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('renders a message when the message property is set', async () => {
|
|
40
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
41
|
-
el.message = 'You must accept';
|
|
42
|
-
el.errored = true;
|
|
43
|
-
await el.updateComplete;
|
|
44
|
-
|
|
45
|
-
const message = el.shadowRoot.querySelector('dile-input-message');
|
|
46
|
-
expect(message).toBeTruthy();
|
|
47
|
-
expect(message.getAttribute('message')).toBe('You must accept');
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
describe('Toggling', () => {
|
|
52
|
-
it('toggles checked state on click', async () => {
|
|
53
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
54
|
-
el.shadowRoot.querySelector('div').click();
|
|
55
|
-
await el.updateComplete;
|
|
56
|
-
|
|
57
|
-
expect(el.checked).toBe(true);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('toggles checked state on Space key press', async () => {
|
|
61
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
62
|
-
const control = getControl(el);
|
|
63
|
-
control.dispatchEvent(new KeyboardEvent('keydown', { key: ' ', bubbles: true, cancelable: true }));
|
|
64
|
-
await el.updateComplete;
|
|
65
|
-
|
|
66
|
-
expect(el.checked).toBe(true);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('does not toggle when disabled', async () => {
|
|
70
|
-
const el = await renderCheckbox('<dile-checkbox name="terms" disabled></dile-checkbox>');
|
|
71
|
-
el.shadowRoot.querySelector('div').click();
|
|
72
|
-
await el.updateComplete;
|
|
73
|
-
|
|
74
|
-
expect(el.checked).toBe(false);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('clears the checked state via clear()', async () => {
|
|
78
|
-
const el = await renderCheckbox('<dile-checkbox name="terms" checked></dile-checkbox>');
|
|
79
|
-
expect(el.checked).toBe(true);
|
|
80
|
-
|
|
81
|
-
el.clear();
|
|
82
|
-
await el.updateComplete;
|
|
83
|
-
|
|
84
|
-
expect(el.checked).toBe(false);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('mirrors checked through the value property', async () => {
|
|
88
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
89
|
-
el.value = true;
|
|
90
|
-
await el.updateComplete;
|
|
91
|
-
|
|
92
|
-
expect(el.checked).toBe(true);
|
|
93
|
-
expect(el.value).toBe(true);
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
describe('Events', () => {
|
|
98
|
-
it('dispatches dile-checkbox-changed with checked and name', async () => {
|
|
99
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
100
|
-
let detail = null;
|
|
101
|
-
el.addEventListener('dile-checkbox-changed', (e) => { detail = e.detail; });
|
|
102
|
-
|
|
103
|
-
el.shadowRoot.querySelector('div').click();
|
|
104
|
-
await el.updateComplete;
|
|
105
|
-
|
|
106
|
-
expect(detail).toEqual({ checked: true, name: 'terms' });
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('dispatches element-changed with name and value', async () => {
|
|
110
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
111
|
-
let detail = null;
|
|
112
|
-
el.addEventListener('element-changed', (e) => { detail = e.detail; });
|
|
113
|
-
|
|
114
|
-
el.shadowRoot.querySelector('div').click();
|
|
115
|
-
await el.updateComplete;
|
|
116
|
-
|
|
117
|
-
expect(detail).toEqual({ name: 'terms', value: true });
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('clears the error state on toggle when hideErrorOnInput is set', async () => {
|
|
121
|
-
const el = await renderCheckbox('<dile-checkbox name="terms" hideErrorOnInput></dile-checkbox>');
|
|
122
|
-
el.message = 'Required';
|
|
123
|
-
el.errored = true;
|
|
124
|
-
await el.updateComplete;
|
|
125
|
-
|
|
126
|
-
el.shadowRoot.querySelector('div').click();
|
|
127
|
-
await el.updateComplete;
|
|
128
|
-
|
|
129
|
-
expect(el.message).toBe('');
|
|
130
|
-
expect(el.errored).toBe(false);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
describe('Native form submission', () => {
|
|
135
|
-
it('participates in FormData when name is set as an attribute', async () => {
|
|
136
|
-
document.body.innerHTML = `
|
|
137
|
-
<form id="testForm">
|
|
138
|
-
<dile-checkbox name="terms" checked></dile-checkbox>
|
|
139
|
-
</form>
|
|
140
|
-
`;
|
|
141
|
-
const el = document.body.querySelector('dile-checkbox');
|
|
142
|
-
await el.updateComplete;
|
|
143
|
-
|
|
144
|
-
const data = new FormData(document.getElementById('testForm'));
|
|
145
|
-
expect(data.get('terms')).toBe('true');
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it('participates in FormData when name is set as a JS property', async () => {
|
|
149
|
-
document.body.innerHTML = `
|
|
150
|
-
<form id="testForm">
|
|
151
|
-
<dile-checkbox checked></dile-checkbox>
|
|
152
|
-
</form>
|
|
153
|
-
`;
|
|
154
|
-
const el = document.body.querySelector('dile-checkbox');
|
|
155
|
-
el.name = 'terms';
|
|
156
|
-
await el.updateComplete;
|
|
157
|
-
|
|
158
|
-
expect(el.getAttribute('name')).toBe('terms');
|
|
159
|
-
|
|
160
|
-
const data = new FormData(document.getElementById('testForm'));
|
|
161
|
-
expect(data.get('terms')).toBe('true');
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it('is excluded from FormData when unchecked', async () => {
|
|
165
|
-
document.body.innerHTML = `
|
|
166
|
-
<form id="testForm">
|
|
167
|
-
<dile-checkbox name="terms"></dile-checkbox>
|
|
168
|
-
</form>
|
|
169
|
-
`;
|
|
170
|
-
const el = document.body.querySelector('dile-checkbox');
|
|
171
|
-
await el.updateComplete;
|
|
172
|
-
|
|
173
|
-
const data = new FormData(document.getElementById('testForm'));
|
|
174
|
-
expect(data.get('terms')).toBeNull();
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
describe('Accessibility', () => {
|
|
179
|
-
it('exposes role="checkbox" on the interactive control', async () => {
|
|
180
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
181
|
-
expect(getControl(el)).toBeTruthy();
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it('keeps aria-checked in sync with the checked state', async () => {
|
|
185
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
186
|
-
const control = getControl(el);
|
|
187
|
-
expect(control.getAttribute('aria-checked')).toBe('false');
|
|
188
|
-
|
|
189
|
-
el.checked = true;
|
|
190
|
-
await el.updateComplete;
|
|
191
|
-
|
|
192
|
-
expect(control.getAttribute('aria-checked')).toBe('true');
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it('is keyboard focusable when enabled', async () => {
|
|
196
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
197
|
-
const control = getControl(el);
|
|
198
|
-
expect(control.getAttribute('tabindex')).toBe('0');
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
it('is removed from the tab order and marked aria-disabled when disabled', async () => {
|
|
202
|
-
const el = await renderCheckbox('<dile-checkbox name="terms" disabled></dile-checkbox>');
|
|
203
|
-
const control = getControl(el);
|
|
204
|
-
expect(control.getAttribute('tabindex')).toBe('-1');
|
|
205
|
-
expect(control.getAttribute('aria-disabled')).toBe('true');
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('links the control to the slotted label via aria-labelledby', async () => {
|
|
209
|
-
const el = await renderCheckbox('<dile-checkbox name="terms">Accept terms</dile-checkbox>');
|
|
210
|
-
const control = getControl(el);
|
|
211
|
-
const labelledbyId = control.getAttribute('aria-labelledby');
|
|
212
|
-
|
|
213
|
-
expect(labelledbyId).toBeTruthy();
|
|
214
|
-
expect(el.shadowRoot.getElementById(labelledbyId)).toBeTruthy();
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
it('does not set aria-labelledby when there is no slotted label', async () => {
|
|
218
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
219
|
-
expect(getControl(el).hasAttribute('aria-labelledby')).toBe(false);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('links the control to the message via aria-describedby when a message is set', async () => {
|
|
223
|
-
const el = await renderCheckbox('<dile-checkbox name="terms"></dile-checkbox>');
|
|
224
|
-
el.message = 'Required';
|
|
225
|
-
el.errored = true;
|
|
226
|
-
await el.updateComplete;
|
|
227
|
-
|
|
228
|
-
const control = getControl(el);
|
|
229
|
-
const describedbyId = control.getAttribute('aria-describedby');
|
|
230
|
-
|
|
231
|
-
expect(describedbyId).toBeTruthy();
|
|
232
|
-
expect(el.shadowRoot.getElementById(describedbyId)).toBeTruthy();
|
|
233
|
-
});
|
|
234
|
-
});
|
|
235
|
-
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
-
import './chip.js';
|
|
3
|
-
|
|
4
|
-
describe('dile-chip', () => {
|
|
5
|
-
afterEach(() => {
|
|
6
|
-
document.body.innerHTML = '';
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
async function renderChip(html) {
|
|
10
|
-
document.body.innerHTML = html;
|
|
11
|
-
const el = document.body.querySelector('dile-chip');
|
|
12
|
-
await el.updateComplete;
|
|
13
|
-
return el;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
it('renders the slotted content and a close icon', async () => {
|
|
17
|
-
const el = await renderChip('<dile-chip>Tag</dile-chip>');
|
|
18
|
-
expect(el.textContent.trim()).toBe('Tag');
|
|
19
|
-
expect(el.shadowRoot.querySelector('dile-icon')).toBeTruthy();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('dispatches dile-chip-icon-click with the name when the icon is clicked', async () => {
|
|
23
|
-
const el = await renderChip('<dile-chip name="tag1">Tag</dile-chip>');
|
|
24
|
-
let detail = null;
|
|
25
|
-
el.addEventListener('dile-chip-icon-click', (e) => { detail = e.detail; });
|
|
26
|
-
|
|
27
|
-
el.shadowRoot.querySelector('dile-icon').click();
|
|
28
|
-
|
|
29
|
-
expect(detail).toEqual({ name: 'tag1' });
|
|
30
|
-
});
|
|
31
|
-
});
|