@crowdstrike/glide-core 0.8.0 → 0.9.1

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 (181) hide show
  1. package/dist/accordion.d.ts +7 -3
  2. package/dist/button-group.button.d.ts +12 -16
  3. package/dist/button-group.button.js +1 -1
  4. package/dist/button-group.button.styles.js +76 -52
  5. package/dist/button-group.button.test.basics.d.ts +1 -1
  6. package/dist/button-group.button.test.basics.js +83 -147
  7. package/dist/button-group.button.test.events.js +8 -67
  8. package/dist/button-group.button.test.focus.js +13 -0
  9. package/dist/button-group.button.test.interactions.d.ts +1 -0
  10. package/dist/button-group.button.test.interactions.js +42 -0
  11. package/dist/button-group.d.ts +10 -10
  12. package/dist/button-group.js +1 -1
  13. package/dist/button-group.stories.d.ts +1 -5
  14. package/dist/button-group.styles.js +18 -6
  15. package/dist/button-group.test.basics.js +113 -234
  16. package/dist/button-group.test.events.js +210 -263
  17. package/dist/button-group.test.focus.d.ts +1 -0
  18. package/dist/button-group.test.focus.js +39 -0
  19. package/dist/button-group.test.interactions.d.ts +1 -0
  20. package/dist/button-group.test.interactions.js +91 -0
  21. package/dist/button.d.ts +3 -0
  22. package/dist/button.test.basics.js +1 -1
  23. package/dist/checkbox-group.d.ts +6 -2
  24. package/dist/checkbox-group.js +1 -1
  25. package/dist/checkbox-group.stories.d.ts +1 -1
  26. package/dist/checkbox-group.styles.js +1 -1
  27. package/dist/checkbox-group.test.basics.js +1 -1
  28. package/dist/checkbox-group.test.events.js +4 -4
  29. package/dist/checkbox-group.test.focus.js +4 -3
  30. package/dist/checkbox.d.ts +12 -5
  31. package/dist/checkbox.js +1 -1
  32. package/dist/checkbox.stories.d.ts +1 -1
  33. package/dist/checkbox.styles.js +10 -0
  34. package/dist/checkbox.test.basics.js +15 -6
  35. package/dist/checkbox.test.events.js +16 -8
  36. package/dist/checkbox.test.focus.js +3 -3
  37. package/dist/checkbox.test.form.js +1 -0
  38. package/dist/checkbox.test.interactions.js +123 -0
  39. package/dist/drawer.d.ts +5 -5
  40. package/dist/drawer.js +1 -1
  41. package/dist/drawer.stories.d.ts +0 -1
  42. package/dist/dropdown.d.ts +9 -6
  43. package/dist/dropdown.js +1 -1
  44. package/dist/dropdown.option.d.ts +6 -2
  45. package/dist/dropdown.option.js +1 -1
  46. package/dist/dropdown.option.styles.js +13 -0
  47. package/dist/dropdown.option.test.basics.js +6 -3
  48. package/dist/dropdown.option.test.events.js +1 -1
  49. package/dist/dropdown.option.test.focus.js +1 -1
  50. package/dist/dropdown.option.test.interactions.multiple.js +1 -54
  51. package/dist/dropdown.option.test.interactions.single.js +51 -9
  52. package/dist/dropdown.styles.js +20 -19
  53. package/dist/dropdown.test.basics.js +143 -2
  54. package/dist/dropdown.test.basics.multiple.js +5 -2
  55. package/dist/dropdown.test.events.filterable.js +74 -0
  56. package/dist/dropdown.test.events.js +49 -160
  57. package/dist/dropdown.test.events.multiple.js +265 -8
  58. package/dist/dropdown.test.events.single.js +199 -2
  59. package/dist/dropdown.test.focus.filterable.js +9 -5
  60. package/dist/dropdown.test.focus.js +1 -1
  61. package/dist/dropdown.test.focus.multiple.js +1 -1
  62. package/dist/dropdown.test.focus.single.js +1 -1
  63. package/dist/dropdown.test.interactions.filterable.js +68 -11
  64. package/dist/dropdown.test.interactions.js +94 -5
  65. package/dist/dropdown.test.interactions.multiple.js +202 -5
  66. package/dist/dropdown.test.interactions.single.js +68 -6
  67. package/dist/form-controls-layout.test.basics.js +1 -1
  68. package/dist/icon-button.d.ts +2 -0
  69. package/dist/icon-button.test.basics.js +1 -1
  70. package/dist/icons/checked.d.ts +1 -1
  71. package/dist/icons/checked.js +1 -1
  72. package/dist/icons/magnifying-glass.js +1 -1
  73. package/dist/input.d.ts +4 -9
  74. package/dist/input.js +1 -1
  75. package/dist/input.styles.js +7 -2
  76. package/dist/input.test.basics.js +19 -5
  77. package/dist/input.test.events.js +4 -4
  78. package/dist/input.test.focus.js +4 -4
  79. package/dist/input.test.translations.d.ts +1 -0
  80. package/dist/input.test.translations.js +38 -0
  81. package/dist/input.test.validity.js +133 -4
  82. package/dist/label.d.ts +1 -1
  83. package/dist/label.js +1 -1
  84. package/dist/label.styles.js +25 -13
  85. package/dist/label.test.basics.js +26 -24
  86. package/dist/library/expect-argument-error.js +1 -1
  87. package/dist/library/localize.d.ts +4 -1
  88. package/dist/menu.d.ts +3 -5
  89. package/dist/menu.js +1 -1
  90. package/dist/menu.options.test.basics.js +2 -2
  91. package/dist/menu.styles.js +1 -15
  92. package/dist/menu.test.basics.d.ts +1 -2
  93. package/dist/menu.test.basics.js +22 -6
  94. package/dist/menu.test.events.js +197 -7
  95. package/dist/menu.test.focus.d.ts +1 -0
  96. package/dist/menu.test.focus.js +13 -6
  97. package/dist/menu.test.interactions.js +214 -58
  98. package/dist/modal.icon-button.test.basics.js +1 -1
  99. package/dist/modal.js +1 -1
  100. package/dist/modal.stories.d.ts +1 -0
  101. package/dist/modal.styles.js +18 -13
  102. package/dist/modal.tertiary-icon.d.ts +0 -1
  103. package/dist/modal.tertiary-icon.js +1 -1
  104. package/dist/modal.tertiary-icon.test.basics.js +3 -3
  105. package/dist/modal.test.basics.js +1 -1
  106. package/dist/modal.test.events.js +10 -10
  107. package/dist/radio-group.d.ts +4 -3
  108. package/dist/radio-group.js +1 -1
  109. package/dist/radio-group.stories.d.ts +1 -1
  110. package/dist/radio-group.styles.js +1 -1
  111. package/dist/radio-group.test.focus.js +3 -3
  112. package/dist/radio.d.ts +2 -2
  113. package/dist/radio.js +1 -1
  114. package/dist/radio.styles.js +33 -0
  115. package/dist/split-container.d.ts +1 -1
  116. package/dist/split-container.test.basics.js +4 -0
  117. package/dist/split-link.test.interactions.js +1 -1
  118. package/dist/status-indicator.d.ts +1 -1
  119. package/dist/styles/variables.css +1 -1
  120. package/dist/tab.d.ts +1 -1
  121. package/dist/tab.group.js +1 -1
  122. package/dist/tab.group.test.basics.js +1 -1
  123. package/dist/tab.group.test.interactions.js +198 -2
  124. package/dist/tab.js +1 -1
  125. package/dist/tab.panel.d.ts +1 -0
  126. package/dist/tab.panel.js +1 -1
  127. package/dist/tab.panel.styles.js +11 -1
  128. package/dist/tabs.stories.d.ts +1 -0
  129. package/dist/tag.d.ts +3 -6
  130. package/dist/tag.test.basics.js +2 -2
  131. package/dist/textarea.d.ts +4 -4
  132. package/dist/textarea.js +2 -2
  133. package/dist/textarea.stories.d.ts +3 -4
  134. package/dist/textarea.styles.js +14 -3
  135. package/dist/textarea.test.basics.js +80 -44
  136. package/dist/textarea.test.events.js +56 -41
  137. package/dist/textarea.test.translations.d.ts +1 -0
  138. package/dist/textarea.test.translations.js +34 -0
  139. package/dist/textarea.test.validity.js +104 -20
  140. package/dist/toasts.js +1 -1
  141. package/dist/toasts.styles.js +8 -1
  142. package/dist/toasts.test.basics.js +20 -0
  143. package/dist/toggle.d.ts +3 -3
  144. package/dist/toggle.js +1 -1
  145. package/dist/toggle.stories.d.ts +1 -1
  146. package/dist/toggle.test.focus.js +1 -1
  147. package/dist/toggle.test.interactions.d.ts +1 -0
  148. package/dist/{toggle.test.states.js → toggle.test.interactions.js} +26 -0
  149. package/dist/tooltip.d.ts +9 -7
  150. package/dist/tooltip.js +1 -1
  151. package/dist/tooltip.styles.js +90 -25
  152. package/dist/tooltip.test.basics.js +38 -3
  153. package/dist/tooltip.test.interactions.js +136 -34
  154. package/dist/translations/en.js +1 -1
  155. package/dist/translations/fr.js +1 -1
  156. package/dist/translations/ja.js +1 -1
  157. package/dist/tree.d.ts +1 -2
  158. package/dist/tree.item.d.ts +1 -5
  159. package/dist/tree.item.icon-button.d.ts +1 -0
  160. package/dist/tree.item.icon-button.js +1 -1
  161. package/dist/tree.item.icon-button.test.basics.js +9 -0
  162. package/dist/tree.item.js +1 -1
  163. package/dist/tree.item.menu.d.ts +2 -1
  164. package/dist/tree.item.menu.js +1 -1
  165. package/dist/tree.item.menu.test.basics.js +15 -0
  166. package/dist/tree.item.styles.js +2 -0
  167. package/dist/tree.item.test.basics.d.ts +2 -1
  168. package/dist/tree.item.test.basics.js +46 -4
  169. package/dist/tree.js +1 -1
  170. package/dist/tree.test.basics.js +1 -1
  171. package/dist/tree.test.focus.js +91 -4
  172. package/package.json +3 -4
  173. package/dist/checkbox.test.states.js +0 -63
  174. package/dist/drawer.test.floating-components.d.ts +0 -1
  175. package/dist/drawer.test.floating-components.js +0 -52
  176. package/dist/library/set-containing-block.d.ts +0 -15
  177. package/dist/library/set-containing-block.js +0 -1
  178. package/dist/modal.test.floating-components.js +0 -63
  179. /package/dist/{checkbox.test.states.d.ts → button-group.button.test.focus.d.ts} +0 -0
  180. /package/dist/{modal.test.floating-components.d.ts → checkbox.test.interactions.d.ts} +0 -0
  181. /package/dist/{toggle.test.states.d.ts → dropdown.test.events.filterable.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-expressions */
2
- import { assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
2
+ import { aTimeout, assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
3
3
  import { sendKeys } from '@web/test-runner-commands';
4
4
  import GlideCoreDropdown from './dropdown.js';
5
5
  import GlideCoreDropdownOption from './dropdown.option.js';
@@ -72,7 +72,11 @@ it('opens on click', async () => {
72
72
  component.shadowRoot
73
73
  ?.querySelector('[data-test="input"]')
74
74
  ?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
75
+ // Wait for it to open.
76
+ await aTimeout(0);
77
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
75
78
  expect(component.open).to.be.true;
79
+ expect(options?.checkVisibility()).to.be.true;
76
80
  });
77
81
  it('filters', async () => {
78
82
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
@@ -85,10 +89,12 @@ it('filters', async () => {
85
89
  ].filter(({ hidden }) => !hidden);
86
90
  expect(options.length).to.equal(1);
87
91
  });
88
- it('clears the filter term when an option is selected', async () => {
92
+ it('unfilters when an option is selected via click', async () => {
89
93
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
90
94
  ${defaultSlot}
91
95
  </glide-core-dropdown>`);
96
+ // Wait for it to open.
97
+ await aTimeout(0);
92
98
  component.focus();
93
99
  await sendKeys({ type: ' one ' });
94
100
  const option = [
@@ -102,6 +108,20 @@ it('clears the filter term when an option is selected', async () => {
102
108
  expect(input?.value).to.equal('');
103
109
  expect(options.length).to.equal(11);
104
110
  });
111
+ it('unfilters when an option is selected via Enter', async () => {
112
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
113
+ ${defaultSlot}
114
+ </glide-core-dropdown>`);
115
+ component.focus();
116
+ await sendKeys({ type: ' one ' });
117
+ await sendKeys({ press: 'Enter' });
118
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
119
+ const options = [
120
+ ...component.querySelectorAll('glide-core-dropdown-option'),
121
+ ].filter(({ hidden }) => !hidden);
122
+ expect(input?.value).to.equal('');
123
+ expect(options.length).to.equal(11);
124
+ });
105
125
  it('shows the magnifying glass icon when there is a filter term', async () => {
106
126
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
107
127
  ${defaultSlot}
@@ -119,9 +139,11 @@ it('hides the magnifying glass icon when there is no filter term', async () => {
119
139
  expect(icon?.checkVisibility()).to.be.not.ok;
120
140
  });
121
141
  it('hides the magnifying glass icon when an option is selected', async () => {
122
- const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
142
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
123
143
  ${defaultSlot}
124
144
  </glide-core-dropdown>`);
145
+ // Wait for it to open.
146
+ await aTimeout(0);
125
147
  component.focus();
126
148
  await sendKeys({ type: ' one ' });
127
149
  const option = [
@@ -147,10 +169,14 @@ it('hides the options when all of them are filtered out', async () => {
147
169
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
148
170
  ${defaultSlot}
149
171
  </glide-core-dropdown>`);
172
+ // Wait for it to open.
173
+ await aTimeout(0);
150
174
  component.focus();
151
- await sendKeys({ type: 'twelve' });
175
+ await sendKeys({ type: 'fifty' });
176
+ // Wait for it to close.
177
+ await aTimeout(0);
152
178
  const options = component.shadowRoot?.querySelector('[data-test="options"]');
153
- expect(options?.dataset.testVisible).to.equal('false');
179
+ expect(options?.checkVisibility()).to.be.false;
154
180
  });
155
181
  it('hides Select All when filtering', async () => {
156
182
  const component = await fixture(html `<glide-core-dropdown
@@ -194,6 +220,20 @@ it('updates `value` when an option `value` is changed programmatically', async (
194
220
  option.value = 'two';
195
221
  expect(component.value).to.deep.equal(['two']);
196
222
  });
223
+ it('does not select options on Space', async () => {
224
+ const component = await fixture(html `<glide-core-dropdown
225
+ label="Label"
226
+ placeholder="Placeholder"
227
+ multiple
228
+ open
229
+ >
230
+ ${defaultSlot}
231
+ </glide-core-dropdown>`);
232
+ const options = component.querySelectorAll('glide-core-dropdown-option');
233
+ options[0]?.focus();
234
+ await sendKeys({ press: ' ' });
235
+ expect(options[0]?.selected).to.be.false;
236
+ });
197
237
  it('deselects options on Backspace', async () => {
198
238
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
199
239
  ${defaultSlot}
@@ -244,6 +284,8 @@ it('sets `aria-activedescendant` on ArrowDown', async () => {
244
284
  >
245
285
  ${defaultSlot}
246
286
  </glide-core-dropdown>`);
287
+ // Wait for it to open.
288
+ await aTimeout(0);
247
289
  const options = component.querySelectorAll('glide-core-dropdown-option');
248
290
  options[0]?.focus();
249
291
  await sendKeys({ press: 'ArrowDown' });
@@ -259,6 +301,8 @@ it('sets `aria-activedescendant` on ArrowUp', async () => {
259
301
  >
260
302
  ${defaultSlot}
261
303
  </glide-core-dropdown>`);
304
+ // Wait for it to open.
305
+ await aTimeout(0);
262
306
  const options = component.querySelectorAll('glide-core-dropdown-option');
263
307
  options[1]?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
264
308
  options[1]?.focus();
@@ -275,6 +319,8 @@ it('sets `aria-activedescendant` on Home', async () => {
275
319
  >
276
320
  ${defaultSlot}
277
321
  </glide-core-dropdown>`);
322
+ // Wait for it to open.
323
+ await aTimeout(0);
278
324
  const options = component.querySelectorAll('glide-core-dropdown-option');
279
325
  options[1]?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
280
326
  options[1].focus();
@@ -291,6 +337,8 @@ it('sets `aria-activedescendant` on PageUp', async () => {
291
337
  >
292
338
  ${defaultSlot}
293
339
  </glide-core-dropdown>`);
340
+ // Wait for it to open.
341
+ await aTimeout(0);
294
342
  const options = component.querySelectorAll('glide-core-dropdown-option');
295
343
  options[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
296
344
  options[1].focus();
@@ -298,7 +346,7 @@ it('sets `aria-activedescendant` on PageUp', async () => {
298
346
  const input = component.shadowRoot?.querySelector('[data-test="input"]');
299
347
  expect(input?.getAttribute('aria-activedescendant')).to.equal(options[0].id);
300
348
  });
301
- it('sets `aria-activedescendant` on ArrowUp + Meta', async () => {
349
+ it('sets `aria-activedescendant` on Meta + ArrowUp', async () => {
302
350
  const component = await fixture(html `<glide-core-dropdown
303
351
  label="Label"
304
352
  placeholder="Placeholder"
@@ -307,9 +355,11 @@ it('sets `aria-activedescendant` on ArrowUp + Meta', async () => {
307
355
  >
308
356
  ${defaultSlot}
309
357
  </glide-core-dropdown>`);
358
+ // Wait for it to open.
359
+ await aTimeout(0);
360
+ component.focus();
310
361
  const options = component.querySelectorAll('glide-core-dropdown-option');
311
362
  options[1]?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
312
- options[1].focus();
313
363
  await sendKeys({ down: 'Meta' });
314
364
  await sendKeys({ press: 'ArrowUp' });
315
365
  await sendKeys({ up: 'Meta' });
@@ -327,7 +377,8 @@ it('sets `aria-activedescendant` on open via click', async () => {
327
377
  component.shadowRoot
328
378
  ?.querySelector('[data-test="button"]')
329
379
  ?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
330
- await elementUpdated(component);
380
+ // Wait for it to open.
381
+ await aTimeout(0);
331
382
  const input = component.shadowRoot?.querySelector('[data-test="input"]');
332
383
  const option = component.querySelector('glide-core-dropdown-option');
333
384
  expect(input?.getAttribute('aria-activedescendant')).to.equal(option?.id);
@@ -351,11 +402,13 @@ it('sets `aria-activedescendant` on End', async () => {
351
402
  >
352
403
  ${defaultSlot}
353
404
  </glide-core-dropdown>`);
405
+ // Wait for it to open.
406
+ await aTimeout(0);
407
+ component.focus();
354
408
  // Made into an array because the linter forces `at(-1)` instead of
355
409
  // `[options.length - 1]` but doesn't take into account that `options`
356
410
  // isn't an actual array and doesn't have an `at()` method.
357
411
  const options = [...component.querySelectorAll('glide-core-dropdown-option')];
358
- options[0]?.focus();
359
412
  await sendKeys({ press: 'End' });
360
413
  const input = component.shadowRoot?.querySelector('[data-test="input"]');
361
414
  expect(input?.getAttribute('aria-activedescendant')).to.equal(options.at(-1)?.id);
@@ -369,11 +422,13 @@ it('sets `aria-activedescendant` on PageDown', async () => {
369
422
  >
370
423
  ${defaultSlot}
371
424
  </glide-core-dropdown>`);
425
+ // Wait for it to open.
426
+ await aTimeout(0);
427
+ component.focus();
372
428
  // Made into an array because the linter forces `at(-1)` instead of
373
429
  // `[options.length - 1]` but doesn't take into account that `options`
374
430
  // isn't an actual array and doesn't have an `at()` method.
375
431
  const options = [...component.querySelectorAll('glide-core-dropdown-option')];
376
- options[0]?.focus();
377
432
  await sendKeys({ press: 'PageDown' });
378
433
  const input = component.shadowRoot?.querySelector('[data-test="input"]');
379
434
  expect(input?.getAttribute('aria-activedescendant')).to.equal(options.at(-1)?.id);
@@ -387,11 +442,13 @@ it('sets `aria-activedescendant` on Meta + ArrowDown', async () => {
387
442
  >
388
443
  ${defaultSlot}
389
444
  </glide-core-dropdown>`);
445
+ // Wait for it to open.
446
+ await aTimeout(0);
447
+ component.focus();
390
448
  // Spread into an array because the linter forces `at(-1)` instead of
391
449
  // `[options.length - 1]` but doesn't take into account that `options`
392
450
  // isn't an actual array and doesn't have an `at()` method.
393
451
  const options = [...component.querySelectorAll('glide-core-dropdown-option')];
394
- options[0]?.focus();
395
452
  await sendKeys({ down: 'Meta' });
396
453
  await sendKeys({ press: 'ArrowDown' });
397
454
  await sendKeys({ up: 'Meta' });
@@ -1,10 +1,22 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-expressions */
2
- import { assert, expect, fixture, html } from '@open-wc/testing';
2
+ import { aTimeout, assert, expect, fixture, html } from '@open-wc/testing';
3
3
  import { sendKeys, sendMouse } from '@web/test-runner-commands';
4
4
  import GlideCoreDropdown from './dropdown.js';
5
5
  import GlideCoreDropdownOption from './dropdown.option.js';
6
6
  GlideCoreDropdown.shadowRootOptions.mode = 'open';
7
7
  GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
8
+ it('opens when opened programmatically', async () => {
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>`);
15
+ component.open = true;
16
+ await aTimeout(0);
17
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
18
+ expect(options?.checkVisibility()).to.be.true;
19
+ });
8
20
  it('opens on ArrowUp', async () => {
9
21
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
10
22
  <glide-core-dropdown-option
@@ -14,9 +26,9 @@ it('opens on ArrowUp', async () => {
14
26
  </glide-core-dropdown>`);
15
27
  component.focus();
16
28
  await sendKeys({ press: 'ArrowUp' });
17
- const option = component.querySelector('glide-core-dropdown-option');
29
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
18
30
  expect(component.open).to.be.true;
19
- expect(option?.privateActive).to.be.true;
31
+ expect(options?.checkVisibility()).to.be.true;
20
32
  });
21
33
  it('does not open on ArrowUp when `disabled`', async () => {
22
34
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" disabled>
@@ -27,7 +39,9 @@ it('does not open on ArrowUp when `disabled`', async () => {
27
39
  </glide-core-dropdown>`);
28
40
  component.focus();
29
41
  await sendKeys({ press: 'ArrowUp' });
42
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
30
43
  expect(component.open).to.be.false;
44
+ expect(options?.checkVisibility()).to.be.false;
31
45
  });
32
46
  it('does not open on ArrowUp when `readonly`', async () => {
33
47
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" readonly>
@@ -38,7 +52,9 @@ it('does not open on ArrowUp when `readonly`', async () => {
38
52
  </glide-core-dropdown>`);
39
53
  component.focus();
40
54
  await sendKeys({ press: 'ArrowUp' });
55
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
41
56
  expect(component.open).to.be.false;
57
+ expect(options?.checkVisibility()).to.be.false;
42
58
  });
43
59
  it('opens on ArrowDown', async () => {
44
60
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
@@ -54,9 +70,9 @@ it('opens on ArrowDown', async () => {
54
70
  </glide-core-dropdown>`);
55
71
  component.focus();
56
72
  await sendKeys({ press: 'ArrowDown' });
57
- const option = component.querySelector('glide-core-dropdown-option');
73
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
58
74
  expect(component.open).to.be.true;
59
- expect(option?.privateActive).to.be.true;
75
+ expect(options?.checkVisibility()).to.be.true;
60
76
  });
61
77
  it('does not open on ArrowDown when `disabled`', async () => {
62
78
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" disabled>
@@ -72,7 +88,9 @@ it('does not open on ArrowDown when `disabled`', async () => {
72
88
  </glide-core-dropdown>`);
73
89
  component.focus();
74
90
  await sendKeys({ press: 'ArrowDown' });
91
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
75
92
  expect(component.open).to.be.false;
93
+ expect(options?.checkVisibility()).to.be.false;
76
94
  });
77
95
  it('does not open on ArrowDown when `readonly`', async () => {
78
96
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" readonly>
@@ -88,7 +106,9 @@ it('does not open on ArrowDown when `readonly`', async () => {
88
106
  </glide-core-dropdown>`);
89
107
  component.focus();
90
108
  await sendKeys({ press: 'ArrowDown' });
109
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
91
110
  expect(component.open).to.be.false;
111
+ expect(options?.checkVisibility()).to.be.false;
92
112
  });
93
113
  it('opens on Space', async () => {
94
114
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
@@ -99,7 +119,9 @@ it('opens on Space', async () => {
99
119
  </glide-core-dropdown>`);
100
120
  component.focus();
101
121
  await sendKeys({ press: ' ' });
122
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
102
123
  expect(component.open).to.be.true;
124
+ expect(options?.checkVisibility()).to.be.true;
103
125
  });
104
126
  it('does not open on Space when `disabled`', async () => {
105
127
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" disabled>
@@ -110,7 +132,9 @@ it('does not open on Space when `disabled`', async () => {
110
132
  </glide-core-dropdown>`);
111
133
  component.focus();
112
134
  await sendKeys({ press: ' ' });
135
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
113
136
  expect(component.open).to.be.false;
137
+ expect(options?.checkVisibility()).to.be.false;
114
138
  });
115
139
  it('does not open on Space when `readonly`', async () => {
116
140
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" readonly>
@@ -121,7 +145,9 @@ it('does not open on Space when `readonly`', async () => {
121
145
  </glide-core-dropdown>`);
122
146
  component.focus();
123
147
  await sendKeys({ press: ' ' });
148
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
124
149
  expect(component.open).to.be.false;
150
+ expect(options?.checkVisibility()).to.be.false;
125
151
  });
126
152
  // See the `document` click listener comment in `dropdown.ts` for an explanation.
127
153
  it('opens when opened programmatically via the click handler of another element', async () => {
@@ -136,7 +162,11 @@ it('opens when opened programmatically via the click handler of another element'
136
162
  button.addEventListener('click', () => (component.open = true));
137
163
  div.append(button);
138
164
  button.click();
165
+ // Wait for it to open.
166
+ await aTimeout(0);
167
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
139
168
  expect(component.open).to.be.true;
169
+ expect(options?.checkVisibility()).to.be.true;
140
170
  });
141
171
  it('closes when something outside of it is clicked', async () => {
142
172
  const component = await fixture(html `<glide-core-dropdown
@@ -181,6 +211,49 @@ it('closes on Escape', async () => {
181
211
  await sendKeys({ press: 'Escape' });
182
212
  expect(component.open).to.be.false;
183
213
  });
214
+ it('opens when open and enabled programmatically', async () => {
215
+ const component = await fixture(html `<glide-core-dropdown
216
+ label="Label"
217
+ placeholder="Placeholder"
218
+ open
219
+ disabled
220
+ >
221
+ <glide-core-dropdown-option
222
+ label="One"
223
+ value="one"
224
+ selected
225
+ ></glide-core-dropdown-option>
226
+
227
+ <glide-core-dropdown-option
228
+ label="Two"
229
+ value="two"
230
+ ></glide-core-dropdown-option>
231
+ </glide-core-dropdown>`);
232
+ component.disabled = false;
233
+ // Wait for it to open.
234
+ await aTimeout(0);
235
+ const options = component?.shadowRoot?.querySelector('[data-test="options"]');
236
+ expect(options?.checkVisibility()).to.be.true;
237
+ });
238
+ it('closes when open and disabled programmatically', async () => {
239
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
240
+ <glide-core-dropdown-option
241
+ label="One"
242
+ value="one"
243
+ selected
244
+ ></glide-core-dropdown-option>
245
+
246
+ <glide-core-dropdown-option
247
+ label="Two"
248
+ value="two"
249
+ ></glide-core-dropdown-option>
250
+ </glide-core-dropdown>`);
251
+ // Wait for it to open.
252
+ await aTimeout(0);
253
+ component.disabled = true;
254
+ const options = component?.shadowRoot?.querySelector('[data-test="options"]');
255
+ expect(options?.checkVisibility()).to.be.false;
256
+ });
184
257
  it('activates an option on "mouseover"', async () => {
185
258
  const component = await fixture(html `<glide-core-dropdown open>
186
259
  <glide-core-dropdown-option
@@ -209,6 +282,8 @@ it('activates the next option on ArrowDown', async () => {
209
282
  value="two"
210
283
  ></glide-core-dropdown-option>
211
284
  </glide-core-dropdown>`);
285
+ // Wait for it to open.
286
+ await aTimeout(0);
212
287
  const options = component.querySelectorAll('glide-core-dropdown-option');
213
288
  options[0]?.focus();
214
289
  await sendKeys({ press: 'ArrowDown' });
@@ -227,6 +302,8 @@ it('activates the previous option on ArrowUp', async () => {
227
302
  value="two"
228
303
  ></glide-core-dropdown-option>
229
304
  </glide-core-dropdown>`);
305
+ // Wait for it to open.
306
+ await aTimeout(0);
230
307
  const options = component.querySelectorAll('glide-core-dropdown-option');
231
308
  options[1]?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
232
309
  options[1]?.focus();
@@ -247,6 +324,8 @@ it('activates the first option on Home', async () => {
247
324
  value="two"
248
325
  ></glide-core-dropdown-option>
249
326
  </glide-core-dropdown>`);
327
+ // Wait for it to open.
328
+ await aTimeout(0);
250
329
  const options = component.querySelectorAll('glide-core-dropdown-option');
251
330
  options[1]?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
252
331
  expect(options[1].privateActive).to.be.true;
@@ -267,6 +346,8 @@ it('activates the first option on PageUp', async () => {
267
346
  value="two"
268
347
  ></glide-core-dropdown-option>
269
348
  </glide-core-dropdown>`);
349
+ // Wait for it to open.
350
+ await aTimeout(0);
270
351
  const options = component.querySelectorAll('glide-core-dropdown-option');
271
352
  options[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
272
353
  options[1].focus();
@@ -287,6 +368,8 @@ it('activates the first option on ArrowUp + Meta', async () => {
287
368
  value="two"
288
369
  ></glide-core-dropdown-option>
289
370
  </glide-core-dropdown>`);
371
+ // Wait for it to open.
372
+ await aTimeout(0);
290
373
  const options = component.querySelectorAll('glide-core-dropdown-option');
291
374
  options[1]?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
292
375
  expect(options[1]?.privateActive).to.be.true;
@@ -309,6 +392,8 @@ it('activates the last option on End', async () => {
309
392
  value="two"
310
393
  ></glide-core-dropdown-option>
311
394
  </glide-core-dropdown>`);
395
+ // Wait for it to open.
396
+ await aTimeout(0);
312
397
  const options = component.querySelectorAll('glide-core-dropdown-option');
313
398
  options[0]?.focus();
314
399
  await sendKeys({ press: 'End' });
@@ -327,6 +412,8 @@ it('activates the last option on PageDown', async () => {
327
412
  value="two"
328
413
  ></glide-core-dropdown-option>
329
414
  </glide-core-dropdown>`);
415
+ // Wait for it to open.
416
+ await aTimeout(0);
330
417
  const options = component.querySelectorAll('glide-core-dropdown-option');
331
418
  options[0]?.focus();
332
419
  await sendKeys({ press: 'PageDown' });
@@ -345,6 +432,8 @@ it('activates the last option on Meta + ArrowDown', async () => {
345
432
  value="two"
346
433
  ></glide-core-dropdown-option>
347
434
  </glide-core-dropdown>`);
435
+ // Wait for it to open.
436
+ await aTimeout(0);
348
437
  const options = component.querySelectorAll('glide-core-dropdown-option');
349
438
  options[0]?.focus();
350
439
  await sendKeys({ down: 'Meta' });