@dile/ui 3.4.5 → 3.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/components/accordion/accordion-item.js +3 -1
  2. package/components/accordion/accordion.js +3 -1
  3. package/components/app-drawer/app-drawer.js +3 -1
  4. package/components/avatar/avatar.js +3 -1
  5. package/components/avatar/avatar.spec.js +25 -0
  6. package/components/box-selector/box-selector-item.js +3 -1
  7. package/components/box-selector/box-selector-item.spec.js +27 -0
  8. package/components/box-selector/box-selector.js +3 -1
  9. package/components/box-selector/box-selector.spec.js +27 -0
  10. package/components/breadcrumbs/breadcrumbs-item.js +3 -1
  11. package/components/breadcrumbs/breadcrumbs-item.spec.js +28 -0
  12. package/components/breadcrumbs/breadcrumbs.js +3 -1
  13. package/components/breadcrumbs/breadcrumbs.spec.js +33 -0
  14. package/components/button/button-icon.js +3 -1
  15. package/components/button/button.js +3 -1
  16. package/components/card/card-slide.js +3 -1
  17. package/components/card/card-slide.spec.js +30 -0
  18. package/components/card/card.js +3 -1
  19. package/components/card/card.spec.js +26 -0
  20. package/components/checkbox/checkbox.js +3 -1
  21. package/components/chip/chip.js +3 -1
  22. package/components/chip/chip.spec.js +31 -0
  23. package/components/color-picker/color-picker.js +3 -1
  24. package/components/confirm/confirm.js +3 -1
  25. package/components/confirm/confirm.spec.js +32 -0
  26. package/components/confirm-text/confirm-text.js +3 -1
  27. package/components/confirm-text/confirm-text.spec.js +29 -0
  28. package/components/copy-markdown-url/copy-markdown-url.spec.js +27 -0
  29. package/components/copy-markdown-url/index.js +3 -1
  30. package/components/copy-text/__screenshots__/copy-text.spec.js/dile-copy-text-dispatches-dile-text-copied-with-the-content-on-copy---1.png +0 -0
  31. package/components/copy-text/copy-text.spec.js +38 -0
  32. package/components/copy-text/index.js +3 -1
  33. package/components/drop-file/drop-file.js +3 -1
  34. package/components/drop-file/drop-file.spec.js +33 -0
  35. package/components/drop-file/file-preview.js +3 -1
  36. package/components/drop-file/file-preview.spec.js +35 -0
  37. package/components/floating-feedback/floating-feedback.spec.js +30 -0
  38. package/components/floating-feedback/index.js +3 -1
  39. package/components/floating-menu/floating-menu-item.js +3 -1
  40. package/components/floating-menu/floating-menu-item.spec.js +27 -0
  41. package/components/floating-menu/floating-menu.js +3 -1
  42. package/components/floating-menu/floating-menu.spec.js +31 -0
  43. package/components/form-separator/form-separator.js +3 -1
  44. package/components/form-separator/form-separator.spec.js +28 -0
  45. package/components/hamburger/hamburger.js +3 -1
  46. package/components/hamburger/hamburger.spec.js +28 -0
  47. package/components/icon/icon.js +3 -1
  48. package/components/icon/icon.spec.js +31 -0
  49. package/components/icon-switch/icon-switch-group.js +3 -1
  50. package/components/icon-switch/icon-switch-group.spec.js +46 -0
  51. package/components/icon-switch/icon-switch.js +3 -1
  52. package/components/icon-switch/icon-switch.spec.js +35 -0
  53. package/components/info-box/info-box.js +3 -1
  54. package/components/info-box/info-box.spec.js +38 -0
  55. package/components/inline-feedback/inline-feedback.js +3 -1
  56. package/components/inline-feedback/inline-feedback.spec.js +46 -0
  57. package/components/input/__screenshots__/input-number-mask.spec.js/dile-input-number-mask-masks-digit-keydowns-following-the-given-pattern-1.png +0 -0
  58. package/components/input/input-contact.js +3 -1
  59. package/components/input/input-contact.spec.js +32 -0
  60. package/components/input/input-integer.js +3 -1
  61. package/components/input/input-integer.spec.js +31 -0
  62. package/components/input/input-message.js +3 -1
  63. package/components/input/input-message.spec.js +27 -0
  64. package/components/input/input-money.js +3 -1
  65. package/components/input/input-money.spec.js +30 -0
  66. package/components/input/input-number-mask.js +3 -1
  67. package/components/input/input-number-mask.spec.js +32 -0
  68. package/components/input/input-percentage.js +3 -1
  69. package/components/input/input-percentage.spec.js +31 -0
  70. package/components/input/input-search.js +3 -1
  71. package/components/input/input-search.spec.js +39 -0
  72. package/components/input/input.js +3 -1
  73. package/components/input/input.spec.js +47 -0
  74. package/components/light-mode-switch/light-mode-switch.js +3 -1
  75. package/components/light-mode-switch/light-mode-switch.spec.js +34 -0
  76. package/components/menu-hamburger/menu-hamburger.js +3 -1
  77. package/components/menu-hamburger/menu-hamburger.spec.js +34 -0
  78. package/components/menu-overlay/menu-overlay.js +3 -1
  79. package/components/menu-overlay/menu-overlay.spec.js +44 -0
  80. package/components/message/message.js +3 -1
  81. package/components/message/message.spec.js +42 -0
  82. package/components/modal/__screenshots__/modal-help.spec.js/dile-modal-help-opens-the-inner-modal-on-open---1.png +0 -0
  83. package/components/modal/modal-help.js +3 -1
  84. package/components/modal/modal-help.spec.js +32 -0
  85. package/components/modal/modal.js +3 -1
  86. package/components/modal/modal.spec.js +46 -0
  87. package/components/nav/nav.js +3 -1
  88. package/components/nav/nav.spec.js +33 -0
  89. package/components/number-picker/number-picker-element.js +3 -1
  90. package/components/number-picker/number-picker-element.spec.js +30 -0
  91. package/components/number-picker/number-picker.js +3 -1
  92. package/components/number-picker/number-picker.spec.js +30 -0
  93. package/components/order-switch/order-switch.js +3 -1
  94. package/components/order-switch/order-switch.spec.js +31 -0
  95. package/components/otp-input/otp-input.js +3 -1
  96. package/components/otp-input/otp-input.spec.js +41 -0
  97. package/components/pages/pages.js +3 -1
  98. package/components/pages/pages.spec.js +44 -0
  99. package/components/password/password.js +3 -1
  100. package/components/password/password.spec.js +35 -0
  101. package/components/progress-bar/progress-bar.js +3 -1
  102. package/components/progress-bar/progress-bar.spec.js +28 -0
  103. package/components/radio-group/radio-group.js +3 -1
  104. package/components/radio-group/radio-group.spec.js +44 -0
  105. package/components/radio-group/radio.js +3 -1
  106. package/components/radio-group/radio.spec.js +32 -0
  107. package/components/range/range.js +3 -1
  108. package/components/range/range.spec.js +36 -0
  109. package/components/rating/rating.js +3 -1
  110. package/components/rating/rating.spec.js +34 -0
  111. package/components/rating/star.js +3 -1
  112. package/components/rating/star.spec.js +30 -0
  113. package/components/rating-scale-question/rating-scale-option.js +3 -1
  114. package/components/rating-scale-question/rating-scale-option.spec.js +32 -0
  115. package/components/rating-scale-question/rating-scale-question.js +3 -1
  116. package/components/rating-scale-question/rating-scale-question.spec.js +35 -0
  117. package/components/select/select-ajax.js +3 -1
  118. package/components/select/select-boolean.js +3 -1
  119. package/components/select/select.js +3 -1
  120. package/components/selector/selector-item.js +3 -1
  121. package/components/selector/selector-item.spec.js +40 -0
  122. package/components/selector/selector-overlay.js +3 -1
  123. package/components/selector/selector.js +3 -1
  124. package/components/selector/selector.spec.js +45 -0
  125. package/components/slide-menu/slide-menu.js +3 -1
  126. package/components/slide-menu/slide-menu.spec.js +38 -0
  127. package/components/slide-show/slide-show.js +3 -1
  128. package/components/slide-show/slide-show.spec.js +34 -0
  129. package/components/social-icon/social-icon.js +3 -1
  130. package/components/social-icon/social-icon.spec.js +26 -0
  131. package/components/spinner/spinner-bar.js +3 -1
  132. package/components/spinner/spinner-bar.spec.js +26 -0
  133. package/components/spinner/spinner-block.js +3 -1
  134. package/components/spinner/spinner-block.spec.js +21 -0
  135. package/components/spinner/spinner-horizontal.js +3 -1
  136. package/components/spinner/spinner-horizontal.spec.js +25 -0
  137. package/components/spinner/spinner-icon.js +3 -1
  138. package/components/spinner/spinner-icon.spec.js +25 -0
  139. package/components/spinner/spinner-modal.js +3 -1
  140. package/components/spinner/spinner-modal.spec.js +26 -0
  141. package/components/spinner/spinner.js +3 -1
  142. package/components/spinner/spinner.spec.js +26 -0
  143. package/components/switch/switch.js +3 -1
  144. package/components/switch/switch.spec.js +33 -0
  145. package/components/tabs/tab.js +3 -1
  146. package/components/tabs/tabs.js +3 -1
  147. package/components/tabs/tabs.spec.js +45 -0
  148. package/components/textarea/textarea.js +3 -1
  149. package/components/textarea/textarea.spec.js +39 -0
  150. package/components/time-picker/time-picker.js +3 -1
  151. package/components/time-picker/time-picker.spec.js +26 -0
  152. package/components/timer/timer.js +3 -1
  153. package/components/timer/timer.spec.js +31 -0
  154. package/components/toast/toast-item.js +3 -1
  155. package/components/toast/toast-persistent.js +3 -1
  156. package/components/toast/toast.js +3 -1
  157. package/components/tooltip/chip-tooltip.js +3 -1
  158. package/components/tooltip/chip-tooltip.spec.js +29 -0
  159. package/components/tooltip/tooltip.js +3 -1
  160. package/components/tooltip/tooltip.spec.js +32 -0
  161. package/components/web-visor/web-visor.js +3 -1
  162. package/components/web-visor/web-visor.spec.js +32 -0
  163. package/package.json +3 -3
@@ -0,0 +1,39 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './input-search.js';
3
+
4
+ describe('dile-input-search', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderInputSearch(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-input-search');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders a native text input and a search icon', async () => {
17
+ const el = await renderInputSearch('<dile-input-search placeholder="Search..."></dile-input-search>');
18
+ const input = el.shadowRoot.querySelector('input');
19
+ expect(input).toBeTruthy();
20
+ expect(input.placeholder).toBe('Search...');
21
+ expect(el.shadowRoot.querySelector('dile-icon')).toBeTruthy();
22
+ });
23
+
24
+ it('updates the value on input and dispatches dile-input-search after the delay', async () => {
25
+ const el = await renderInputSearch('<dile-input-search delay="10"></dile-input-search>');
26
+ const input = el.shadowRoot.querySelector('input');
27
+ let detail = null;
28
+ el.addEventListener('dile-input-search', (e) => { detail = e.detail; });
29
+
30
+ input.value = 'lit';
31
+ input.dispatchEvent(new Event('input', { bubbles: true }));
32
+ await el.updateComplete;
33
+
34
+ expect(el.value).toBe('lit');
35
+
36
+ await new Promise((resolve) => setTimeout(resolve, 30));
37
+ expect(detail).toEqual({ keyword: 'lit' });
38
+ });
39
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileInput } from './src/DileInput.js';
2
2
 
3
- window.customElements.define('dile-input', DileInput);
3
+ if (!customElements.get('dile-input')) {
4
+ window.customElements.define('dile-input', DileInput);
5
+ }
@@ -0,0 +1,47 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './input.js';
3
+
4
+ describe('dile-input', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderInput(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-input');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders a native text input with the given value', async () => {
17
+ const el = await renderInput('<dile-input name="first" value="hello"></dile-input>');
18
+ const input = el.shadowRoot.querySelector('input');
19
+ expect(input).toBeTruthy();
20
+ expect(input.value).toBe('hello');
21
+ });
22
+
23
+ it('renders the label when set', async () => {
24
+ const el = await renderInput('<dile-input label="First name"></dile-input>');
25
+ const label = el.shadowRoot.querySelector('label');
26
+ expect(label).toBeTruthy();
27
+ expect(label.textContent.trim()).toBe('First name');
28
+ });
29
+
30
+ it('updates the value property on user input', async () => {
31
+ const el = await renderInput('<dile-input name="first"></dile-input>');
32
+ const input = el.shadowRoot.querySelector('input');
33
+ input.value = 'typed';
34
+ input.dispatchEvent(new Event('input', { bubbles: true }));
35
+ await el.updateComplete;
36
+
37
+ expect(el.value).toBe('typed');
38
+ });
39
+
40
+ it('renders a message when the message property is set', async () => {
41
+ const el = await renderInput('<dile-input></dile-input>');
42
+ el.message = 'Required field';
43
+ await el.updateComplete;
44
+
45
+ expect(el.shadowRoot.querySelector('.message span').textContent.trim()).toBe('Required field');
46
+ });
47
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileLightModeSwitch } from "./src/DileLightModeSwitch.js";
2
2
 
3
- window.customElements.define("dile-light-mode-switch", DileLightModeSwitch);
3
+ if (!customElements.get("dile-light-mode-switch")) {
4
+ window.customElements.define("dile-light-mode-switch", DileLightModeSwitch);
5
+ }
@@ -0,0 +1,34 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './light-mode-switch.js';
3
+
4
+ describe('dile-light-mode-switch', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ localStorage.removeItem('dile_light_mode_switch_state');
8
+ document.documentElement.classList.remove('dark-theme');
9
+ });
10
+
11
+ async function renderLightModeSwitch(html) {
12
+ document.body.innerHTML = html;
13
+ const el = document.body.querySelector('dile-light-mode-switch');
14
+ await el.updateComplete;
15
+ return el;
16
+ }
17
+
18
+ it('renders an icon and a switch', async () => {
19
+ const el = await renderLightModeSwitch('<dile-light-mode-switch></dile-light-mode-switch>');
20
+ expect(el.shadowRoot.querySelector('dile-icon')).toBeTruthy();
21
+ expect(el.shadowRoot.querySelector('dile-switch')).toBeTruthy();
22
+ });
23
+
24
+ it('toggles darkMode and reflects the attribute', async () => {
25
+ const el = await renderLightModeSwitch('<dile-light-mode-switch></dile-light-mode-switch>');
26
+ const initial = el.darkMode;
27
+
28
+ el.toggle();
29
+ await el.updateComplete;
30
+
31
+ expect(el.darkMode).toBe(!initial);
32
+ expect(el.hasAttribute('darkMode')).toBe(!initial);
33
+ });
34
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileMenuHamburger } from './src/DileMenuHamburger.js';
2
2
 
3
- window.customElements.define('dile-menu-hamburger', DileMenuHamburger);
3
+ if (!customElements.get('dile-menu-hamburger')) {
4
+ window.customElements.define('dile-menu-hamburger', DileMenuHamburger);
5
+ }
@@ -0,0 +1,34 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './menu-hamburger.js';
3
+
4
+ describe('dile-menu-hamburger', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderMenuHamburger(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-menu-hamburger');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders a hamburger and a drawer, closed by default', async () => {
17
+ const el = await renderMenuHamburger('<dile-menu-hamburger><nav slot="menu">Links</nav></dile-menu-hamburger>');
18
+ expect(el.opened).toBe(false);
19
+ expect(el.shadowRoot.querySelector('dile-hamburger')).toBeTruthy();
20
+ expect(el.shadowRoot.querySelector('dile-app-drawer')).toBeTruthy();
21
+ });
22
+
23
+ it('opens on toggle and dispatches dile-menu-hamburger-opened', async () => {
24
+ const el = await renderMenuHamburger('<dile-menu-hamburger><nav slot="menu">Links</nav></dile-menu-hamburger>');
25
+ let opened = false;
26
+ el.addEventListener('dile-menu-hamburger-opened', () => { opened = true; });
27
+
28
+ el.toggle();
29
+ await el.updateComplete;
30
+
31
+ expect(el.opened).toBe(true);
32
+ expect(opened).toBe(true);
33
+ });
34
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileMenuOverlay } from './src/DileMenuOverlay.js';
2
2
 
3
- customElements.define("dile-menu-overlay", DileMenuOverlay);
3
+ if (!customElements.get("dile-menu-overlay")) {
4
+ customElements.define("dile-menu-overlay", DileMenuOverlay);
5
+ }
@@ -0,0 +1,44 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './menu-overlay.js';
3
+
4
+ describe('dile-menu-overlay', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderMenuOverlay(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-menu-overlay');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ function wait(ms) {
17
+ return new Promise((resolve) => setTimeout(resolve, ms));
18
+ }
19
+
20
+ it('renders the trigger and content slots', async () => {
21
+ const el = await renderMenuOverlay(`
22
+ <dile-menu-overlay>
23
+ <button slot="trigger">Open</button>
24
+ <div slot="content">Menu content</div>
25
+ </dile-menu-overlay>
26
+ `);
27
+ expect(el.shadowRoot.getElementById('trigger')).toBeTruthy();
28
+ expect(el.shadowRoot.getElementById('overlay')).toBeTruthy();
29
+ });
30
+
31
+ it('opens the overlay when the trigger is clicked', async () => {
32
+ const el = await renderMenuOverlay(`
33
+ <dile-menu-overlay>
34
+ <button slot="trigger">Open</button>
35
+ <div slot="content">Menu content</div>
36
+ </dile-menu-overlay>
37
+ `);
38
+
39
+ el.shadowRoot.getElementById('trigger').click();
40
+ await wait(100);
41
+
42
+ expect(el.shadowRoot.getElementById('overlay').classList.contains('opened')).toBe(true);
43
+ });
44
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileMessage } from './src/DileMessage.js';
2
2
 
3
- window.customElements.define('dile-message', DileMessage);
3
+ if (!customElements.get('dile-message')) {
4
+ window.customElements.define('dile-message', DileMessage);
5
+ }
@@ -0,0 +1,42 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './message.js';
3
+
4
+ describe('dile-message', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderMessage(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-message');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders closed by default with a close icon', async () => {
17
+ const el = await renderMessage('<dile-message></dile-message>');
18
+ expect(el.opened).toBe(false);
19
+ expect(el.shadowRoot.querySelector('dile-icon.icon')).toBeTruthy();
20
+ });
21
+
22
+ it('opens and shows the message text via openMessage()', async () => {
23
+ const el = await renderMessage('<dile-message></dile-message>');
24
+ el.openMessage('Saved successfully');
25
+ await el.updateComplete;
26
+
27
+ expect(el.opened).toBe(true);
28
+ expect(el.shadowRoot.querySelector('.content').textContent.trim()).toBe('Saved successfully');
29
+ });
30
+
31
+ it('dispatches dile-message-closed-by-user when the close icon is clicked', async () => {
32
+ const el = await renderMessage('<dile-message opened></dile-message>');
33
+ let closed = false;
34
+ el.addEventListener('dile-message-closed-by-user', () => { closed = true; });
35
+
36
+ el.shadowRoot.querySelector('dile-icon.icon').click();
37
+ await el.updateComplete;
38
+
39
+ expect(closed).toBe(true);
40
+ expect(el.opened).toBe(false);
41
+ });
42
+ });
@@ -1,4 +1,6 @@
1
1
  import './modal.js';
2
2
  import { DileModalHelp } from './src/DileModalHelp.js';
3
3
 
4
- customElements.define("dile-modal-help", DileModalHelp);
4
+ if (!customElements.get("dile-modal-help")) {
5
+ customElements.define("dile-modal-help", DileModalHelp);
6
+ }
@@ -0,0 +1,32 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './modal-help.js';
3
+
4
+ describe('dile-modal-help', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderModalHelp(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-modal-help');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders a trigger button with the default label and a closed inner modal', async () => {
17
+ const el = await renderModalHelp('<dile-modal-help>Help content</dile-modal-help>');
18
+ const button = el.shadowRoot.querySelector('dile-button-icon');
19
+ expect(button).toBeTruthy();
20
+ expect(button.textContent.trim()).toBe('Help');
21
+ expect(el.elmodal.opened).toBe(false);
22
+ });
23
+
24
+ it('opens the inner modal on open()', async () => {
25
+ const el = await renderModalHelp('<dile-modal-help title="Info">Help content</dile-modal-help>');
26
+ el.open();
27
+ await el.elmodal.updateComplete;
28
+
29
+ expect(el.elmodal.opened).toBe(true);
30
+ expect(el.shadowRoot.querySelector('h1').textContent.trim()).toBe('Info');
31
+ });
32
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileModal } from './src/DileModal.js';
2
2
 
3
- customElements.define("dile-modal", DileModal);
3
+ if (!customElements.get("dile-modal")) {
4
+ customElements.define("dile-modal", DileModal);
5
+ }
@@ -0,0 +1,46 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './modal.js';
3
+
4
+ describe('dile-modal', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderModal(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-modal');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders closed by default with slotted content', async () => {
17
+ const el = await renderModal('<dile-modal>Modal content</dile-modal>');
18
+ expect(el.opened).toBe(false);
19
+ expect(el.textContent.trim()).toBe('Modal content');
20
+ expect(el.shadowRoot.querySelector('section').classList.contains('opaque')).toBe(false);
21
+ });
22
+
23
+ it('opens the modal via open()', async () => {
24
+ const el = await renderModal('<dile-modal>Modal content</dile-modal>');
25
+ el.open();
26
+ await el.updateComplete;
27
+
28
+ expect(el.opened).toBe(true);
29
+ expect(el.shadowRoot.querySelector('section').classList.contains('opened')).toBe(true);
30
+ });
31
+
32
+ it('closes and dispatches dile-modal-closed via close()', async () => {
33
+ const el = await renderModal('<dile-modal>Modal content</dile-modal>');
34
+ el.open();
35
+ await el.updateComplete;
36
+
37
+ let closed = false;
38
+ el.addEventListener('dile-modal-closed', () => { closed = true; });
39
+
40
+ el.close();
41
+ await el.updateComplete;
42
+
43
+ expect(el.opened).toBe(false);
44
+ expect(closed).toBe(true);
45
+ });
46
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileNav } from './src/DileNav.js';
2
2
 
3
- window.customElements.define('dile-nav', DileNav);
3
+ if (!customElements.get('dile-nav')) {
4
+ window.customElements.define('dile-nav', DileNav);
5
+ }
@@ -0,0 +1,33 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './nav.js';
3
+
4
+ describe('dile-nav', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderNav(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-nav');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders the menu, title and actions slots', async () => {
17
+ const el = await renderNav(`
18
+ <dile-nav>
19
+ <span slot="title">My App</span>
20
+ </dile-nav>
21
+ `);
22
+
23
+ expect(el.shadowRoot.querySelector('slot[name="menu"]')).toBeTruthy();
24
+ expect(el.shadowRoot.querySelector('slot[name="title"]')).toBeTruthy();
25
+ expect(el.shadowRoot.querySelector('slot[name="actions"]')).toBeTruthy();
26
+ expect(el.menu).toBe('left');
27
+ });
28
+
29
+ it('reflects the menu property as an attribute', async () => {
30
+ const el = await renderNav('<dile-nav menu="right"></dile-nav>');
31
+ expect(el.getAttribute('menu')).toBe('right');
32
+ });
33
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileNumberPickerElement } from './src/DileNumberPickerElement.js';
2
2
 
3
- window.customElements.define('dile-number-picker-element', DileNumberPickerElement);
3
+ if (!customElements.get('dile-number-picker-element')) {
4
+ window.customElements.define('dile-number-picker-element', DileNumberPickerElement);
5
+ }
@@ -0,0 +1,30 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './number-picker-element.js';
3
+
4
+ describe('dile-number-picker-element', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderNumberPickerElement(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-number-picker-element');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders an input and increment/decrement icons', async () => {
17
+ const el = await renderNumberPickerElement('<dile-number-picker-element value="3"></dile-number-picker-element>');
18
+
19
+ expect(el.shadowRoot.querySelector('input')).toBeTruthy();
20
+ expect(el.shadowRoot.querySelectorAll('dile-icon').length).toBe(2);
21
+ });
22
+
23
+ it('increments the value when calling increment()', async () => {
24
+ const el = await renderNumberPickerElement('<dile-number-picker-element value="3" step="1"></dile-number-picker-element>');
25
+ el.increment();
26
+ await el.updateComplete;
27
+
28
+ expect(el.value).toBe('4');
29
+ });
30
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileNumberPicker } from './src/DileNumberPicker.js';
2
2
 
3
- customElements.define('dile-number-picker', DileNumberPicker);
3
+ if (!customElements.get('dile-number-picker')) {
4
+ customElements.define('dile-number-picker', DileNumberPicker);
5
+ }
@@ -0,0 +1,30 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './number-picker.js';
3
+
4
+ describe('dile-number-picker', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderNumberPicker(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-number-picker');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders an inner dile-number-picker-element with the given value', async () => {
17
+ const el = await renderNumberPicker('<dile-number-picker name="qty" value="5"></dile-number-picker>');
18
+
19
+ const inner = el.shadowRoot.querySelector('dile-number-picker-element');
20
+ expect(inner).toBeTruthy();
21
+ expect(el.value).toBe('5');
22
+ });
23
+
24
+ it('renders the label when set', async () => {
25
+ const el = await renderNumberPicker('<dile-number-picker label="Quantity"></dile-number-picker>');
26
+ const label = el.shadowRoot.querySelector('label');
27
+ expect(label).toBeTruthy();
28
+ expect(label.textContent.trim()).toBe('Quantity');
29
+ });
30
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileOrderSwitch } from "./src/DileOrderSwitch.js";
2
2
 
3
- window.customElements.define("dile-order-switch", DileOrderSwitch);
3
+ if (!customElements.get("dile-order-switch")) {
4
+ window.customElements.define("dile-order-switch", DileOrderSwitch);
5
+ }
@@ -0,0 +1,31 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './order-switch.js';
3
+
4
+ describe('dile-order-switch', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderOrderSwitch(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-order-switch');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('defaults to ascending order', async () => {
17
+ const el = await renderOrderSwitch('<dile-order-switch label="Name"></dile-order-switch>');
18
+
19
+ expect(el.value).toBe('asc');
20
+ expect(el.shadowRoot.querySelector('dile-icon')).toBeTruthy();
21
+ expect(el.shadowRoot.querySelector('span').textContent.trim()).toBe('Name');
22
+ });
23
+
24
+ it('toggles between asc and desc', async () => {
25
+ const el = await renderOrderSwitch('<dile-order-switch></dile-order-switch>');
26
+ el.toggle();
27
+ await el.updateComplete;
28
+
29
+ expect(el.value).toBe('desc');
30
+ });
31
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileOtpInput } from './src/DileOtpInput.js';
2
2
 
3
- window.customElements.define('dile-otp-input', DileOtpInput);
3
+ if (!customElements.get('dile-otp-input')) {
4
+ window.customElements.define('dile-otp-input', DileOtpInput);
5
+ }
@@ -0,0 +1,41 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './otp-input.js';
3
+
4
+ describe('dile-otp-input', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderOtpInput(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-otp-input');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders one input box per digit', async () => {
17
+ const el = await renderOtpInput('<dile-otp-input name="code" length="4"></dile-otp-input>');
18
+
19
+ expect(el.shadowRoot.querySelectorAll('input').length).toBe(4);
20
+ });
21
+
22
+ it('renders the slotted-in value across the boxes', async () => {
23
+ const el = await renderOtpInput('<dile-otp-input length="4" value="12"></dile-otp-input>');
24
+ const boxes = el.shadowRoot.querySelectorAll('input');
25
+
26
+ expect(boxes[0].value).toBe('1');
27
+ expect(boxes[1].value).toBe('2');
28
+ expect(boxes[2].value).toBe('');
29
+ });
30
+
31
+ it('dispatches dile-otp-input-completed when the last box is filled', async () => {
32
+ const el = await renderOtpInput('<dile-otp-input name="code" length="2"></dile-otp-input>');
33
+ let detail = null;
34
+ el.addEventListener('dile-otp-input-completed', (e) => { detail = e.detail; });
35
+
36
+ el.value = '12';
37
+ await el.updateComplete;
38
+
39
+ expect(detail).toEqual({ name: 'code', value: '12' });
40
+ });
41
+ });
@@ -1,3 +1,5 @@
1
1
  import { DilePages } from "./src/DilePages.js";
2
2
 
3
- window.customElements.define("dile-pages", DilePages);
3
+ if (!customElements.get("dile-pages")) {
4
+ window.customElements.define("dile-pages", DilePages);
5
+ }
@@ -0,0 +1,44 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './pages.js';
3
+
4
+ describe('dile-pages', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderPages(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-pages');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('shows only the selected page', async () => {
17
+ const el = await renderPages(`
18
+ <dile-pages selected="1">
19
+ <div>Page 0</div>
20
+ <div>Page 1</div>
21
+ </dile-pages>
22
+ `);
23
+
24
+ const [page0, page1] = el.children;
25
+ expect(page0.style.display).toBe('none');
26
+ expect(page1.style.display).toBe('block');
27
+ });
28
+
29
+ it('hides the previous page and shows the new one when selected changes', async () => {
30
+ const el = await renderPages(`
31
+ <dile-pages selected="0">
32
+ <div>Page 0</div>
33
+ <div>Page 1</div>
34
+ </dile-pages>
35
+ `);
36
+
37
+ el.selected = 1;
38
+ await el.updateComplete;
39
+
40
+ const [page0, page1] = el.children;
41
+ expect(page0.style.display).toBe('none');
42
+ expect(page1.style.display).toBe('block');
43
+ });
44
+ });
@@ -1,3 +1,5 @@
1
1
  import { DilePassword } from './src/DilePassword.js';
2
2
 
3
- window.customElements.define('dile-password', DilePassword);
3
+ if (!customElements.get('dile-password')) {
4
+ window.customElements.define('dile-password', DilePassword);
5
+ }