@crowdstrike/glide-core 0.7.0 → 0.9.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 (203) hide show
  1. package/README.md +44 -5
  2. package/dist/accordion.test.basics.js +1 -0
  3. package/dist/accordion.test.events.js +1 -0
  4. package/dist/button-group.button.d.ts +14 -15
  5. package/dist/button-group.button.js +1 -1
  6. package/dist/button-group.button.styles.js +75 -52
  7. package/dist/button-group.button.test.basics.d.ts +1 -1
  8. package/dist/button-group.button.test.basics.js +84 -147
  9. package/dist/button-group.button.test.events.js +9 -67
  10. package/dist/button-group.button.test.focus.js +13 -0
  11. package/dist/button-group.button.test.interactions.d.ts +1 -0
  12. package/dist/button-group.button.test.interactions.js +42 -0
  13. package/dist/button-group.d.ts +7 -10
  14. package/dist/button-group.js +1 -1
  15. package/dist/button-group.stories.d.ts +1 -5
  16. package/dist/button-group.styles.js +18 -6
  17. package/dist/button-group.test.basics.js +114 -234
  18. package/dist/button-group.test.events.js +211 -263
  19. package/dist/button-group.test.focus.d.ts +1 -0
  20. package/dist/button-group.test.focus.js +39 -0
  21. package/dist/button-group.test.interactions.d.ts +1 -0
  22. package/dist/button-group.test.interactions.js +91 -0
  23. package/dist/button.test.basics.js +2 -1
  24. package/dist/button.test.events.js +1 -0
  25. package/dist/button.test.form.js +1 -0
  26. package/dist/checkbox-group.js +1 -1
  27. package/dist/checkbox-group.styles.js +1 -1
  28. package/dist/checkbox-group.test.basics.js +2 -1
  29. package/dist/checkbox-group.test.events.js +5 -4
  30. package/dist/checkbox-group.test.focus.js +5 -3
  31. package/dist/checkbox-group.test.form.js +1 -0
  32. package/dist/checkbox-group.test.validity.js +1 -0
  33. package/dist/checkbox.d.ts +7 -1
  34. package/dist/checkbox.js +1 -1
  35. package/dist/checkbox.styles.js +11 -3
  36. package/dist/checkbox.test.basics.js +1 -0
  37. package/dist/checkbox.test.events.js +5 -4
  38. package/dist/checkbox.test.focus.js +2 -2
  39. package/dist/checkbox.test.form.js +1 -0
  40. package/dist/{checkbox.test.states.js → checkbox.test.interactions.js} +25 -1
  41. package/dist/checkbox.test.validity.js +1 -0
  42. package/dist/drawer.js +1 -1
  43. package/dist/drawer.test.basics.js +1 -0
  44. package/dist/drawer.test.closing.js +1 -0
  45. package/dist/drawer.test.events.js +1 -0
  46. package/dist/drawer.test.methods.js +1 -0
  47. package/dist/dropdown.d.ts +6 -4
  48. package/dist/dropdown.js +1 -1
  49. package/dist/dropdown.option.d.ts +7 -2
  50. package/dist/dropdown.option.js +1 -1
  51. package/dist/dropdown.option.styles.js +13 -0
  52. package/dist/dropdown.option.test.basics.js +7 -3
  53. package/dist/dropdown.option.test.basics.multiple.js +1 -0
  54. package/dist/dropdown.option.test.basics.single.js +1 -0
  55. package/dist/dropdown.option.test.events.js +2 -1
  56. package/dist/dropdown.option.test.focus.js +1 -1
  57. package/dist/dropdown.option.test.interactions.multiple.js +2 -54
  58. package/dist/dropdown.option.test.interactions.single.js +52 -9
  59. package/dist/dropdown.styles.js +20 -19
  60. package/dist/dropdown.test.basics.filterable.js +1 -0
  61. package/dist/dropdown.test.basics.js +144 -2
  62. package/dist/dropdown.test.basics.multiple.js +6 -3
  63. package/dist/dropdown.test.basics.single.js +1 -1
  64. package/dist/dropdown.test.events.filterable.js +74 -0
  65. package/dist/dropdown.test.events.js +50 -160
  66. package/dist/dropdown.test.events.multiple.js +268 -10
  67. package/dist/dropdown.test.events.single.js +202 -4
  68. package/dist/dropdown.test.focus.filterable.js +9 -5
  69. package/dist/dropdown.test.focus.js +2 -1
  70. package/dist/dropdown.test.focus.multiple.js +1 -2
  71. package/dist/dropdown.test.focus.single.js +1 -1
  72. package/dist/dropdown.test.form.js +1 -0
  73. package/dist/dropdown.test.form.multiple.js +1 -0
  74. package/dist/dropdown.test.form.single.js +1 -0
  75. package/dist/dropdown.test.interactions.filterable.js +69 -11
  76. package/dist/dropdown.test.interactions.js +95 -5
  77. package/dist/dropdown.test.interactions.multiple.js +203 -6
  78. package/dist/dropdown.test.interactions.single.js +69 -6
  79. package/dist/dropdown.test.validity.js +1 -0
  80. package/dist/form-controls-layout.test.basics.js +2 -1
  81. package/dist/icon-button.test.basics.js +2 -1
  82. package/dist/icons/checked.d.ts +1 -1
  83. package/dist/icons/checked.js +1 -1
  84. package/dist/icons/magnifying-glass.js +1 -1
  85. package/dist/input.d.ts +0 -6
  86. package/dist/input.js +1 -1
  87. package/dist/input.styles.js +7 -2
  88. package/dist/input.test.basics.js +20 -5
  89. package/dist/input.test.events.js +5 -4
  90. package/dist/input.test.focus.js +5 -4
  91. package/dist/input.test.form.js +1 -0
  92. package/dist/input.test.translations.d.ts +1 -0
  93. package/dist/input.test.translations.js +38 -0
  94. package/dist/input.test.validity.js +134 -4
  95. package/dist/label.d.ts +1 -1
  96. package/dist/label.js +1 -1
  97. package/dist/label.styles.js +29 -20
  98. package/dist/label.test.basics.js +27 -24
  99. package/dist/library/expect-argument-error.js +1 -1
  100. package/dist/library/localize.d.ts +5 -1
  101. package/dist/library/ow.test.d.ts +2 -1
  102. package/dist/library/ow.test.js +8 -3
  103. package/dist/menu.button.test.basics.js +1 -0
  104. package/dist/menu.d.ts +3 -5
  105. package/dist/menu.js +1 -1
  106. package/dist/menu.link.test.basics.js +1 -0
  107. package/dist/menu.options.test.basics.js +3 -2
  108. package/dist/menu.styles.js +1 -15
  109. package/dist/menu.test.basics.d.ts +1 -2
  110. package/dist/menu.test.basics.js +23 -6
  111. package/dist/menu.test.events.d.ts +1 -0
  112. package/dist/menu.test.events.js +2 -1
  113. package/dist/menu.test.focus.d.ts +1 -0
  114. package/dist/menu.test.focus.js +14 -6
  115. package/dist/menu.test.interactions.js +213 -56
  116. package/dist/modal.icon-button.test.basics.js +2 -1
  117. package/dist/modal.js +1 -1
  118. package/dist/modal.styles.js +18 -13
  119. package/dist/modal.tertiary-icon.d.ts +0 -1
  120. package/dist/modal.tertiary-icon.js +1 -1
  121. package/dist/modal.tertiary-icon.test.basics.js +2 -1
  122. package/dist/modal.test.accessibility.js +1 -0
  123. package/dist/modal.test.basics.js +2 -1
  124. package/dist/modal.test.close.js +1 -0
  125. package/dist/modal.test.events.js +11 -10
  126. package/dist/modal.test.lock-scroll.js +1 -0
  127. package/dist/modal.test.methods.js +1 -0
  128. package/dist/modal.test.scrollbars.js +1 -0
  129. package/dist/radio-group.js +1 -1
  130. package/dist/radio-group.styles.js +1 -1
  131. package/dist/radio-group.test.basics.js +1 -0
  132. package/dist/radio-group.test.events.js +1 -0
  133. package/dist/radio-group.test.focus.js +4 -3
  134. package/dist/radio-group.test.form.js +1 -0
  135. package/dist/radio-group.test.validity.js +1 -0
  136. package/dist/radio.d.ts +1 -0
  137. package/dist/radio.js +1 -1
  138. package/dist/radio.styles.js +33 -0
  139. package/dist/split-button.test.basics.js +1 -0
  140. package/dist/split-container.test.basics.js +5 -0
  141. package/dist/split-link.test.basics.js +1 -0
  142. package/dist/split-link.test.interactions.js +2 -1
  143. package/dist/styles/variables.css +1 -1
  144. package/dist/tab.d.ts +1 -3
  145. package/dist/tab.group.d.ts +3 -5
  146. package/dist/tab.group.js +1 -1
  147. package/dist/tab.group.styles.js +27 -13
  148. package/dist/tab.group.test.basics.js +8 -57
  149. package/dist/tab.group.test.interactions.d.ts +3 -0
  150. package/dist/tab.group.test.interactions.js +454 -0
  151. package/dist/tab.js +1 -1
  152. package/dist/tab.panel.d.ts +1 -0
  153. package/dist/tab.panel.js +1 -1
  154. package/dist/tab.panel.styles.js +11 -1
  155. package/dist/tab.styles.js +7 -68
  156. package/dist/tab.test.basics.js +0 -20
  157. package/dist/tabs.stories.d.ts +1 -2
  158. package/dist/tag.test.basics.js +3 -2
  159. package/dist/textarea.d.ts +0 -1
  160. package/dist/textarea.js +2 -2
  161. package/dist/textarea.stories.d.ts +3 -4
  162. package/dist/textarea.styles.js +14 -3
  163. package/dist/textarea.test.basics.js +81 -44
  164. package/dist/textarea.test.events.js +57 -41
  165. package/dist/textarea.test.form.js +1 -0
  166. package/dist/textarea.test.translations.d.ts +1 -0
  167. package/dist/textarea.test.translations.js +34 -0
  168. package/dist/textarea.test.validity.js +105 -20
  169. package/dist/toasts.js +1 -1
  170. package/dist/toasts.styles.js +8 -1
  171. package/dist/toasts.test.basics.js +20 -0
  172. package/dist/toggle.js +1 -1
  173. package/dist/toggle.test.basics.js +1 -0
  174. package/dist/toggle.test.events.js +1 -0
  175. package/dist/toggle.test.focus.js +1 -1
  176. package/dist/toggle.test.interactions.d.ts +1 -0
  177. package/dist/{toggle.test.states.js → toggle.test.interactions.js} +1 -0
  178. package/dist/tooltip.d.ts +7 -5
  179. package/dist/tooltip.js +1 -1
  180. package/dist/tooltip.styles.js +90 -25
  181. package/dist/tooltip.test.basics.js +39 -3
  182. package/dist/tooltip.test.interactions.js +137 -34
  183. package/dist/translations/en.js +1 -1
  184. package/dist/translations/fr.js +1 -1
  185. package/dist/translations/ja.js +1 -1
  186. package/dist/tree.d.ts +0 -1
  187. package/dist/tree.item.d.ts +2 -3
  188. package/dist/tree.item.js +1 -1
  189. package/dist/tree.item.menu.d.ts +0 -1
  190. package/dist/tree.item.menu.js +1 -1
  191. package/dist/tree.item.test.basics.js +1 -0
  192. package/dist/tree.js +1 -1
  193. package/dist/tree.test.basics.js +2 -1
  194. package/dist/tree.test.events.js +1 -1
  195. package/package.json +40 -29
  196. package/dist/drawer.test.floating-components.d.ts +0 -1
  197. package/dist/drawer.test.floating-components.js +0 -51
  198. package/dist/library/set-containing-block.d.ts +0 -15
  199. package/dist/library/set-containing-block.js +0 -1
  200. package/dist/modal.test.floating-components.js +0 -62
  201. /package/dist/{checkbox.test.states.d.ts → button-group.button.test.focus.d.ts} +0 -0
  202. /package/dist/{modal.test.floating-components.d.ts → checkbox.test.interactions.d.ts} +0 -0
  203. /package/dist/{toggle.test.states.d.ts → dropdown.test.events.filterable.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import * as sinon from 'sinon';
2
- import { aTimeout, expect, fixture, html, oneEvent } from '@open-wc/testing';
3
- import { sendKeys } from '@web/test-runner-commands';
3
+ import { aTimeout, assert, expect, fixture, html, oneEvent, } from '@open-wc/testing';
4
4
  import GlideCoreDropdown from './dropdown.js';
5
5
  import GlideCoreDropdownOption from './dropdown.option.js';
6
6
  GlideCoreDropdown.shadowRootOptions.mode = 'open';
@@ -10,160 +10,6 @@ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
10
10
  // timeout, which would make for a slow test. Its timeout can likely be
11
11
  // configured. But waiting a turn of the event loop, when which the event
12
12
  // will have been dispatched, gets the job done as well.
13
- it('dispatches a "change" event when an option is selected via click', async () => {
14
- const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
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.querySelector('glide-core-dropdown-option')?.click();
30
- });
31
- const event = await oneEvent(component, 'change');
32
- expect(event instanceof Event).to.be.true;
33
- expect(event.bubbles).to.be.true;
34
- expect(spy.calledOnce).to.be.true;
35
- });
36
- it('dispatches a "change" event when an option is selected via Enter', async () => {
37
- const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
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
- </glide-core-dropdown>`);
49
- const spy = sinon.spy();
50
- component.addEventListener('change', spy);
51
- // Activate the first option before selecting it. The second option is
52
- // currently active because it's selected.
53
- component
54
- .querySelector('glide-core-dropdown-option')
55
- ?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
56
- component.focus();
57
- sendKeys({ press: 'Enter' });
58
- const event = await oneEvent(component, 'change');
59
- expect(event instanceof Event).to.be.true;
60
- expect(event.bubbles).to.be.true;
61
- expect(spy.calledOnce).to.be.true;
62
- });
63
- it('dispatches a "change" event when an option is selected via Space', async () => {
64
- const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
65
- <glide-core-dropdown-option
66
- label="One"
67
- value="one"
68
- ></glide-core-dropdown-option>
69
-
70
- <glide-core-dropdown-option
71
- label="Two"
72
- value="two"
73
- selected
74
- ></glide-core-dropdown-option>
75
- </glide-core-dropdown>`);
76
- const spy = sinon.spy();
77
- component.addEventListener('change', spy);
78
- // Activate the first option before selecting it. The second option is
79
- // currently active because it's selected.
80
- component
81
- .querySelector('glide-core-dropdown-option')
82
- ?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
83
- component.focus();
84
- sendKeys({ press: ' ' });
85
- const event = await oneEvent(component, 'change');
86
- expect(event instanceof Event).to.be.true;
87
- expect(event.bubbles).to.be.true;
88
- expect(spy.calledOnce).to.be.true;
89
- });
90
- it('dispatches an "input" event when an option is selected via click', async () => {
91
- const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
92
- <glide-core-dropdown-option
93
- label="One"
94
- value="one"
95
- ></glide-core-dropdown-option>
96
-
97
- <glide-core-dropdown-option
98
- label="Two"
99
- value="two"
100
- selected
101
- ></glide-core-dropdown-option>
102
- </glide-core-dropdown>`);
103
- const spy = sinon.spy();
104
- component.addEventListener('input', spy);
105
- setTimeout(() => {
106
- component.querySelector('glide-core-dropdown-option')?.click();
107
- });
108
- const event = await oneEvent(component, 'input');
109
- expect(event instanceof Event).to.be.true;
110
- expect(event.bubbles).to.be.true;
111
- expect(spy.calledOnce).to.be.true;
112
- });
113
- it('dispatches an "input" event when an option is selected via Enter', async () => {
114
- const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
115
- <glide-core-dropdown-option
116
- label="One"
117
- value="one"
118
- ></glide-core-dropdown-option>
119
-
120
- <glide-core-dropdown-option
121
- label="Two"
122
- value="two"
123
- selected
124
- ></glide-core-dropdown-option>
125
- </glide-core-dropdown>`);
126
- const spy = sinon.spy();
127
- component.addEventListener('input', spy);
128
- // Activate the first option before selecting it. The second option is
129
- // currently active because it's selected.
130
- component
131
- .querySelector('glide-core-dropdown-option')
132
- ?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
133
- component.focus();
134
- sendKeys({ press: 'Enter' });
135
- const event = await oneEvent(component, 'input');
136
- expect(event instanceof Event).to.be.true;
137
- expect(event.bubbles).to.be.true;
138
- expect(spy.calledOnce).to.be.true;
139
- });
140
- it('dispatches an "input" event when an option is selected via Space', async () => {
141
- const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
142
- <glide-core-dropdown-option
143
- label="One"
144
- value="one"
145
- ></glide-core-dropdown-option>
146
-
147
- <glide-core-dropdown-option
148
- label="Two"
149
- value="two"
150
- selected
151
- ></glide-core-dropdown-option>
152
- </glide-core-dropdown>`);
153
- const spy = sinon.spy();
154
- component.addEventListener('input', spy);
155
- // Activate the first option before selecting it. The second option is
156
- // currently active because it's selected.
157
- component
158
- .querySelector('glide-core-dropdown-option')
159
- ?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
160
- component.focus();
161
- sendKeys({ press: ' ' });
162
- const event = await oneEvent(component, 'input');
163
- expect(event instanceof Event).to.be.true;
164
- expect(event.bubbles).to.be.true;
165
- expect(spy.calledOnce).to.be.true;
166
- });
167
13
  it('dispatches an "invalid" event on submit when required and no option is selected', async () => {
168
14
  const form = document.createElement('form');
169
15
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" required>
@@ -212,7 +58,7 @@ it('does not dispatch an "invalid" event when `checkValidity` is called when not
212
58
  component.addEventListener('invalid', spy);
213
59
  component.checkValidity();
214
60
  await aTimeout(0);
215
- expect(spy.notCalled).to.be.true;
61
+ expect(spy.callCount).to.equal(0);
216
62
  });
217
63
  it('does not dispatch an "invalid" event when `checkValidity` is called when required, disabled, and no option is selected', async () => {
218
64
  const form = document.createElement('form');
@@ -231,7 +77,7 @@ it('does not dispatch an "invalid" event when `checkValidity` is called when req
231
77
  component.addEventListener('invalid', spy);
232
78
  component.checkValidity();
233
79
  await aTimeout(0);
234
- expect(spy.notCalled).to.be.true;
80
+ expect(spy.callCount).to.equal(0);
235
81
  });
236
82
  it('does not dispatch an "invalid" event when `reportValidity` is called when not required,', async () => {
237
83
  const form = document.createElement('form');
@@ -245,7 +91,7 @@ it('does not dispatch an "invalid" event when `reportValidity` is called when no
245
91
  component.addEventListener('invalid', spy);
246
92
  component.reportValidity();
247
93
  await aTimeout(0);
248
- expect(spy.notCalled).to.be.true;
94
+ expect(spy.callCount).to.equal(0);
249
95
  });
250
96
  it('does not dispatch an "invalid" event when `reportValidity` is called when required, disabled, and no option is selected', async () => {
251
97
  const form = document.createElement('form');
@@ -264,5 +110,49 @@ it('does not dispatch an "invalid" event when `reportValidity` is called when re
264
110
  component.addEventListener('invalid', spy);
265
111
  component.reportValidity();
266
112
  await aTimeout(0);
267
- expect(spy.notCalled).to.be.true;
113
+ expect(spy.callCount).to.equal(0);
114
+ });
115
+ it('does not dispatch a "change" event when an option is selected programmatically', async () => {
116
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
117
+ <glide-core-dropdown-option
118
+ label="One"
119
+ value="one"
120
+ ></glide-core-dropdown-option>
121
+
122
+ <glide-core-dropdown-option
123
+ label="Two"
124
+ value="two"
125
+ ></glide-core-dropdown-option>
126
+ </glide-core-dropdown>`);
127
+ const spy = sinon.spy();
128
+ component.addEventListener('change', spy);
129
+ setTimeout(() => {
130
+ const option = component?.querySelector('glide-core-dropdown-option');
131
+ assert(option);
132
+ option.selected = true;
133
+ });
134
+ await aTimeout(0);
135
+ expect(spy.callCount).to.equal(0);
136
+ });
137
+ it('does not dispatch a "input" event when an option is selected programmatically', async () => {
138
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
139
+ <glide-core-dropdown-option
140
+ label="One"
141
+ value="one"
142
+ ></glide-core-dropdown-option>
143
+
144
+ <glide-core-dropdown-option
145
+ label="Two"
146
+ value="two"
147
+ ></glide-core-dropdown-option>
148
+ </glide-core-dropdown>`);
149
+ const spy = sinon.spy();
150
+ component.addEventListener('input', spy);
151
+ setTimeout(() => {
152
+ const option = component?.querySelector('glide-core-dropdown-option');
153
+ assert(option);
154
+ option.selected = true;
155
+ });
156
+ await aTimeout(0);
157
+ expect(spy.callCount).to.equal(0);
268
158
  });
@@ -1,9 +1,211 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import * as sinon from 'sinon';
2
3
  import { aTimeout, expect, fixture, html, oneEvent } from '@open-wc/testing';
4
+ import { sendKeys } from '@web/test-runner-commands';
3
5
  import GlideCoreDropdown from './dropdown.js';
4
6
  import GlideCoreDropdownOption from './dropdown.option.js';
5
7
  GlideCoreDropdown.shadowRootOptions.mode = 'open';
6
8
  GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
9
+ it('dispatches one "change" event when an option is selected via click', async () => {
10
+ const component = await fixture(html `<glide-core-dropdown
11
+ label="Label"
12
+ placeholder="Placeholder"
13
+ open
14
+ multiple
15
+ >
16
+ <glide-core-dropdown-option
17
+ label="One"
18
+ value="one"
19
+ ></glide-core-dropdown-option>
20
+
21
+ <glide-core-dropdown-option
22
+ label="Two"
23
+ value="two"
24
+ selected
25
+ ></glide-core-dropdown-option>
26
+ </glide-core-dropdown>`);
27
+ const spy = sinon.spy();
28
+ component.addEventListener('change', spy);
29
+ setTimeout(() => {
30
+ // Calling `click()` isn't sufficient because it simply sets
31
+ // `selected` and so isn't likely to produce a duplicate event,
32
+ // we assert against below. The checkbox, because it produces
33
+ // its own "change" event, is most likely where the duplicate would
34
+ // come from.
35
+ component
36
+ .querySelector('glide-core-dropdown-option')
37
+ ?.shadowRoot?.querySelector('[data-test="checkbox"]')
38
+ ?.click();
39
+ });
40
+ const event = await oneEvent(component, 'change');
41
+ expect(event instanceof Event).to.be.true;
42
+ expect(event.bubbles).to.be.true;
43
+ expect(spy.callCount).to.equal(1);
44
+ });
45
+ it('dispatches one "change" event when an option is selected via Enter', async () => {
46
+ const component = await fixture(html `<glide-core-dropdown
47
+ label="Label"
48
+ placeholder="Placeholder"
49
+ open
50
+ multiple
51
+ >
52
+ <glide-core-dropdown-option
53
+ label="One"
54
+ value="one"
55
+ ></glide-core-dropdown-option>
56
+
57
+ <glide-core-dropdown-option
58
+ label="Two"
59
+ value="two"
60
+ selected
61
+ ></glide-core-dropdown-option>
62
+ </glide-core-dropdown>`);
63
+ const spy = sinon.spy();
64
+ component.addEventListener('change', spy);
65
+ // Activate the first option before selecting it. The second option is
66
+ // currently active because it's selected.
67
+ component
68
+ .querySelector('glide-core-dropdown-option')
69
+ ?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
70
+ component.focus();
71
+ sendKeys({ press: 'Enter' });
72
+ const event = await oneEvent(component, 'change');
73
+ expect(event instanceof Event).to.be.true;
74
+ expect(event.bubbles).to.be.true;
75
+ expect(spy.callCount).to.equal(1);
76
+ });
77
+ it('dispatches one "change" event when an option is selected via Space', async () => {
78
+ const component = await fixture(html `<glide-core-dropdown
79
+ label="Label"
80
+ placeholder="Placeholder"
81
+ open
82
+ multiple
83
+ >
84
+ <glide-core-dropdown-option
85
+ label="One"
86
+ value="one"
87
+ ></glide-core-dropdown-option>
88
+
89
+ <glide-core-dropdown-option
90
+ label="Two"
91
+ value="two"
92
+ selected
93
+ ></glide-core-dropdown-option>
94
+ </glide-core-dropdown>`);
95
+ const spy = sinon.spy();
96
+ component.addEventListener('change', spy);
97
+ // Activate the first option before selecting it. The second option is
98
+ // currently active because it's selected.
99
+ component
100
+ .querySelector('glide-core-dropdown-option')
101
+ ?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
102
+ component.focus();
103
+ sendKeys({ press: ' ' });
104
+ const event = await oneEvent(component, 'change');
105
+ expect(event instanceof Event).to.be.true;
106
+ expect(event.bubbles).to.be.true;
107
+ expect(spy.callCount).to.equal(1);
108
+ });
109
+ it('dispatches one "input" event when an option is selected via click', async () => {
110
+ const component = await fixture(html `<glide-core-dropdown
111
+ label="Label"
112
+ placeholder="Placeholder"
113
+ open
114
+ multiple
115
+ >
116
+ <glide-core-dropdown-option
117
+ label="One"
118
+ value="one"
119
+ ></glide-core-dropdown-option>
120
+
121
+ <glide-core-dropdown-option
122
+ label="Two"
123
+ value="two"
124
+ selected
125
+ ></glide-core-dropdown-option>
126
+ </glide-core-dropdown>`);
127
+ const spy = sinon.spy();
128
+ component.addEventListener('input', spy);
129
+ setTimeout(() => {
130
+ // Calling `click()` isn't sufficient because it simply sets
131
+ // `selected` and so isn't likely to produce a duplicate event,
132
+ // we assert against below. The checkbox, because it produces
133
+ // its own "change" event, is most likely where the duplicate would
134
+ // come from.
135
+ component
136
+ .querySelector('glide-core-dropdown-option')
137
+ ?.shadowRoot?.querySelector('[data-test="checkbox"]')
138
+ ?.click();
139
+ });
140
+ const event = await oneEvent(component, 'input');
141
+ expect(event instanceof Event).to.be.true;
142
+ expect(event.bubbles).to.be.true;
143
+ expect(spy.callCount).to.equal(1);
144
+ });
145
+ it('dispatches one "input" event when an option is selected via Enter', async () => {
146
+ const component = await fixture(html `<glide-core-dropdown
147
+ label="Label"
148
+ placeholder="Placeholder"
149
+ open
150
+ multiple
151
+ >
152
+ <glide-core-dropdown-option
153
+ label="One"
154
+ value="one"
155
+ ></glide-core-dropdown-option>
156
+
157
+ <glide-core-dropdown-option
158
+ label="Two"
159
+ value="two"
160
+ selected
161
+ ></glide-core-dropdown-option>
162
+ </glide-core-dropdown>`);
163
+ const spy = sinon.spy();
164
+ component.addEventListener('input', spy);
165
+ // Activate the first option before selecting it. The second option is
166
+ // currently active because it's selected.
167
+ component
168
+ .querySelector('glide-core-dropdown-option')
169
+ ?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
170
+ component.focus();
171
+ sendKeys({ press: 'Enter' });
172
+ const event = await oneEvent(component, 'input');
173
+ expect(event instanceof Event).to.be.true;
174
+ expect(event.bubbles).to.be.true;
175
+ expect(spy.callCount).to.equal(1);
176
+ });
177
+ it('dispatches one "input" event when an option is selected via Space', async () => {
178
+ const component = await fixture(html `<glide-core-dropdown
179
+ label="Label"
180
+ placeholder="Placeholder"
181
+ open
182
+ multiple
183
+ >
184
+ <glide-core-dropdown-option
185
+ label="One"
186
+ value="one"
187
+ ></glide-core-dropdown-option>
188
+
189
+ <glide-core-dropdown-option
190
+ label="Two"
191
+ value="two"
192
+ selected
193
+ ></glide-core-dropdown-option>
194
+ </glide-core-dropdown>`);
195
+ const spy = sinon.spy();
196
+ component.addEventListener('input', spy);
197
+ // Activate the first option before selecting it. The second option is
198
+ // currently active because it's selected.
199
+ component
200
+ .querySelector('glide-core-dropdown-option')
201
+ ?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
202
+ component.focus();
203
+ sendKeys({ press: ' ' });
204
+ const event = await oneEvent(component, 'input');
205
+ expect(event instanceof Event).to.be.true;
206
+ expect(event.bubbles).to.be.true;
207
+ expect(spy.callCount).to.equal(1);
208
+ });
7
209
  it('dispatches one "change" event when Select All is clicked', async () => {
8
210
  const component = await fixture(html `<glide-core-dropdown
9
211
  label="Label"
@@ -31,7 +233,7 @@ it('dispatches one "change" event when Select All is clicked', async () => {
31
233
  ?.click();
32
234
  });
33
235
  await aTimeout(0);
34
- expect(spy.calledOnce).to.be.true;
236
+ expect(spy.callCount).to.equal(1);
35
237
  });
36
238
  it('dispatches one "input" event when Select All is clicked', async () => {
37
239
  const component = await fixture(html `<glide-core-dropdown
@@ -60,9 +262,9 @@ it('dispatches one "input" event when Select All is clicked', async () => {
60
262
  ?.click();
61
263
  });
62
264
  await aTimeout(0);
63
- expect(spy.calledOnce).to.be.true;
265
+ expect(spy.callCount).to.equal(1);
64
266
  });
65
- it('dispatches one "change" event when `value` is changed programmatically', async () => {
267
+ it('does not dispatch a "change" event when `value` is changed programmatically', async () => {
66
268
  const component = await fixture(html `<glide-core-dropdown
67
269
  label="Label"
68
270
  placeholder="Placeholder"
@@ -91,7 +293,7 @@ it('dispatches one "change" event when `value` is changed programmatically', asy
91
293
  component.value = ['one', 'two'];
92
294
  });
93
295
  await aTimeout(0);
94
- expect(spy.calledOnce).to.be.true;
296
+ expect(spy.callCount).to.equal(0);
95
297
  });
96
298
  it('continues to dispatch "change" events upon selection after `value` is changed programmatically', async () => {
97
299
  const component = await fixture(html `<glide-core-dropdown
@@ -126,7 +328,7 @@ it('continues to dispatch "change" events upon selection after `value` is change
126
328
  const event = await oneEvent(component, 'change');
127
329
  expect(event instanceof Event).to.be.true;
128
330
  });
129
- it('dispatches one "input" event when `value` is changed programmatically', async () => {
331
+ it('does not dispatch an "input" event when `value` is changed programmatically', async () => {
130
332
  const component = await fixture(html `<glide-core-dropdown
131
333
  label="Label"
132
334
  placeholder="Placeholder"
@@ -155,7 +357,7 @@ it('dispatches one "input" event when `value` is changed programmatically', asyn
155
357
  component.value = ['one', 'two'];
156
358
  });
157
359
  await aTimeout(0);
158
- expect(spy.calledOnce).to.be.true;
360
+ expect(spy.callCount).to.equal(0);
159
361
  });
160
362
  it('continues to dispatch "input" events upon selection after `value` is changed programmatically', async () => {
161
363
  const component = await fixture(html `<glide-core-dropdown
@@ -190,7 +392,7 @@ it('continues to dispatch "input" events upon selection after `value` is changed
190
392
  const event = await oneEvent(component, 'input');
191
393
  expect(event instanceof Event).to.be.true;
192
394
  });
193
- it('dispatches a "change" event when an option is selected after Select All is clicked', async () => {
395
+ it('dispatches one "change" event when an option is selected after Select All is clicked', async () => {
194
396
  const component = await fixture(html `<glide-core-dropdown
195
397
  label="Label"
196
398
  placeholder="Placeholder"
@@ -221,9 +423,9 @@ it('dispatches a "change" event when an option is selected after Select All is c
221
423
  component.querySelector('glide-core-dropdown-option')?.click();
222
424
  });
223
425
  await aTimeout(0);
224
- expect(spy.called).to.be.true;
426
+ expect(spy.callCount).to.equal(1);
225
427
  });
226
- it('dispatches an "input" event when an option is selected after Select All is clicked', async () => {
428
+ it('dispatches one "input" event when an option is selected after Select All is clicked', async () => {
227
429
  const component = await fixture(html `<glide-core-dropdown
228
430
  label="Label"
229
431
  placeholder="Placeholder"
@@ -254,5 +456,61 @@ it('dispatches an "input" event when an option is selected after Select All is c
254
456
  component.querySelector('glide-core-dropdown-option')?.click();
255
457
  });
256
458
  await aTimeout(0);
257
- expect(spy.called).to.be.true;
459
+ expect(spy.callCount).to.equal(1);
460
+ });
461
+ it('dispatches one "change" event when a tag is removed', async () => {
462
+ const component = await fixture(html `<glide-core-dropdown
463
+ label="Label"
464
+ placeholder="Placeholder"
465
+ open
466
+ multiple
467
+ >
468
+ <glide-core-dropdown-option
469
+ label="One"
470
+ value="one"
471
+ selected
472
+ ></glide-core-dropdown-option>
473
+
474
+ <glide-core-dropdown-option
475
+ label="Two"
476
+ value="two"
477
+ ></glide-core-dropdown-option>
478
+ </glide-core-dropdown>`);
479
+ setTimeout(() => {
480
+ component.shadowRoot
481
+ ?.querySelector('[data-test="tag"]')
482
+ ?.click();
483
+ });
484
+ const spy = sinon.spy();
485
+ component.addEventListener('change', spy);
486
+ await aTimeout(0);
487
+ expect(spy.callCount).to.equal(1);
488
+ });
489
+ it('dispatches one "input" event when a tag is removed', async () => {
490
+ const component = await fixture(html `<glide-core-dropdown
491
+ label="Label"
492
+ placeholder="Placeholder"
493
+ open
494
+ multiple
495
+ >
496
+ <glide-core-dropdown-option
497
+ label="One"
498
+ value="one"
499
+ selected
500
+ ></glide-core-dropdown-option>
501
+
502
+ <glide-core-dropdown-option
503
+ label="Two"
504
+ value="two"
505
+ ></glide-core-dropdown-option>
506
+ </glide-core-dropdown>`);
507
+ setTimeout(() => {
508
+ component.shadowRoot
509
+ ?.querySelector('[data-test="tag"]')
510
+ ?.click();
511
+ });
512
+ const spy = sinon.spy();
513
+ component.addEventListener('input', spy);
514
+ await aTimeout(0);
515
+ expect(spy.callCount).to.equal(1);
258
516
  });