@crowdstrike/glide-core 0.5.1 → 0.6.0

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 (242) hide show
  1. package/README.md +11 -1
  2. package/dist/accordion.js +1 -1
  3. package/dist/accordion.styles.js +5 -4
  4. package/dist/accordion.test.basics.js +109 -0
  5. package/dist/accordion.test.events.js +39 -0
  6. package/dist/button-group.button.js +1 -1
  7. package/dist/button-group.button.styles.js +6 -5
  8. package/dist/button-group.button.test.basics.js +169 -0
  9. package/dist/button-group.button.test.events.js +73 -0
  10. package/dist/button-group.js +1 -1
  11. package/dist/button-group.styles.js +3 -3
  12. package/dist/button-group.test.basics.js +268 -0
  13. package/dist/button-group.test.events.js +291 -0
  14. package/dist/button.d.ts +3 -2
  15. package/dist/button.js +1 -1
  16. package/dist/button.styles.js +5 -5
  17. package/dist/button.test.basics.js +202 -0
  18. package/dist/button.test.events.js +25 -0
  19. package/dist/button.test.form.js +49 -0
  20. package/dist/checkbox-group.js +1 -1
  21. package/dist/checkbox-group.styles.js +2 -2
  22. package/dist/checkbox-group.test.basics.js +119 -0
  23. package/dist/checkbox-group.test.events.js +110 -0
  24. package/dist/checkbox-group.test.focus.js +45 -0
  25. package/dist/checkbox-group.test.form.js +130 -0
  26. package/dist/checkbox-group.test.validity.js +75 -0
  27. package/dist/checkbox.js +1 -1
  28. package/dist/checkbox.styles.js +7 -4
  29. package/dist/checkbox.test.basics.js +89 -0
  30. package/dist/checkbox.test.events.js +87 -0
  31. package/dist/checkbox.test.focus.js +38 -0
  32. package/dist/checkbox.test.form.js +115 -0
  33. package/dist/checkbox.test.states.js +62 -0
  34. package/dist/checkbox.test.validity.js +51 -0
  35. package/dist/drawer.d.ts +2 -2
  36. package/dist/drawer.js +1 -15
  37. package/dist/drawer.styles.js +14 -4
  38. package/dist/drawer.test.accessibility.js +22 -0
  39. package/dist/drawer.test.basics.js +43 -0
  40. package/dist/drawer.test.closing.js +37 -0
  41. package/dist/drawer.test.events.js +52 -0
  42. package/dist/drawer.test.floating-components.d.ts +1 -0
  43. package/dist/drawer.test.floating-components.js +51 -0
  44. package/dist/drawer.test.methods.js +34 -0
  45. package/dist/dropdown.d.ts +4 -2
  46. package/dist/dropdown.js +1 -1
  47. package/dist/dropdown.option.d.ts +0 -2
  48. package/dist/dropdown.option.js +1 -1
  49. package/dist/dropdown.option.styles.js +2 -2
  50. package/dist/dropdown.option.test.basics.js +59 -0
  51. package/dist/dropdown.option.test.basics.multiple.js +26 -0
  52. package/dist/dropdown.option.test.basics.single.js +20 -0
  53. package/dist/dropdown.option.test.events.js +27 -0
  54. package/dist/dropdown.option.test.focus.js +11 -0
  55. package/dist/dropdown.option.test.interactions.multiple.js +82 -0
  56. package/dist/dropdown.option.test.interactions.single.js +22 -0
  57. package/dist/dropdown.styles.js +26 -6
  58. package/dist/dropdown.test.basics.filterable.js +84 -0
  59. package/dist/dropdown.test.basics.js +233 -0
  60. package/dist/dropdown.test.basics.multiple.js +270 -0
  61. package/dist/dropdown.test.basics.single.js +79 -0
  62. package/dist/dropdown.test.events.js +268 -0
  63. package/dist/dropdown.test.events.multiple.js +130 -0
  64. package/dist/dropdown.test.focus.d.ts +1 -0
  65. package/dist/dropdown.test.focus.filterable.js +154 -0
  66. package/dist/dropdown.test.focus.js +28 -0
  67. package/dist/dropdown.test.focus.multiple.js +181 -0
  68. package/dist/dropdown.test.focus.single.js +53 -0
  69. package/dist/dropdown.test.form.js +140 -0
  70. package/dist/dropdown.test.form.multiple.js +149 -0
  71. package/dist/dropdown.test.form.single.js +128 -0
  72. package/dist/dropdown.test.interactions.filterable.js +449 -0
  73. package/dist/dropdown.test.interactions.js +446 -0
  74. package/dist/dropdown.test.interactions.multiple.js +908 -0
  75. package/dist/dropdown.test.interactions.single.js +466 -0
  76. package/dist/dropdown.test.validity.js +46 -0
  77. package/dist/icon-button.d.ts +3 -2
  78. package/dist/icon-button.js +1 -1
  79. package/dist/icon-button.styles.js +12 -12
  80. package/dist/icon-button.test.basics.js +110 -0
  81. package/dist/icons/checked.js +1 -1
  82. package/dist/icons/magnifying-glass.js +1 -1
  83. package/dist/input.js +1 -1
  84. package/dist/input.styles.js +4 -3
  85. package/dist/input.test.basics.js +169 -0
  86. package/dist/input.test.events.js +97 -0
  87. package/dist/input.test.focus.js +54 -0
  88. package/dist/input.test.form.js +56 -0
  89. package/dist/input.test.validity.js +50 -0
  90. package/dist/label.js +1 -1
  91. package/dist/label.styles.js +13 -15
  92. package/dist/label.test.basics.js +129 -0
  93. package/dist/library/expect-argument-error.js +1 -1
  94. package/dist/library/localize.d.ts +17 -0
  95. package/dist/library/localize.js +1 -0
  96. package/dist/library/ow.js +1 -1
  97. package/dist/library/ow.test.js +55 -0
  98. package/dist/library/set-containing-block.d.ts +15 -0
  99. package/dist/library/set-containing-block.js +1 -0
  100. package/dist/menu.button.d.ts +1 -2
  101. package/dist/menu.button.js +1 -1
  102. package/dist/menu.button.styles.js +3 -3
  103. package/dist/menu.button.test.basics.js +42 -0
  104. package/dist/menu.d.ts +7 -2
  105. package/dist/menu.js +1 -1
  106. package/dist/menu.link.d.ts +1 -2
  107. package/dist/menu.link.js +1 -1
  108. package/dist/menu.link.styles.js +3 -3
  109. package/dist/menu.link.test.basics.js +46 -0
  110. package/dist/menu.options.d.ts +22 -0
  111. package/dist/menu.options.js +1 -0
  112. package/dist/menu.options.styles.d.ts +2 -0
  113. package/dist/menu.options.styles.js +33 -0
  114. package/dist/menu.options.test.basics.d.ts +2 -0
  115. package/dist/menu.options.test.basics.js +43 -0
  116. package/dist/menu.stories.d.ts +1 -0
  117. package/dist/menu.styles.js +7 -31
  118. package/dist/menu.test.basics.d.ts +1 -0
  119. package/dist/menu.test.basics.js +183 -0
  120. package/dist/menu.test.focus.d.ts +0 -1
  121. package/dist/menu.test.focus.js +84 -0
  122. package/dist/menu.test.interactions.d.ts +1 -1
  123. package/dist/menu.test.interactions.js +664 -0
  124. package/dist/modal.icon-button.js +1 -1
  125. package/dist/modal.icon-button.styles.js +2 -2
  126. package/dist/modal.icon-button.test.basics.js +45 -0
  127. package/dist/modal.js +1 -15
  128. package/dist/modal.styles.js +4 -7
  129. package/dist/modal.tertiary-icon.d.ts +1 -0
  130. package/dist/modal.tertiary-icon.js +1 -1
  131. package/dist/modal.tertiary-icon.test.basics.js +59 -0
  132. package/dist/modal.test.accessibility.js +48 -0
  133. package/dist/modal.test.basics.js +203 -0
  134. package/dist/modal.test.close.js +38 -0
  135. package/dist/modal.test.events.js +110 -0
  136. package/dist/modal.test.floating-components.d.ts +1 -0
  137. package/dist/modal.test.floating-components.js +62 -0
  138. package/dist/modal.test.lock-scroll.js +76 -0
  139. package/dist/modal.test.methods.js +23 -0
  140. package/dist/modal.test.scrollbars.js +19 -0
  141. package/dist/radio-group.js +1 -1
  142. package/dist/radio-group.styles.js +20 -24
  143. package/dist/radio-group.test.basics.js +323 -0
  144. package/dist/radio-group.test.events.js +277 -0
  145. package/dist/radio-group.test.focus.js +75 -0
  146. package/dist/radio-group.test.form.js +104 -0
  147. package/dist/radio-group.test.validity.js +228 -0
  148. package/dist/radio.js +1 -1
  149. package/dist/radio.styles.js +14 -31
  150. package/dist/split-button.d.ts +27 -0
  151. package/dist/split-button.js +1 -0
  152. package/dist/split-button.stories.d.ts +17 -0
  153. package/dist/split-button.styles.d.ts +2 -0
  154. package/dist/split-button.styles.js +102 -0
  155. package/dist/split-button.test.basics.d.ts +1 -0
  156. package/dist/split-button.test.basics.js +99 -0
  157. package/dist/split-container.d.ts +31 -0
  158. package/dist/split-container.js +1 -0
  159. package/dist/split-container.styles.d.ts +2 -0
  160. package/dist/split-container.styles.js +134 -0
  161. package/dist/split-container.test.basics.d.ts +3 -0
  162. package/dist/split-container.test.basics.js +440 -0
  163. package/dist/split-container.test.interactions.d.ts +1 -0
  164. package/dist/split-container.test.interactions.js +20 -0
  165. package/dist/split-link.d.ts +25 -0
  166. package/dist/split-link.js +1 -0
  167. package/dist/split-link.test.basics.d.ts +1 -0
  168. package/dist/split-link.test.basics.js +92 -0
  169. package/dist/split-link.test.interactions.d.ts +1 -0
  170. package/dist/split-link.test.interactions.js +19 -0
  171. package/dist/status-indicator.js +1 -1
  172. package/dist/status-indicator.styles.js +2 -2
  173. package/dist/status-indicator.test.basics.js +102 -0
  174. package/dist/styles/focus-outline.js +1 -4
  175. package/dist/styles/variables.css +1 -1
  176. package/dist/styles/visually-hidden.js +1 -11
  177. package/dist/tab.group.js +1 -1
  178. package/dist/tab.group.styles.js +2 -2
  179. package/dist/tab.group.test.basics.js +185 -0
  180. package/dist/tab.js +1 -1
  181. package/dist/tab.panel.js +1 -1
  182. package/dist/tab.panel.styles.js +3 -3
  183. package/dist/tab.styles.js +80 -55
  184. package/dist/tab.test.basics.js +71 -0
  185. package/dist/tag.js +1 -1
  186. package/dist/tag.styles.js +4 -3
  187. package/dist/tag.test.basics.js +118 -0
  188. package/dist/tag.test.events.js +16 -0
  189. package/dist/tag.test.focus.js +11 -0
  190. package/dist/tag.test.translations.d.ts +1 -0
  191. package/dist/tag.test.translations.js +25 -0
  192. package/dist/textarea.js +2 -2
  193. package/dist/textarea.styles.js +5 -4
  194. package/dist/textarea.test.basics.js +140 -0
  195. package/dist/textarea.test.events.js +204 -0
  196. package/dist/textarea.test.form.js +70 -0
  197. package/dist/textarea.test.validity.js +83 -0
  198. package/dist/toasts.js +1 -1
  199. package/dist/toasts.styles.js +2 -2
  200. package/dist/toasts.test.basics.js +94 -0
  201. package/dist/toasts.toast.js +1 -1
  202. package/dist/toasts.toast.styles.js +5 -2
  203. package/dist/toasts.toast.test.basics.js +139 -0
  204. package/dist/toggle.js +1 -1
  205. package/dist/toggle.styles.js +3 -3
  206. package/dist/toggle.test.basics.js +68 -0
  207. package/dist/toggle.test.events.js +29 -0
  208. package/dist/toggle.test.focus.js +9 -0
  209. package/dist/toggle.test.states.js +43 -0
  210. package/dist/tooltip.d.ts +2 -0
  211. package/dist/tooltip.js +1 -1
  212. package/dist/tooltip.styles.js +5 -3
  213. package/dist/tooltip.test.basics.js +64 -0
  214. package/dist/tooltip.test.interactions.js +78 -0
  215. package/dist/translations/en.d.ts +3 -0
  216. package/dist/translations/en.js +1 -0
  217. package/dist/translations/fr.d.ts +3 -0
  218. package/dist/translations/fr.js +1 -0
  219. package/dist/translations/ja.d.ts +3 -0
  220. package/dist/translations/ja.js +1 -0
  221. package/dist/tree.d.ts +1 -0
  222. package/dist/tree.item.d.ts +3 -1
  223. package/dist/tree.item.icon-button.js +1 -1
  224. package/dist/tree.item.icon-button.styles.js +2 -2
  225. package/dist/tree.item.icon-button.test.basics.js +13 -0
  226. package/dist/tree.item.js +1 -1
  227. package/dist/tree.item.menu.d.ts +2 -0
  228. package/dist/tree.item.menu.js +1 -1
  229. package/dist/tree.item.menu.styles.js +2 -2
  230. package/dist/tree.item.menu.test.basics.js +33 -0
  231. package/dist/tree.item.styles.js +23 -8
  232. package/dist/tree.item.test.basics.js +102 -0
  233. package/dist/tree.js +1 -1
  234. package/dist/tree.stories.d.ts +1 -0
  235. package/dist/tree.styles.js +2 -2
  236. package/dist/tree.test.aria.js +86 -0
  237. package/dist/tree.test.basics.js +123 -0
  238. package/dist/tree.test.events.js +19 -0
  239. package/dist/tree.test.focus.js +261 -0
  240. package/package.json +25 -18
  241. /package/dist/{dropdown.option.test.focus.multiple.d.ts → dropdown.option.test.focus.d.ts} +0 -0
  242. /package/dist/{dropdown.option.test.focus.single.d.ts → dropdown.test.events.multiple.d.ts} +0 -0
@@ -0,0 +1,130 @@
1
+ import * as sinon from 'sinon';
2
+ import { aTimeout, expect, fixture, html } from '@open-wc/testing';
3
+ import GlideCoreDropdown from './dropdown.js';
4
+ import GlideCoreDropdownOption from './dropdown.option.js';
5
+ GlideCoreDropdown.shadowRootOptions.mode = 'open';
6
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
7
+ it('dispatches one "change" event when Select All is clicked', async () => {
8
+ const component = await fixture(html `<glide-core-dropdown
9
+ label="Label"
10
+ placeholder="Placeholder"
11
+ open
12
+ multiple
13
+ select-all
14
+ >
15
+ <glide-core-dropdown-option
16
+ label="One"
17
+ value="one"
18
+ ></glide-core-dropdown-option>
19
+
20
+ <glide-core-dropdown-option
21
+ label="Two"
22
+ value="two"
23
+ selected
24
+ ></glide-core-dropdown-option>
25
+ </glide-core-dropdown>`);
26
+ const spy = sinon.spy();
27
+ component.addEventListener('change', spy);
28
+ setTimeout(() => {
29
+ component.shadowRoot
30
+ ?.querySelector('[data-test="select-all"]')
31
+ ?.click();
32
+ });
33
+ await aTimeout(0);
34
+ expect(spy.calledOnce).to.be.true;
35
+ });
36
+ it('dispatches one "input" event when Select All is clicked', async () => {
37
+ const component = await fixture(html `<glide-core-dropdown
38
+ label="Label"
39
+ placeholder="Placeholder"
40
+ open
41
+ multiple
42
+ select-all
43
+ >
44
+ <glide-core-dropdown-option
45
+ label="One"
46
+ value="one"
47
+ ></glide-core-dropdown-option>
48
+
49
+ <glide-core-dropdown-option
50
+ label="Two"
51
+ value="two"
52
+ selected
53
+ ></glide-core-dropdown-option>
54
+ </glide-core-dropdown>`);
55
+ const spy = sinon.spy();
56
+ component.addEventListener('input', spy);
57
+ setTimeout(() => {
58
+ component.shadowRoot
59
+ ?.querySelector('[data-test="select-all"]')
60
+ ?.click();
61
+ });
62
+ await aTimeout(0);
63
+ expect(spy.calledOnce).to.be.true;
64
+ });
65
+ it('dispatches a "change" event when an option is selected after Select All is clicked', async () => {
66
+ const component = await fixture(html `<glide-core-dropdown
67
+ label="Label"
68
+ placeholder="Placeholder"
69
+ open
70
+ multiple
71
+ select-all
72
+ >
73
+ <glide-core-dropdown-option
74
+ label="One"
75
+ value="one"
76
+ ></glide-core-dropdown-option>
77
+
78
+ <glide-core-dropdown-option
79
+ label="Two"
80
+ value="two"
81
+ selected
82
+ ></glide-core-dropdown-option>
83
+ </glide-core-dropdown>`);
84
+ setTimeout(() => {
85
+ component.shadowRoot
86
+ ?.querySelector('[data-test="select-all"]')
87
+ ?.click();
88
+ });
89
+ await aTimeout(0);
90
+ const spy = sinon.spy();
91
+ component.addEventListener('change', spy);
92
+ setTimeout(() => {
93
+ component.querySelector('glide-core-dropdown-option')?.click();
94
+ });
95
+ await aTimeout(0);
96
+ expect(spy.called).to.be.true;
97
+ });
98
+ it('dispatches an "input" event when an option is selected after Select All is clicked', async () => {
99
+ const component = await fixture(html `<glide-core-dropdown
100
+ label="Label"
101
+ placeholder="Placeholder"
102
+ open
103
+ multiple
104
+ select-all
105
+ >
106
+ <glide-core-dropdown-option
107
+ label="One"
108
+ value="one"
109
+ ></glide-core-dropdown-option>
110
+
111
+ <glide-core-dropdown-option
112
+ label="Two"
113
+ value="two"
114
+ selected
115
+ ></glide-core-dropdown-option>
116
+ </glide-core-dropdown>`);
117
+ setTimeout(() => {
118
+ component.shadowRoot
119
+ ?.querySelector('[data-test="select-all"]')
120
+ ?.click();
121
+ });
122
+ await aTimeout(0);
123
+ const spy = sinon.spy();
124
+ component.addEventListener('input', spy);
125
+ setTimeout(() => {
126
+ component.querySelector('glide-core-dropdown-option')?.click();
127
+ });
128
+ await aTimeout(0);
129
+ expect(spy.called).to.be.true;
130
+ });
@@ -0,0 +1 @@
1
+ import './dropdown.option.js';
@@ -0,0 +1,154 @@
1
+ import './dropdown.option.js';
2
+ import { assert, expect, fixture, html } from '@open-wc/testing';
3
+ import { sendMouse } from '@web/test-runner-commands';
4
+ import GlideCoreDropdown from './dropdown.js';
5
+ import GlideCoreDropdownOption from './dropdown.option.js';
6
+ GlideCoreDropdown.shadowRootOptions.mode = 'open';
7
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
8
+ const defaultSlot = html `
9
+ <glide-core-dropdown-option
10
+ label="One"
11
+ value="one"
12
+ ></glide-core-dropdown-option>
13
+
14
+ <glide-core-dropdown-option
15
+ label="Two"
16
+ value="two"
17
+ ></glide-core-dropdown-option>
18
+
19
+ <glide-core-dropdown-option
20
+ label="Three"
21
+ value="three"
22
+ ></glide-core-dropdown-option>
23
+
24
+ <glide-core-dropdown-option
25
+ label="Four"
26
+ value="four"
27
+ ></glide-core-dropdown-option>
28
+
29
+ <glide-core-dropdown-option
30
+ label="Five"
31
+ value="five"
32
+ ></glide-core-dropdown-option>
33
+
34
+ <glide-core-dropdown-option
35
+ label="Six"
36
+ value="six"
37
+ ></glide-core-dropdown-option>
38
+
39
+ <glide-core-dropdown-option
40
+ label="Seven"
41
+ value="seven"
42
+ ></glide-core-dropdown-option>
43
+
44
+ <glide-core-dropdown-option
45
+ label="Eight"
46
+ value="eight"
47
+ ></glide-core-dropdown-option>
48
+
49
+ <glide-core-dropdown-option
50
+ label="Nine"
51
+ value="nine"
52
+ ></glide-core-dropdown-option>
53
+
54
+ <glide-core-dropdown-option
55
+ label="Ten"
56
+ value="ten"
57
+ ></glide-core-dropdown-option>
58
+
59
+ <glide-core-dropdown-option
60
+ label="Eleven"
61
+ value="eleven"
62
+ ></glide-core-dropdown-option>
63
+ `;
64
+ it('focuses the input when `focus` is called', async () => {
65
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
66
+ ${defaultSlot}
67
+ </glide-core-dropdown>`);
68
+ component.focus();
69
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
70
+ expect(component.shadowRoot?.activeElement).to.equal(input);
71
+ });
72
+ it('retains focus on the input when an option is selected via click', async () => {
73
+ const component = await fixture(html `<glide-core-dropdown
74
+ label="Label"
75
+ placeholder="Placeholder"
76
+ multiple
77
+ open
78
+ >
79
+ ${defaultSlot}
80
+ </glide-core-dropdown>`);
81
+ component.focus();
82
+ const option = component.querySelector('glide-core-dropdown-option');
83
+ assert(option);
84
+ const { x, y } = option.getBoundingClientRect();
85
+ // A simple `option.click()` won't do because we need a "mousedown" so that
86
+ // `#onOptionsMousedown` gets covered.
87
+ await sendMouse({
88
+ type: 'click',
89
+ position: [Math.ceil(x), Math.ceil(y)],
90
+ });
91
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
92
+ expect(component.shadowRoot?.activeElement).to.equal(input);
93
+ });
94
+ it('retains focus on the the input when an option is selected via Enter', async () => {
95
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
96
+ ${defaultSlot}
97
+ </glide-core-dropdown>`);
98
+ component.focus();
99
+ component
100
+ .querySelector('glide-core-dropdown-option')
101
+ ?.shadowRoot?.querySelector('[data-test="component"]')
102
+ ?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
103
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
104
+ expect(component.shadowRoot?.activeElement).to.equal(input);
105
+ });
106
+ it('retains focus on the the input when the button is clicked', async () => {
107
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
108
+ ${defaultSlot}
109
+ </glide-core-dropdown>`);
110
+ component.focus();
111
+ const button = component.shadowRoot?.querySelector('[data-test="button"]');
112
+ assert(button);
113
+ const { x, y } = button.getBoundingClientRect();
114
+ // A simple `option.click()` won't do because we need a "mousedown" so that
115
+ // `#onDropdownMousedown` gets covered.
116
+ await sendMouse({
117
+ type: 'click',
118
+ position: [Math.ceil(x), Math.ceil(y)],
119
+ });
120
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
121
+ expect(component.shadowRoot?.activeElement).to.equal(input);
122
+ });
123
+ it('focuses the input on submit when required and no option is selected', async () => {
124
+ const form = document.createElement('form');
125
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" required>
126
+ ${defaultSlot}
127
+ <glide-core-dropdown-option
128
+ label="Label"
129
+ value="value"
130
+ ></glide-core-dropdown-option>
131
+ </glide-core-dropdown>`, {
132
+ parentNode: form,
133
+ });
134
+ form.requestSubmit();
135
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
136
+ expect(component.shadowRoot?.activeElement).to.be.equal(input);
137
+ });
138
+ it('focuses the input when `reportValidity` is called when required and no option is selected', async () => {
139
+ const form = document.createElement('form');
140
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" required>
141
+ ${defaultSlot}
142
+ </glide-core-dropdown>`, { parentNode: form });
143
+ component.reportValidity();
144
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
145
+ expect(component.shadowRoot?.activeElement).to.equal(input);
146
+ });
147
+ it('does not focus the input when `checkValidity` is called', async () => {
148
+ const form = document.createElement('form');
149
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" required>
150
+ ${defaultSlot}
151
+ </glide-core-dropdown>`, { parentNode: form });
152
+ component.checkValidity();
153
+ expect(component.shadowRoot?.activeElement).to.equal(null);
154
+ });
@@ -0,0 +1,28 @@
1
+ import './dropdown.option.js';
2
+ import { expect, fixture, html } from '@open-wc/testing';
3
+ import { sendKeys } from '@web/test-runner-commands';
4
+ import GlideCoreDropdown from './dropdown.js';
5
+ import GlideCoreDropdownOption from './dropdown.option.js';
6
+ GlideCoreDropdown.shadowRootOptions.mode = 'open';
7
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
8
+ it('closes when it loses focus', async () => {
9
+ const div = document.createElement('div');
10
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
11
+ <glide-core-dropdown-option
12
+ label="Label"
13
+ value="value"
14
+ ></glide-core-dropdown-option>
15
+ </glide-core-dropdown>`, { parentNode: div });
16
+ const button = document.createElement('button');
17
+ div.prepend(button);
18
+ component.focus();
19
+ // Move focus to the body.
20
+ await sendKeys({ press: 'Tab' });
21
+ expect(component.open).to.be.false;
22
+ component.open = true;
23
+ component.focus();
24
+ // Move focus to the button.
25
+ await sendKeys({ down: 'Shift' });
26
+ await sendKeys({ press: 'Tab' });
27
+ expect(component.open).to.be.false;
28
+ });
@@ -0,0 +1,181 @@
1
+ import './dropdown.option.js';
2
+ import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
3
+ import GlideCoreDropdown from './dropdown.js';
4
+ import GlideCoreDropdownOption from './dropdown.option.js';
5
+ import GlideCoreTag from './tag.js';
6
+ GlideCoreDropdown.shadowRootOptions.mode = 'open';
7
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
8
+ it('focuses the button when `focus` is called', async () => {
9
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
10
+ <glide-core-dropdown-option
11
+ label="One"
12
+ value="one"
13
+ ></glide-core-dropdown-option>
14
+
15
+ <glide-core-dropdown-option
16
+ label="Two"
17
+ value="two"
18
+ ></glide-core-dropdown-option>
19
+ </glide-core-dropdown>`);
20
+ component.focus();
21
+ expect(component.shadowRoot?.activeElement).to.equal(component.shadowRoot?.querySelector('[data-test="button"]'));
22
+ });
23
+ it('focuses the button on submit when required and no options are selected', async () => {
24
+ const form = document.createElement('form');
25
+ const component = await fixture(html `<glide-core-dropdown
26
+ label="Label"
27
+ placeholder="Placeholder"
28
+ multiple
29
+ required
30
+ >
31
+ <glide-core-dropdown-option
32
+ label="One"
33
+ value="one"
34
+ ></glide-core-dropdown-option>
35
+
36
+ <glide-core-dropdown-option
37
+ label="Two"
38
+ value="two"
39
+ ></glide-core-dropdown-option>
40
+ </glide-core-dropdown>`, {
41
+ parentNode: form,
42
+ });
43
+ form.requestSubmit();
44
+ const button = component.shadowRoot?.querySelector('[data-test="button"]');
45
+ expect(component.shadowRoot?.activeElement).to.be.equal(button);
46
+ });
47
+ it('focuses the button when `reportValidity` is called when required and no options are selected', async () => {
48
+ const form = document.createElement('form');
49
+ const component = await fixture(html `<glide-core-dropdown
50
+ label="Label"
51
+ placeholder="Placeholder"
52
+ multiple
53
+ required
54
+ >
55
+ <glide-core-dropdown-option
56
+ label="One"
57
+ value="one"
58
+ ></glide-core-dropdown-option>
59
+
60
+ <glide-core-dropdown-option
61
+ label="Two"
62
+ value="two"
63
+ ></glide-core-dropdown-option>
64
+ </glide-core-dropdown>`, { parentNode: form });
65
+ component.reportValidity();
66
+ const button = component.shadowRoot?.querySelector('[data-test="button"]');
67
+ expect(component.shadowRoot?.activeElement).to.equal(button);
68
+ });
69
+ it('does not focus the button when `checkValidity` is called', async () => {
70
+ const form = document.createElement('form');
71
+ const component = await fixture(html `<glide-core-dropdown
72
+ label="Label"
73
+ placeholder="Placeholder"
74
+ multiple
75
+ required
76
+ >
77
+ <glide-core-dropdown-option
78
+ label="One"
79
+ value="one"
80
+ selected
81
+ ></glide-core-dropdown-option>
82
+
83
+ <glide-core-dropdown-option
84
+ label="Two"
85
+ value="two"
86
+ selected
87
+ ></glide-core-dropdown-option>
88
+ </glide-core-dropdown>`, { parentNode: form });
89
+ component.checkValidity();
90
+ expect(component.shadowRoot?.activeElement).to.equal(null);
91
+ });
92
+ it('focuses the second tag when the first one is removed', async () => {
93
+ const component = await fixture(html `<glide-core-dropdown
94
+ label="Label"
95
+ placeholder="Placeholder"
96
+ open
97
+ multiple
98
+ >
99
+ <glide-core-dropdown-option
100
+ label="One"
101
+ value="one"
102
+ selected
103
+ ></glide-core-dropdown-option>
104
+
105
+ <glide-core-dropdown-option
106
+ label="Two"
107
+ value="two"
108
+ selected
109
+ ></glide-core-dropdown-option>
110
+
111
+ <glide-core-dropdown-option
112
+ label="Three"
113
+ value="three"
114
+ selected
115
+ ></glide-core-dropdown-option>
116
+ </glide-core-dropdown>`);
117
+ const tags = component.shadowRoot?.querySelectorAll('[data-test="tag"]');
118
+ tags?.[0].click();
119
+ await elementUpdated(component);
120
+ expect(component.shadowRoot?.activeElement).to.equal(tags?.[1]);
121
+ });
122
+ it('focuses the third tag when the second one is removed', async () => {
123
+ const component = await fixture(html `<glide-core-dropdown
124
+ label="Label"
125
+ placeholder="Placeholder"
126
+ open
127
+ multiple
128
+ >
129
+ <glide-core-dropdown-option
130
+ label="One"
131
+ value="one"
132
+ selected
133
+ ></glide-core-dropdown-option>
134
+
135
+ <glide-core-dropdown-option
136
+ label="Two"
137
+ value="two"
138
+ selected
139
+ ></glide-core-dropdown-option>
140
+
141
+ <glide-core-dropdown-option
142
+ label="Three"
143
+ value="three"
144
+ selected
145
+ ></glide-core-dropdown-option>
146
+ </glide-core-dropdown>`);
147
+ const tags = component.shadowRoot?.querySelectorAll('[data-test="tag"]');
148
+ tags?.[1].click();
149
+ await elementUpdated(component);
150
+ expect(component.shadowRoot?.activeElement).to.equal(tags?.[2]);
151
+ });
152
+ it('focuses the second tag when the last one removed', async () => {
153
+ const component = await fixture(html `<glide-core-dropdown
154
+ label="Label"
155
+ placeholder="Placeholder"
156
+ open
157
+ multiple
158
+ >
159
+ <glide-core-dropdown-option
160
+ label="One"
161
+ value="one"
162
+ selected
163
+ ></glide-core-dropdown-option>
164
+
165
+ <glide-core-dropdown-option
166
+ label="Two"
167
+ value="two"
168
+ selected
169
+ ></glide-core-dropdown-option>
170
+
171
+ <glide-core-dropdown-option
172
+ label="Three"
173
+ value="three"
174
+ selected
175
+ ></glide-core-dropdown-option>
176
+ </glide-core-dropdown>`);
177
+ const tags = component.shadowRoot?.querySelectorAll('[data-test="tag"]');
178
+ tags?.[2].click();
179
+ await elementUpdated(component);
180
+ expect(component.shadowRoot?.activeElement).to.equal(tags?.[1]);
181
+ });
@@ -0,0 +1,53 @@
1
+ import './dropdown.option.js';
2
+ import { expect, fixture, html } from '@open-wc/testing';
3
+ import GlideCoreDropdown from './dropdown.js';
4
+ import GlideCoreDropdownOption from './dropdown.option.js';
5
+ GlideCoreDropdown.shadowRootOptions.mode = 'open';
6
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
7
+ it('focuses the button when `focus` is called', async () => {
8
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
9
+ <glide-core-dropdown-option
10
+ label="Label"
11
+ value="value"
12
+ ></glide-core-dropdown-option>
13
+ </glide-core-dropdown>`);
14
+ component.focus();
15
+ expect(component.shadowRoot?.activeElement).to.equal(component.shadowRoot?.querySelector('[data-test="button"]'));
16
+ });
17
+ it('focuses the button on submit', async () => {
18
+ const form = document.createElement('form');
19
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" required>
20
+ <glide-core-dropdown-option
21
+ label="Label"
22
+ value="value"
23
+ ></glide-core-dropdown-option>
24
+ </glide-core-dropdown>`, {
25
+ parentNode: form,
26
+ });
27
+ form.requestSubmit();
28
+ const button = component.shadowRoot?.querySelector('[data-test="button"]');
29
+ expect(component.shadowRoot?.activeElement).to.be.equal(button);
30
+ });
31
+ it('focuses the button when `reportValidity` is called when required and no option is selected', async () => {
32
+ const form = document.createElement('form');
33
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" required>
34
+ <glide-core-dropdown-option
35
+ label="Label"
36
+ value="value"
37
+ ></glide-core-dropdown-option>
38
+ </glide-core-dropdown>`, { parentNode: form });
39
+ component.reportValidity();
40
+ const button = component.shadowRoot?.querySelector('[data-test="button"]');
41
+ expect(component.shadowRoot?.activeElement).to.equal(button);
42
+ });
43
+ it('does not focus the button when `checkValidity` is called', async () => {
44
+ const form = document.createElement('form');
45
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" required>
46
+ <glide-core-dropdown-option
47
+ label="Label"
48
+ value="value"
49
+ ></glide-core-dropdown-option>
50
+ </glide-core-dropdown>`, { parentNode: form });
51
+ component.checkValidity();
52
+ expect(component.shadowRoot?.activeElement).to.equal(null);
53
+ });
@@ -0,0 +1,140 @@
1
+ import './dropdown.option.js';
2
+ import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
3
+ import GlideCoreDropdown from './dropdown.js';
4
+ import GlideCoreDropdownOption from './dropdown.option.js';
5
+ GlideCoreDropdown.shadowRootOptions.mode = 'open';
6
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
7
+ it('exposes standard form control properties and methods', async () => {
8
+ const form = document.createElement('form');
9
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
10
+ <glide-core-dropdown-option
11
+ label="Label"
12
+ value="value"
13
+ ></glide-core-dropdown-option>
14
+ </glide-core-dropdown>`, { parentNode: form });
15
+ expect(component.form).to.equal(form);
16
+ expect(component.validity instanceof ValidityState).to.be.true;
17
+ expect(component.willValidate).to.be.true;
18
+ expect(component.checkValidity).to.be.a('function');
19
+ expect(component.reportValidity).to.be.a('function');
20
+ });
21
+ it('can be reset', async () => {
22
+ const form = document.createElement('form');
23
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
24
+ <glide-core-dropdown-option
25
+ label="One"
26
+ value="one"
27
+ ></glide-core-dropdown-option>
28
+
29
+ <glide-core-dropdown-option
30
+ label="Two"
31
+ value="two"
32
+ ></glide-core-dropdown-option>
33
+ </glide-core-dropdown>`, {
34
+ parentNode: form,
35
+ });
36
+ component
37
+ .querySelector('glide-core-dropdown-option')
38
+ ?.shadowRoot?.querySelector('[data-test="component"]')
39
+ ?.dispatchEvent(new Event('click'));
40
+ form.reset();
41
+ await elementUpdated(component);
42
+ const label = component.shadowRoot?.querySelector('[data-test="internal-label"]');
43
+ expect(label?.textContent?.trim()).to.equal('Placeholder');
44
+ expect(component.value).to.deep.equal([]);
45
+ });
46
+ it('can be reset to the initially selected option', async () => {
47
+ const form = document.createElement('form');
48
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
49
+ <glide-core-dropdown-option
50
+ label="One"
51
+ value="one"
52
+ ></glide-core-dropdown-option>
53
+
54
+ <glide-core-dropdown-option
55
+ label="Two"
56
+ value="two"
57
+ selected
58
+ ></glide-core-dropdown-option>
59
+ </glide-core-dropdown>`, {
60
+ parentNode: form,
61
+ });
62
+ component
63
+ .querySelector('glide-core-dropdown-option')
64
+ ?.shadowRoot?.querySelector('[data-test="component"]')
65
+ ?.dispatchEvent(new Event('click'));
66
+ form.reset();
67
+ expect(component.value).to.deep.equal(['two']);
68
+ });
69
+ it('has `formData` value when an option is selected', async () => {
70
+ const form = document.createElement('form');
71
+ await fixture(html `<glide-core-dropdown
72
+ label="Label"
73
+ placeholder="Placeholder"
74
+ name="name"
75
+ >
76
+ <glide-core-dropdown-option
77
+ label="Label"
78
+ value="value"
79
+ selected
80
+ ></glide-core-dropdown-option>
81
+ </glide-core-dropdown>
82
+ >`, {
83
+ parentNode: form,
84
+ });
85
+ const formData = new FormData(form);
86
+ expect(formData.get('name')).to.be.equal('["value"]');
87
+ });
88
+ it('has no `formData` value when no option is selected', async () => {
89
+ const form = document.createElement('form');
90
+ await fixture(html `<glide-core-dropdown
91
+ label="Label"
92
+ placeholder="Placeholder"
93
+ name="name"
94
+ >
95
+ <glide-core-dropdown-option
96
+ label=""
97
+ value="value"
98
+ ></glide-core-dropdown-option>
99
+ </glide-core-dropdown>`, {
100
+ parentNode: form,
101
+ });
102
+ const formData = new FormData(form);
103
+ expect(formData.get('name')).to.be.null;
104
+ });
105
+ it('has no `formData` value when disabled and an option is selected', async () => {
106
+ const form = document.createElement('form');
107
+ await fixture(html `<glide-core-dropdown
108
+ label="Label"
109
+ placeholder="Placeholder"
110
+ name="name"
111
+ disabled
112
+ >
113
+ <glide-core-dropdown-option
114
+ label="Label"
115
+ value="value"
116
+ selected
117
+ ></glide-core-dropdown-option>
118
+ </glide-core-dropdown>`, {
119
+ parentNode: form,
120
+ });
121
+ const formData = new FormData(form);
122
+ expect(formData.get('name')).to.be.null;
123
+ });
124
+ it('has no `formData` value when an option is selected that has no `value`', async () => {
125
+ const form = document.createElement('form');
126
+ await fixture(html `<glide-core-dropdown
127
+ label="Label"
128
+ placeholder="Placeholder"
129
+ name="name"
130
+ >
131
+ <glide-core-dropdown-option
132
+ label="Label"
133
+ selected
134
+ ></glide-core-dropdown-option>
135
+ </glide-core-dropdown>`, {
136
+ parentNode: form,
137
+ });
138
+ const formData = new FormData(form);
139
+ expect(formData.get('name')).to.be.null;
140
+ });