@crowdstrike/glide-core 0.5.0 → 0.5.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.
Files changed (208) hide show
  1. package/dist/accordion.js +1 -1
  2. package/dist/accordion.styles.js +4 -4
  3. package/dist/accordion.test.basics.js +109 -0
  4. package/dist/accordion.test.events.js +39 -0
  5. package/dist/button-group.button.js +1 -1
  6. package/dist/button-group.button.styles.js +4 -4
  7. package/dist/button-group.button.test.basics.js +169 -0
  8. package/dist/button-group.button.test.events.js +73 -0
  9. package/dist/button-group.js +1 -1
  10. package/dist/button-group.styles.js +3 -3
  11. package/dist/button-group.test.basics.js +268 -0
  12. package/dist/button-group.test.events.js +291 -0
  13. package/dist/button.js +1 -1
  14. package/dist/button.styles.js +4 -4
  15. package/dist/button.test.basics.js +196 -0
  16. package/dist/button.test.events.js +25 -0
  17. package/dist/button.test.form.js +49 -0
  18. package/dist/checkbox-group.js +1 -1
  19. package/dist/checkbox-group.styles.js +2 -2
  20. package/dist/checkbox-group.test.basics.js +119 -0
  21. package/dist/checkbox-group.test.events.js +110 -0
  22. package/dist/checkbox-group.test.focus.js +45 -0
  23. package/dist/checkbox-group.test.form.js +130 -0
  24. package/dist/checkbox-group.test.validity.js +75 -0
  25. package/dist/checkbox.js +1 -1
  26. package/dist/checkbox.styles.js +3 -3
  27. package/dist/checkbox.test.basics.js +89 -0
  28. package/dist/checkbox.test.events.js +87 -0
  29. package/dist/checkbox.test.focus.js +38 -0
  30. package/dist/checkbox.test.form.js +115 -0
  31. package/dist/checkbox.test.states.js +62 -0
  32. package/dist/checkbox.test.validity.js +51 -0
  33. package/dist/drawer.d.ts +2 -2
  34. package/dist/drawer.js +1 -15
  35. package/dist/drawer.styles.js +18 -3
  36. package/dist/drawer.test.accessibility.js +22 -0
  37. package/dist/drawer.test.basics.js +43 -0
  38. package/dist/drawer.test.closing.js +37 -0
  39. package/dist/drawer.test.events.js +52 -0
  40. package/dist/drawer.test.methods.js +34 -0
  41. package/dist/dropdown.d.ts +4 -2
  42. package/dist/dropdown.js +1 -1
  43. package/dist/dropdown.option.d.ts +1 -3
  44. package/dist/dropdown.option.js +1 -1
  45. package/dist/dropdown.option.styles.js +2 -2
  46. package/dist/dropdown.option.test.basics.js +59 -0
  47. package/dist/dropdown.option.test.basics.multiple.js +26 -0
  48. package/dist/dropdown.option.test.basics.single.js +20 -0
  49. package/dist/dropdown.option.test.events.js +27 -0
  50. package/dist/dropdown.option.test.focus.js +11 -0
  51. package/dist/dropdown.option.test.interactions.multiple.js +87 -0
  52. package/dist/dropdown.option.test.interactions.single.js +22 -0
  53. package/dist/dropdown.styles.js +28 -9
  54. package/dist/dropdown.test.basics.filterable.js +84 -0
  55. package/dist/dropdown.test.basics.js +233 -0
  56. package/dist/dropdown.test.basics.multiple.js +270 -0
  57. package/dist/dropdown.test.basics.single.js +79 -0
  58. package/dist/dropdown.test.events.js +268 -0
  59. package/dist/dropdown.test.events.multiple.js +130 -0
  60. package/dist/dropdown.test.focus.d.ts +1 -0
  61. package/dist/dropdown.test.focus.filterable.js +154 -0
  62. package/dist/dropdown.test.focus.js +18 -0
  63. package/dist/dropdown.test.focus.multiple.js +181 -0
  64. package/dist/dropdown.test.focus.single.js +53 -0
  65. package/dist/dropdown.test.form.js +140 -0
  66. package/dist/dropdown.test.form.multiple.js +149 -0
  67. package/dist/dropdown.test.form.single.js +128 -0
  68. package/dist/dropdown.test.interactions.filterable.js +385 -0
  69. package/dist/dropdown.test.interactions.js +446 -0
  70. package/dist/dropdown.test.interactions.multiple.js +908 -0
  71. package/dist/dropdown.test.interactions.single.js +466 -0
  72. package/dist/dropdown.test.validity.js +46 -0
  73. package/dist/icon-button.js +1 -1
  74. package/dist/icon-button.styles.js +3 -3
  75. package/dist/icon-button.test.basics.js +103 -0
  76. package/dist/icons/checked.js +1 -1
  77. package/dist/icons/magnifying-glass.js +1 -1
  78. package/dist/input.js +1 -1
  79. package/dist/input.styles.js +3 -3
  80. package/dist/input.test.basics.js +169 -0
  81. package/dist/input.test.events.js +97 -0
  82. package/dist/input.test.focus.js +54 -0
  83. package/dist/input.test.form.js +56 -0
  84. package/dist/input.test.validity.js +50 -0
  85. package/dist/label.js +1 -1
  86. package/dist/label.styles.js +3 -3
  87. package/dist/label.test.basics.js +129 -0
  88. package/dist/library/expect-argument-error.js +1 -1
  89. package/dist/library/ow.js +1 -1
  90. package/dist/library/ow.test.js +55 -0
  91. package/dist/menu.button.d.ts +1 -2
  92. package/dist/menu.button.js +1 -1
  93. package/dist/menu.button.styles.js +3 -3
  94. package/dist/menu.button.test.basics.js +42 -0
  95. package/dist/menu.d.ts +4 -0
  96. package/dist/menu.js +1 -1
  97. package/dist/menu.link.d.ts +1 -2
  98. package/dist/menu.link.js +1 -1
  99. package/dist/menu.link.styles.js +3 -3
  100. package/dist/menu.link.test.basics.js +46 -0
  101. package/dist/menu.styles.js +13 -6
  102. package/dist/menu.test.basics.js +161 -0
  103. package/dist/menu.test.focus.d.ts +0 -1
  104. package/dist/menu.test.focus.js +66 -0
  105. package/dist/menu.test.interactions.d.ts +0 -1
  106. package/dist/menu.test.interactions.js +522 -0
  107. package/dist/modal.icon-button.js +1 -1
  108. package/dist/modal.icon-button.styles.js +2 -2
  109. package/dist/modal.icon-button.test.basics.js +45 -0
  110. package/dist/modal.js +1 -15
  111. package/dist/modal.styles.js +4 -4
  112. package/dist/modal.tertiary-icon.js +1 -1
  113. package/dist/modal.tertiary-icon.test.basics.js +59 -0
  114. package/dist/modal.test.accessibility.js +48 -0
  115. package/dist/modal.test.basics.js +203 -0
  116. package/dist/modal.test.close.js +38 -0
  117. package/dist/modal.test.events.js +110 -0
  118. package/dist/modal.test.lock-scroll.js +76 -0
  119. package/dist/modal.test.methods.js +23 -0
  120. package/dist/modal.test.scrollbars.js +19 -0
  121. package/dist/radio-group.js +1 -1
  122. package/dist/radio-group.styles.js +2 -2
  123. package/dist/radio-group.test.basics.js +323 -0
  124. package/dist/radio-group.test.events.js +277 -0
  125. package/dist/radio-group.test.focus.js +75 -0
  126. package/dist/radio-group.test.form.js +104 -0
  127. package/dist/radio-group.test.validity.js +228 -0
  128. package/dist/radio.js +1 -1
  129. package/dist/radio.styles.js +4 -4
  130. package/dist/split-button.d.ts +24 -0
  131. package/dist/split-button.js +1 -0
  132. package/dist/split-button.stories.d.ts +17 -0
  133. package/dist/split-button.styles.d.ts +2 -0
  134. package/dist/split-button.styles.js +103 -0
  135. package/dist/split-button.test.basics.d.ts +1 -0
  136. package/dist/split-button.test.basics.js +84 -0
  137. package/dist/split-container.d.ts +30 -0
  138. package/dist/split-container.js +1 -0
  139. package/dist/split-container.styles.d.ts +2 -0
  140. package/dist/split-container.styles.js +132 -0
  141. package/dist/split-container.test.basics.d.ts +3 -0
  142. package/dist/split-container.test.basics.js +445 -0
  143. package/dist/split-container.test.interactions.d.ts +1 -0
  144. package/dist/split-container.test.interactions.js +20 -0
  145. package/dist/split-link.d.ts +25 -0
  146. package/dist/split-link.js +1 -0
  147. package/dist/split-link.test.basics.d.ts +1 -0
  148. package/dist/split-link.test.basics.js +92 -0
  149. package/dist/split-link.test.interactions.d.ts +1 -0
  150. package/dist/split-link.test.interactions.js +19 -0
  151. package/dist/status-indicator.js +1 -1
  152. package/dist/status-indicator.styles.js +2 -2
  153. package/dist/status-indicator.test.basics.js +102 -0
  154. package/dist/styles/focus-outline.js +1 -4
  155. package/dist/styles/visually-hidden.js +1 -11
  156. package/dist/tab.group.js +1 -1
  157. package/dist/tab.group.styles.js +2 -2
  158. package/dist/tab.group.test.basics.js +185 -0
  159. package/dist/tab.js +1 -1
  160. package/dist/tab.panel.js +1 -1
  161. package/dist/tab.panel.styles.js +3 -3
  162. package/dist/tab.styles.js +2 -2
  163. package/dist/tab.test.basics.js +71 -0
  164. package/dist/tag.js +1 -1
  165. package/dist/tag.styles.js +3 -3
  166. package/dist/tag.test.basics.js +118 -0
  167. package/dist/tag.test.events.js +16 -0
  168. package/dist/tag.test.focus.js +11 -0
  169. package/dist/textarea.js +2 -2
  170. package/dist/textarea.styles.js +3 -3
  171. package/dist/textarea.test.basics.js +140 -0
  172. package/dist/textarea.test.events.js +204 -0
  173. package/dist/textarea.test.form.js +70 -0
  174. package/dist/textarea.test.validity.js +83 -0
  175. package/dist/toasts.js +1 -1
  176. package/dist/toasts.styles.js +2 -2
  177. package/dist/toasts.test.basics.js +94 -0
  178. package/dist/toasts.toast.js +1 -1
  179. package/dist/toasts.toast.styles.js +5 -2
  180. package/dist/toasts.toast.test.basics.js +139 -0
  181. package/dist/toggle.js +1 -1
  182. package/dist/toggle.styles.js +3 -3
  183. package/dist/toggle.test.basics.js +64 -0
  184. package/dist/toggle.test.events.js +29 -0
  185. package/dist/toggle.test.focus.js +9 -0
  186. package/dist/toggle.test.states.js +35 -0
  187. package/dist/tooltip.js +1 -1
  188. package/dist/tooltip.styles.js +3 -3
  189. package/dist/tooltip.test.basics.js +64 -0
  190. package/dist/tooltip.test.interactions.js +78 -0
  191. package/dist/tree.item.icon-button.js +1 -1
  192. package/dist/tree.item.icon-button.styles.js +2 -2
  193. package/dist/tree.item.icon-button.test.basics.js +13 -0
  194. package/dist/tree.item.js +1 -1
  195. package/dist/tree.item.menu.js +1 -1
  196. package/dist/tree.item.menu.styles.js +2 -2
  197. package/dist/tree.item.menu.test.basics.js +34 -0
  198. package/dist/tree.item.styles.js +2 -2
  199. package/dist/tree.item.test.basics.js +102 -0
  200. package/dist/tree.js +1 -1
  201. package/dist/tree.styles.js +2 -2
  202. package/dist/tree.test.aria.js +86 -0
  203. package/dist/tree.test.basics.js +123 -0
  204. package/dist/tree.test.events.js +19 -0
  205. package/dist/tree.test.focus.js +261 -0
  206. package/package.json +20 -18
  207. /package/dist/{dropdown.option.test.focus.multiple.d.ts → dropdown.option.test.focus.d.ts} +0 -0
  208. /package/dist/{dropdown.option.test.focus.single.d.ts → dropdown.test.events.multiple.d.ts} +0 -0
@@ -0,0 +1,149 @@
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('can be reset', async () => {
8
+ const form = document.createElement('form');
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
+ parentNode: form,
21
+ });
22
+ const options = component.querySelectorAll('glide-core-dropdown-option');
23
+ options[0]?.shadowRoot
24
+ ?.querySelector('[data-test="component"]')
25
+ ?.dispatchEvent(new Event('click'));
26
+ options[1]?.shadowRoot
27
+ ?.querySelector('[data-test="component"]')
28
+ ?.dispatchEvent(new Event('click'));
29
+ form.reset();
30
+ await elementUpdated(component);
31
+ expect(component.value).to.deep.equal([]);
32
+ const label = component.shadowRoot?.querySelector('[data-test="internal-label"]');
33
+ expect(label?.textContent?.trim()).to.equal('Placeholder');
34
+ });
35
+ it('can be reset to the initially selected options', async () => {
36
+ const form = document.createElement('form');
37
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
38
+ <glide-core-dropdown-option
39
+ label="One"
40
+ value="one"
41
+ ></glide-core-dropdown-option>
42
+
43
+ <glide-core-dropdown-option
44
+ label="Two"
45
+ value="two"
46
+ selected
47
+ ></glide-core-dropdown-option>
48
+
49
+ <glide-core-dropdown-option
50
+ label="Three"
51
+ value="three"
52
+ selected
53
+ ></glide-core-dropdown-option>
54
+ </glide-core-dropdown>`, {
55
+ parentNode: form,
56
+ });
57
+ component
58
+ .querySelector('glide-core-dropdown-option')
59
+ ?.shadowRoot?.querySelector('[data-test="component"]')
60
+ ?.dispatchEvent(new Event('click'));
61
+ form.reset();
62
+ const tags = component.shadowRoot?.querySelectorAll('[data-test="tag"]');
63
+ expect(tags?.length).to.equal(2);
64
+ expect(tags?.[0].textContent?.trim()).to.equal('Two');
65
+ expect(tags?.[1].textContent?.trim()).to.equal('Three');
66
+ expect(component.value).to.deep.equal(['two', 'three']);
67
+ });
68
+ it('has `formData` value when options are selected', async () => {
69
+ const form = document.createElement('form');
70
+ await fixture(html `<glide-core-dropdown
71
+ label="Label"
72
+ placeholder="Placeholder"
73
+ name="name"
74
+ multiple
75
+ >
76
+ <glide-core-dropdown-option
77
+ label="One"
78
+ value="one"
79
+ selected
80
+ ></glide-core-dropdown-option>
81
+
82
+ <glide-core-dropdown-option
83
+ label="Two"
84
+ value="two"
85
+ selected
86
+ ></glide-core-dropdown-option>
87
+ </glide-core-dropdown>
88
+ >`, {
89
+ parentNode: form,
90
+ });
91
+ const formData = new FormData(form);
92
+ expect(formData.get('name')).to.be.equal('["one","two"]');
93
+ });
94
+ it('has no `formData` value when no option is selected', async () => {
95
+ const form = document.createElement('form');
96
+ await fixture(html `<glide-core-dropdown
97
+ label="Label"
98
+ placeholder="Placeholder"
99
+ name="name"
100
+ multiple
101
+ >
102
+ <glide-core-dropdown-option
103
+ label=""
104
+ value="value"
105
+ ></glide-core-dropdown-option>
106
+ </glide-core-dropdown>`, {
107
+ parentNode: form,
108
+ });
109
+ const formData = new FormData(form);
110
+ expect(formData.get('name')).to.be.null;
111
+ });
112
+ it('has no `formData` value when disabled and an option is selected', async () => {
113
+ const form = document.createElement('form');
114
+ await fixture(html `<glide-core-dropdown
115
+ label="Label"
116
+ placeholder="Placeholder"
117
+ name="name"
118
+ disabled
119
+ multiple
120
+ >
121
+ <glide-core-dropdown-option
122
+ label="Label"
123
+ value="value"
124
+ selected
125
+ ></glide-core-dropdown-option>
126
+ </glide-core-dropdown>`, {
127
+ parentNode: form,
128
+ });
129
+ const formData = new FormData(form);
130
+ expect(formData.get('name')).to.be.null;
131
+ });
132
+ it('has no `formData` value when an option is selected that has no `value`', async () => {
133
+ const form = document.createElement('form');
134
+ await fixture(html `<glide-core-dropdown
135
+ label="Label"
136
+ placeholder="Placeholder"
137
+ name="name"
138
+ multiple
139
+ >
140
+ <glide-core-dropdown-option
141
+ label="Label"
142
+ selected
143
+ ></glide-core-dropdown-option>
144
+ </glide-core-dropdown>`, {
145
+ parentNode: form,
146
+ });
147
+ const formData = new FormData(form);
148
+ expect(formData.get('name')).to.be.null;
149
+ });
@@ -0,0 +1,128 @@
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('can be reset', 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="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
+ parentNode: form,
21
+ });
22
+ component
23
+ .querySelector('glide-core-dropdown-option')
24
+ ?.shadowRoot?.querySelector('[data-test="component"]')
25
+ ?.dispatchEvent(new Event('click'));
26
+ form.reset();
27
+ await elementUpdated(component);
28
+ const label = component.shadowRoot?.querySelector('[data-test="internal-label"]');
29
+ expect(label?.textContent?.trim()).to.equal('Placeholder');
30
+ expect(component.value).to.deep.equal([]);
31
+ });
32
+ it('can be reset to the initially selected option', async () => {
33
+ const form = document.createElement('form');
34
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
35
+ <glide-core-dropdown-option
36
+ label="One"
37
+ value="one"
38
+ ></glide-core-dropdown-option>
39
+
40
+ <glide-core-dropdown-option
41
+ label="Two"
42
+ value="two"
43
+ selected
44
+ ></glide-core-dropdown-option>
45
+ </glide-core-dropdown>`, {
46
+ parentNode: form,
47
+ });
48
+ component
49
+ .querySelector('glide-core-dropdown-option')
50
+ ?.shadowRoot?.querySelector('[data-test="component"]')
51
+ ?.dispatchEvent(new Event('click'));
52
+ form.reset();
53
+ const label = component.shadowRoot?.querySelector('[data-test="internal-label"]');
54
+ expect(label?.textContent?.trim()).to.equal('Two');
55
+ expect(component.value).to.deep.equal(['two']);
56
+ });
57
+ it('has `formData` value when an option is selected', async () => {
58
+ const form = document.createElement('form');
59
+ await fixture(html `<glide-core-dropdown
60
+ label="Label"
61
+ placeholder="Placeholder"
62
+ name="name"
63
+ >
64
+ <glide-core-dropdown-option
65
+ label="Label"
66
+ value="value"
67
+ selected
68
+ ></glide-core-dropdown-option>
69
+ </glide-core-dropdown>
70
+ >`, {
71
+ parentNode: form,
72
+ });
73
+ const formData = new FormData(form);
74
+ expect(formData.get('name')).to.be.equal('["value"]');
75
+ });
76
+ it('has no `formData` value when no option is selected', async () => {
77
+ const form = document.createElement('form');
78
+ await fixture(html `<glide-core-dropdown
79
+ label="Label"
80
+ placeholder="Placeholder"
81
+ name="name"
82
+ >
83
+ <glide-core-dropdown-option
84
+ label=""
85
+ value="value"
86
+ ></glide-core-dropdown-option>
87
+ </glide-core-dropdown>`, {
88
+ parentNode: form,
89
+ });
90
+ const formData = new FormData(form);
91
+ expect(formData.get('name')).to.be.null;
92
+ });
93
+ it('has no `formData` value when disabled and an option is selected', async () => {
94
+ const form = document.createElement('form');
95
+ await fixture(html `<glide-core-dropdown
96
+ label="Label"
97
+ placeholder="Placeholder"
98
+ name="name"
99
+ disabled
100
+ >
101
+ <glide-core-dropdown-option
102
+ label="Label"
103
+ value="value"
104
+ selected
105
+ ></glide-core-dropdown-option>
106
+ </glide-core-dropdown>`, {
107
+ parentNode: form,
108
+ });
109
+ const formData = new FormData(form);
110
+ expect(formData.get('name')).to.be.null;
111
+ });
112
+ it('has no `formData` value when an option is selected that has no `value`', async () => {
113
+ const form = document.createElement('form');
114
+ await fixture(html `<glide-core-dropdown
115
+ label="Label"
116
+ placeholder="Placeholder"
117
+ name="name"
118
+ >
119
+ <glide-core-dropdown-option
120
+ label="Label"
121
+ selected
122
+ ></glide-core-dropdown-option>
123
+ </glide-core-dropdown>`, {
124
+ parentNode: form,
125
+ });
126
+ const formData = new FormData(form);
127
+ expect(formData.get('name')).to.be.null;
128
+ });
@@ -0,0 +1,385 @@
1
+ import { assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
2
+ import { sendKeys } from '@web/test-runner-commands';
3
+ import GlideCoreDropdown from './dropdown.js';
4
+ import GlideCoreDropdownOption from './dropdown.option.js';
5
+ GlideCoreDropdown.shadowRootOptions.mode = 'open';
6
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
7
+ const defaultSlot = html `
8
+ <glide-core-dropdown-option
9
+ label="One"
10
+ value="one"
11
+ ></glide-core-dropdown-option>
12
+
13
+ <glide-core-dropdown-option
14
+ label="Two"
15
+ value="two"
16
+ ></glide-core-dropdown-option>
17
+
18
+ <glide-core-dropdown-option
19
+ label="Three"
20
+ value="three"
21
+ ></glide-core-dropdown-option>
22
+
23
+ <glide-core-dropdown-option
24
+ label="Four"
25
+ value="four"
26
+ ></glide-core-dropdown-option>
27
+
28
+ <glide-core-dropdown-option
29
+ label="Five"
30
+ value="five"
31
+ ></glide-core-dropdown-option>
32
+
33
+ <glide-core-dropdown-option
34
+ label="Six"
35
+ value="six"
36
+ ></glide-core-dropdown-option>
37
+
38
+ <glide-core-dropdown-option
39
+ label="Seven"
40
+ value="seven"
41
+ ></glide-core-dropdown-option>
42
+
43
+ <glide-core-dropdown-option
44
+ label="Eight"
45
+ value="eight"
46
+ ></glide-core-dropdown-option>
47
+
48
+ <glide-core-dropdown-option
49
+ label="Nine"
50
+ value="nine"
51
+ ></glide-core-dropdown-option>
52
+
53
+ <glide-core-dropdown-option
54
+ label="Ten"
55
+ value="ten"
56
+ ></glide-core-dropdown-option>
57
+
58
+ <glide-core-dropdown-option
59
+ label="Eleven"
60
+ value="eleven"
61
+ ></glide-core-dropdown-option>
62
+ `;
63
+ it('opens on click', async () => {
64
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
65
+ ${defaultSlot}
66
+ </glide-core-dropdown>`);
67
+ // Calling `click()` would be sweet. The problem is it sets `event.detail` to `0`,
68
+ // which puts us in a guard in the event handler. `Event` has no `detail` property
69
+ // and would work. `CustomEvent` is used for completeness and to get us as close as
70
+ // possible to a real click. See the comment in the handler for more information.
71
+ component.shadowRoot
72
+ ?.querySelector('[data-test="input"]')
73
+ ?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
74
+ expect(component.open).to.be.true;
75
+ });
76
+ it('filters', async () => {
77
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
78
+ ${defaultSlot}
79
+ </glide-core-dropdown>`);
80
+ component.focus();
81
+ await sendKeys({ type: ' one ' });
82
+ const options = [
83
+ ...component.querySelectorAll('glide-core-dropdown-option'),
84
+ ].filter(({ hidden }) => !hidden);
85
+ expect(options.length).to.equal(1);
86
+ });
87
+ it('clears the filter term when an option is selected', async () => {
88
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
89
+ ${defaultSlot}
90
+ </glide-core-dropdown>`);
91
+ component.focus();
92
+ await sendKeys({ type: ' one ' });
93
+ const option = [
94
+ ...component.querySelectorAll('glide-core-dropdown-option'),
95
+ ].find(({ hidden }) => !hidden);
96
+ option?.click();
97
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
98
+ const options = [
99
+ ...component.querySelectorAll('glide-core-dropdown-option'),
100
+ ].filter(({ hidden }) => !hidden);
101
+ expect(input?.value).to.equal('');
102
+ expect(options.length).to.equal(11);
103
+ });
104
+ it('shows the magnifying glass icon when there is a filter term', async () => {
105
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
106
+ ${defaultSlot}
107
+ </glide-core-dropdown>`);
108
+ component.focus();
109
+ await sendKeys({ type: ' one ' });
110
+ const icon = component?.shadowRoot?.querySelector('[data-test="magnifying-glass-icon"]');
111
+ expect(icon?.checkVisibility()).to.be.true;
112
+ });
113
+ it('hides the magnifying glass icon when there is no filter term', async () => {
114
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
115
+ ${defaultSlot}
116
+ </glide-core-dropdown>`);
117
+ const icon = component?.shadowRoot?.querySelector('[data-test="magnifying-glass-icon"]');
118
+ expect(icon?.checkVisibility()).to.be.not.ok;
119
+ });
120
+ it('hides the magnifying glass icon when an option is selected', async () => {
121
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
122
+ ${defaultSlot}
123
+ </glide-core-dropdown>`);
124
+ component.focus();
125
+ await sendKeys({ type: ' one ' });
126
+ const option = [
127
+ ...component.querySelectorAll('glide-core-dropdown-option'),
128
+ ].find(({ hidden }) => !hidden);
129
+ option?.click();
130
+ const icon = component?.shadowRoot?.querySelector('[data-test="magnifying-glass-icon"]');
131
+ await elementUpdated(component);
132
+ expect(icon?.checkVisibility()).to.be.not.ok;
133
+ });
134
+ it('does not filter on only whitespace', async () => {
135
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
136
+ ${defaultSlot}
137
+ </glide-core-dropdown>`);
138
+ component.focus();
139
+ await sendKeys({ type: ' ' });
140
+ const options = [
141
+ ...component.querySelectorAll('glide-core-dropdown-option'),
142
+ ].filter(({ hidden }) => !hidden);
143
+ expect(options.length).to.equal(11);
144
+ });
145
+ it('hides the options when all of them are filtered out', async () => {
146
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
147
+ ${defaultSlot}
148
+ </glide-core-dropdown>`);
149
+ component.focus();
150
+ await sendKeys({ type: 'twelve' });
151
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
152
+ expect(options?.dataset.testVisible).to.equal('false');
153
+ });
154
+ it('hides Select All when filtering', async () => {
155
+ const component = await fixture(html `<glide-core-dropdown
156
+ label="Label"
157
+ placeholder="Placeholder"
158
+ open
159
+ multiple
160
+ select-all
161
+ >
162
+ ${defaultSlot}
163
+ </glide-core-dropdown>`);
164
+ component.focus();
165
+ await sendKeys({ type: 'one' });
166
+ const selectAll = component.shadowRoot?.querySelector('[data-test="select-all"]');
167
+ expect(selectAll?.checkVisibility()).to.not.be.ok;
168
+ });
169
+ it('sets the first unfiltered option as active when the previously active option is filtered out', async () => {
170
+ const component = await fixture(html `<glide-core-dropdown
171
+ label="Label"
172
+ placeholder="Placeholder"
173
+ multiple
174
+ select-all
175
+ >
176
+ ${defaultSlot}
177
+ </glide-core-dropdown>`);
178
+ component.focus();
179
+ await sendKeys({ type: 'two' });
180
+ const option = [
181
+ ...component.querySelectorAll('glide-core-dropdown-option'),
182
+ ].find(({ hidden }) => !hidden);
183
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
184
+ expect(option?.privateActive).to.be.true;
185
+ expect(input?.getAttribute('aria-activedescendant')).to.equal(option?.id);
186
+ });
187
+ it('updates `value` when an option `value` is changed programmatically', async () => {
188
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
189
+ ${defaultSlot}
190
+ </glide-core-dropdown>`);
191
+ const option = component.querySelector('glide-core-dropdown-option');
192
+ assert(option);
193
+ option.value = 'two';
194
+ expect(component.value).to.deep.equal(['two']);
195
+ });
196
+ it('deselects options on Backspace', async () => {
197
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
198
+ ${defaultSlot}
199
+ </glide-core-dropdown>`);
200
+ const options = component.querySelectorAll('glide-core-dropdown-option');
201
+ options[0].selected = true;
202
+ options[1].selected = true;
203
+ component.focus();
204
+ await sendKeys({ press: 'Backspace' });
205
+ expect(options[1].selected).to.be.false;
206
+ expect(options[0].selected).to.be.true;
207
+ await sendKeys({ press: 'Backspace' });
208
+ expect(options[0].selected).to.be.false;
209
+ });
210
+ it('uses the label of the selected option as a placeholder when not `multiple`', async () => {
211
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
212
+ ${defaultSlot}
213
+ </glide-core-dropdown>`);
214
+ const option = component?.querySelector('glide-core-dropdown-option');
215
+ option?.click();
216
+ await elementUpdated(component);
217
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
218
+ expect(input?.placeholder).to.equal(option?.label);
219
+ });
220
+ it('uses `placeholder` as a placeholder when `multiple` and an option is selected', async () => {
221
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
222
+ ${defaultSlot}
223
+ </glide-core-dropdown>`);
224
+ component?.querySelector('glide-core-dropdown-option')?.click();
225
+ await elementUpdated(component);
226
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
227
+ expect(input?.placeholder).to.equal('Placeholder');
228
+ });
229
+ it('sets `aria-activedescendant` on option "mouseover"', async () => {
230
+ const component = await fixture(html `<glide-core-dropdown open> ${defaultSlot} </glide-core-dropdown>`);
231
+ const options = component.querySelectorAll('glide-core-dropdown-option');
232
+ options[1]?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
233
+ await elementUpdated(component);
234
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
235
+ expect(input?.getAttribute('aria-activedescendant')).to.equal(options[1].id);
236
+ });
237
+ it('sets `aria-activedescendant` on ArrowDown', async () => {
238
+ const component = await fixture(html `<glide-core-dropdown
239
+ label="Label"
240
+ placeholder="Placeholder"
241
+ open
242
+ multiple
243
+ >
244
+ ${defaultSlot}
245
+ </glide-core-dropdown>`);
246
+ const options = component.querySelectorAll('glide-core-dropdown-option');
247
+ options[0]?.focus();
248
+ await sendKeys({ press: 'ArrowDown' });
249
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
250
+ expect(input?.getAttribute('aria-activedescendant')).to.equal(options[1].id);
251
+ });
252
+ it('sets `aria-activedescendant` on ArrowUp', async () => {
253
+ const component = await fixture(html `<glide-core-dropdown
254
+ label="Label"
255
+ placeholder="Placeholder"
256
+ open
257
+ multiple
258
+ >
259
+ ${defaultSlot}
260
+ </glide-core-dropdown>`);
261
+ const options = component.querySelectorAll('glide-core-dropdown-option');
262
+ options[1]?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
263
+ options[1]?.focus();
264
+ await sendKeys({ press: 'ArrowUp' });
265
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
266
+ expect(input?.getAttribute('aria-activedescendant')).to.equal(options[0].id);
267
+ });
268
+ it('sets `aria-activedescendant` on Home', async () => {
269
+ const component = await fixture(html `<glide-core-dropdown
270
+ label="Label"
271
+ placeholder="Placeholder"
272
+ open
273
+ multiple
274
+ >
275
+ ${defaultSlot}
276
+ </glide-core-dropdown>`);
277
+ const options = component.querySelectorAll('glide-core-dropdown-option');
278
+ options[1]?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
279
+ options[1].focus();
280
+ await sendKeys({ press: 'Home' });
281
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
282
+ expect(input?.getAttribute('aria-activedescendant')).to.equal(options[0].id);
283
+ });
284
+ it('sets `aria-activedescendant` on PageUp', async () => {
285
+ const component = await fixture(html `<glide-core-dropdown
286
+ label="Label"
287
+ placeholder="Placeholder"
288
+ open
289
+ multiple
290
+ >
291
+ ${defaultSlot}
292
+ </glide-core-dropdown>`);
293
+ const options = component.querySelectorAll('glide-core-dropdown-option');
294
+ options[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
295
+ options[1].focus();
296
+ await sendKeys({ press: 'PageUp' });
297
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
298
+ expect(input?.getAttribute('aria-activedescendant')).to.equal(options[0].id);
299
+ });
300
+ it('sets `aria-activedescendant` on ArrowUp + Meta', async () => {
301
+ const component = await fixture(html `<glide-core-dropdown
302
+ label="Label"
303
+ placeholder="Placeholder"
304
+ open
305
+ multiple
306
+ >
307
+ ${defaultSlot}
308
+ </glide-core-dropdown>`);
309
+ const options = component.querySelectorAll('glide-core-dropdown-option');
310
+ options[1]?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
311
+ options[1].focus();
312
+ await sendKeys({ down: 'Meta' });
313
+ await sendKeys({ press: 'ArrowUp' });
314
+ await sendKeys({ up: 'Meta' });
315
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
316
+ expect(input?.getAttribute('aria-activedescendant')).to.equal(options[0].id);
317
+ });
318
+ it('sets `aria-activedescendant` on End', async () => {
319
+ const component = await fixture(html `<glide-core-dropdown
320
+ label="Label"
321
+ placeholder="Placeholder"
322
+ open
323
+ multiple
324
+ >
325
+ ${defaultSlot}
326
+ </glide-core-dropdown>`);
327
+ // Made into an array because the linter forces `at(-1)` instead of
328
+ // `[options.length - 1]` but doesn't take into account that `options`
329
+ // isn't an actual array and doesn't have an `at()` method.
330
+ const options = [...component.querySelectorAll('glide-core-dropdown-option')];
331
+ options[0]?.focus();
332
+ await sendKeys({ press: 'End' });
333
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
334
+ expect(input?.getAttribute('aria-activedescendant')).to.equal(options.at(-1)?.id);
335
+ });
336
+ it('sets `aria-activedescendant` on PageDown', async () => {
337
+ const component = await fixture(html `<glide-core-dropdown
338
+ label="Label"
339
+ placeholder="Placeholder"
340
+ open
341
+ multiple
342
+ >
343
+ ${defaultSlot}
344
+ </glide-core-dropdown>`);
345
+ // Made into an array because the linter forces `at(-1)` instead of
346
+ // `[options.length - 1]` but doesn't take into account that `options`
347
+ // isn't an actual array and doesn't have an `at()` method.
348
+ const options = [...component.querySelectorAll('glide-core-dropdown-option')];
349
+ options[0]?.focus();
350
+ await sendKeys({ press: 'PageDown' });
351
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
352
+ expect(input?.getAttribute('aria-activedescendant')).to.equal(options.at(-1)?.id);
353
+ });
354
+ it('sets `aria-activedescendant` on Meta + ArrowDown', async () => {
355
+ const component = await fixture(html `<glide-core-dropdown
356
+ label="Label"
357
+ placeholder="Placeholder"
358
+ open
359
+ multiple
360
+ >
361
+ ${defaultSlot}
362
+ </glide-core-dropdown>`);
363
+ // Spread into an array because the linter forces `at(-1)` instead of
364
+ // `[options.length - 1]` but doesn't take into account that `options`
365
+ // isn't an actual array and doesn't have an `at()` method.
366
+ const options = [...component.querySelectorAll('glide-core-dropdown-option')];
367
+ options[0]?.focus();
368
+ await sendKeys({ down: 'Meta' });
369
+ await sendKeys({ press: 'ArrowDown' });
370
+ await sendKeys({ up: 'Meta' });
371
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
372
+ expect(input?.getAttribute('aria-activedescendant')).to.equal(options.at(-1)?.id);
373
+ });
374
+ it('cannot be tabbed to when `disabled`', async () => {
375
+ await fixture(html `<glide-core-dropdown
376
+ label="Label"
377
+ placeholder="Placeholder"
378
+ multiple
379
+ disabled
380
+ >
381
+ ${defaultSlot}
382
+ </glide-core-dropdown>`);
383
+ await sendKeys({ down: 'Tab' });
384
+ expect(document.activeElement).to.equal(document.body);
385
+ });