@crowdstrike/glide-core 0.5.1 → 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 -4
  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 +0 -2
  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 +25 -6
  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 +6 -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 +18 -16
  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,26 @@
1
+ import { expect, fixture, html } from '@open-wc/testing';
2
+ import GlideCoreDropdownOption from './dropdown.option.js';
3
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
4
+ it('is selected when initially selected', async () => {
5
+ const component = await fixture(html `<glide-core-dropdown-option
6
+ label="Label"
7
+ value="value"
8
+ private-multiple
9
+ selected
10
+ ></glide-core-dropdown-option>`);
11
+ const checkbox = component.shadowRoot?.querySelector('glide-core-checkbox');
12
+ expect(component.selected).to.be.true;
13
+ expect(component.ariaSelected).to.equal('true');
14
+ expect(checkbox?.checked).to.be.true;
15
+ });
16
+ it('is deselected when initially deselected', async () => {
17
+ const component = await fixture(html `<glide-core-dropdown-option
18
+ label="Label"
19
+ value="value"
20
+ private-multiple
21
+ ></glide-core-dropdown-option>`);
22
+ const checkbox = component.shadowRoot?.querySelector('glide-core-checkbox');
23
+ expect(component.selected).to.be.false;
24
+ expect(component.ariaSelected).to.equal('false');
25
+ expect(checkbox?.checked).to.be.false;
26
+ });
@@ -0,0 +1,20 @@
1
+ import { expect, fixture, html } from '@open-wc/testing';
2
+ import GlideCoreDropdownOption from './dropdown.option.js';
3
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
4
+ it('is selected when initially selected', async () => {
5
+ const component = await fixture(html `<glide-core-dropdown-option
6
+ label="Label"
7
+ value="value"
8
+ selected
9
+ ></glide-core-dropdown-option>`);
10
+ expect(component.selected).to.be.true;
11
+ expect(component.ariaSelected).to.equal('true');
12
+ });
13
+ it('is deselected when initially deselected', async () => {
14
+ const component = await fixture(html `<glide-core-dropdown-option
15
+ label="Label"
16
+ value="value"
17
+ ></glide-core-dropdown-option>`);
18
+ expect(component.selected).to.be.false;
19
+ expect(component.ariaSelected).to.equal('false');
20
+ });
@@ -0,0 +1,27 @@
1
+ import { expect, fixture, html, oneEvent } from '@open-wc/testing';
2
+ import GlideCoreDropdownOption from './dropdown.option.js';
3
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
4
+ it('dispatches a "private-selected-change" event', async () => {
5
+ const component = await fixture(html `<glide-core-dropdown-option
6
+ label="Label"
7
+ value="value"
8
+ ></glide-core-dropdown-option>`);
9
+ setTimeout(() => {
10
+ component.click();
11
+ });
12
+ const event = await oneEvent(component, 'private-selected-change');
13
+ expect(event instanceof Event).to.be.true;
14
+ expect(event.bubbles).to.be.true;
15
+ });
16
+ it('dispatches a "private-value-change" event', async () => {
17
+ const component = await fixture(html `<glide-core-dropdown-option
18
+ label="Label"
19
+ value="value"
20
+ ></glide-core-dropdown-option>`);
21
+ setTimeout(() => {
22
+ component.value = '';
23
+ });
24
+ const event = await oneEvent(component, 'private-value-change');
25
+ expect(event instanceof Event).to.be.true;
26
+ expect(event.bubbles).to.be.true;
27
+ });
@@ -0,0 +1,11 @@
1
+ import { expect, fixture, html } from '@open-wc/testing';
2
+ import GlideCoreDropdownOption from './dropdown.option.js';
3
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
4
+ it('focuses itself when `focus` is called', async () => {
5
+ const component = await fixture(html `<glide-core-dropdown-option
6
+ label="Label"
7
+ value="value"
8
+ ></glide-core-dropdown-option>`);
9
+ component.focus();
10
+ expect(document.activeElement).to.equal(component);
11
+ });
@@ -0,0 +1,87 @@
1
+ import { elementUpdated, expect, fixture, html, waitUntil, } from '@open-wc/testing';
2
+ import GlideCoreCheckbox from './checkbox.js';
3
+ import GlideCoreDropdownOption from './dropdown.option.js';
4
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
5
+ it('is selected on click', async () => {
6
+ const component = await fixture(html `<glide-core-dropdown-option
7
+ label="Label"
8
+ private-multiple
9
+ ></glide-core-dropdown-option>`);
10
+ component.click();
11
+ await elementUpdated(component);
12
+ expect(component.selected).to.be.true;
13
+ expect(component.ariaSelected).to.equal('true');
14
+ });
15
+ it('is deselected on click', async () => {
16
+ const component = await fixture(html `<glide-core-dropdown-option
17
+ label="Label"
18
+ private-multiple
19
+ selected
20
+ ></glide-core-dropdown-option>`);
21
+ component.click();
22
+ await elementUpdated(component);
23
+ expect(component.selected).to.be.false;
24
+ expect(component.ariaSelected).to.equal('false');
25
+ });
26
+ it('is selected on click when the checkbox itself is clicked', async () => {
27
+ const component = await fixture(html `<glide-core-dropdown-option
28
+ label="Label"
29
+ private-multiple
30
+ ></glide-core-dropdown-option>`);
31
+ // Checkbox has its own lifecycle. Wait until it's ready.
32
+ waitUntil(() => {
33
+ return (component.shadowRoot?.querySelector('[data-test="checkbox"]') instanceof
34
+ GlideCoreCheckbox);
35
+ });
36
+ const checkbox = component.shadowRoot?.querySelector('[data-test="checkbox"]');
37
+ checkbox?.click();
38
+ await elementUpdated(component);
39
+ expect(component.selected).to.be.true;
40
+ expect(component.ariaSelected).to.equal('true');
41
+ expect(checkbox?.checked).to.be.true;
42
+ });
43
+ it('is deselected on click when the checkbox itself is clicked', async () => {
44
+ const component = await fixture(html `<glide-core-dropdown-option
45
+ label="Label"
46
+ private-multiple
47
+ selected
48
+ ></glide-core-dropdown-option>`);
49
+ // Checkbox has its own lifecycle. Wait until it's ready.
50
+ waitUntil(() => {
51
+ return (component.shadowRoot?.querySelector('[data-test="checkbox"]') instanceof
52
+ GlideCoreCheckbox);
53
+ });
54
+ const checkbox = component.shadowRoot?.querySelector('[data-test="checkbox"]');
55
+ checkbox?.click();
56
+ await elementUpdated(component);
57
+ expect(component.selected).to.be.false;
58
+ expect(component.ariaSelected).to.equal('false');
59
+ expect(checkbox?.checked).to.be.false;
60
+ });
61
+ it('is selected when programmatically selected', async () => {
62
+ const component = await fixture(html `<glide-core-dropdown-option
63
+ label="Label"
64
+ value="value"
65
+ private-multiple
66
+ ></glide-core-dropdown-option>`);
67
+ component.selected = true;
68
+ await elementUpdated(component);
69
+ const checkbox = component.shadowRoot?.querySelector('[data-test="checkbox"]');
70
+ expect(component.selected).to.be.true;
71
+ expect(component.ariaSelected).to.equal('true');
72
+ expect(checkbox?.checked).to.be.true;
73
+ });
74
+ it('is deselected when programmatically deselected', async () => {
75
+ const component = await fixture(html `<glide-core-dropdown-option
76
+ label="Label"
77
+ value="value"
78
+ private-multiple
79
+ selected
80
+ ></glide-core-dropdown-option>`);
81
+ component.selected = false;
82
+ await elementUpdated(component);
83
+ const checkbox = component.shadowRoot?.querySelector('[data-test="checkbox"]');
84
+ expect(component.selected).to.be.false;
85
+ expect(component.ariaSelected).to.equal('false');
86
+ expect(checkbox?.checked).to.be.false;
87
+ });
@@ -0,0 +1,22 @@
1
+ import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
2
+ import GlideCoreDropdownOption from './dropdown.option.js';
3
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
4
+ it('is selected on click', async () => {
5
+ const component = await fixture(html `<glide-core-dropdown-option
6
+ label="Label"
7
+ ></glide-core-dropdown-option>`);
8
+ component.click();
9
+ await elementUpdated(component);
10
+ expect(component.selected).to.be.true;
11
+ expect(component.ariaSelected).to.equal('true');
12
+ });
13
+ it('is selected when programmatically selected', async () => {
14
+ const component = await fixture(html `<glide-core-dropdown-option
15
+ label="Label"
16
+ value="value"
17
+ ></glide-core-dropdown-option>`);
18
+ component.selected = true;
19
+ await elementUpdated(component);
20
+ expect(component.selected).to.be.true;
21
+ expect(component.ariaSelected).to.equal('true');
22
+ });
@@ -1,10 +1,14 @@
1
- "use strict";import{css as e}from"lit";import i from"./styles/focus-outline.js";export default[e`
1
+ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import visuallyHidden from"./styles/visually-hidden.js";export default[css`
2
2
  .component {
3
3
  --min-inline-size: 9.375rem;
4
4
 
5
5
  font-family: var(--glide-core-font-sans);
6
6
  }
7
7
 
8
+ .selected-option-labels {
9
+ ${visuallyHidden};
10
+ }
11
+
8
12
  .dropdown-and-options {
9
13
  display: flex;
10
14
  position: relative;
@@ -46,7 +50,7 @@
46
50
  }
47
51
 
48
52
  &.disabled {
49
- background: var(--glide-core-surface-base-gray-light);
53
+ background: var(--glide-core-surface-disabled);
50
54
  color: var(--glide-core-text-tertiary-disabled);
51
55
  }
52
56
 
@@ -55,15 +59,20 @@
55
59
  color: var(--glide-core-status-error);
56
60
  }
57
61
 
62
+ &.readonly {
63
+ border-color: transparent;
64
+ padding-inline-start: 0;
65
+ }
66
+
58
67
  &:has(.button:focus-visible, .input:focus-visible) {
59
- ${i};
68
+ ${focusOutline};
60
69
  }
61
70
 
62
- &:hover:not(&.error, &.disabled) {
71
+ &:hover:not(&.error, &.disabled, &.readonly) {
63
72
  border-color: var(--glide-core-border-base);
64
73
  }
65
74
 
66
- &.quiet:hover:not(&.error, &.disabled, &.multiple) {
75
+ &.quiet:hover:not(&.error, &.disabled, &.multiple, &.readonly) {
67
76
  background-color: var(--glide-core-surface-hover);
68
77
  }
69
78
  }
@@ -130,6 +139,7 @@
130
139
  background: none;
131
140
  block-size: var(--button-and-input-height);
132
141
  border: none;
142
+ cursor: inherit;
133
143
  display: flex;
134
144
  padding: 0;
135
145
 
@@ -139,8 +149,10 @@
139
149
  }
140
150
 
141
151
  .input {
152
+ background-color: transparent;
142
153
  block-size: var(--button-and-input-height);
143
154
  border: none;
155
+ cursor: inherit;
144
156
  font-size: inherit;
145
157
  min-inline-size: var(--min-inline-size);
146
158
  padding: 0;
@@ -159,4 +171,11 @@
159
171
  font-family: var(--glide-core-font-sans);
160
172
  }
161
173
  }
162
- `];
174
+
175
+ .caret-icon {
176
+ &.disabled,
177
+ &.readonly {
178
+ color: var(--glide-core-surface-selected-disabled);
179
+ }
180
+ }
181
+ `];
@@ -0,0 +1,84 @@
1
+ import './dropdown.option.js';
2
+ import { expect, fixture, html } from '@open-wc/testing';
3
+ import GlideCoreDropdown from './dropdown.js';
4
+ GlideCoreDropdown.shadowRootOptions.mode = 'open';
5
+ const defaultSlot = html `
6
+ <glide-core-dropdown-option
7
+ label="One"
8
+ value="one"
9
+ ></glide-core-dropdown-option>
10
+
11
+ <glide-core-dropdown-option
12
+ label="Two"
13
+ value="two"
14
+ ></glide-core-dropdown-option>
15
+
16
+ <glide-core-dropdown-option
17
+ label="Three"
18
+ value="three"
19
+ ></glide-core-dropdown-option>
20
+
21
+ <glide-core-dropdown-option
22
+ label="Four"
23
+ value="four"
24
+ ></glide-core-dropdown-option>
25
+
26
+ <glide-core-dropdown-option
27
+ label="Five"
28
+ value="five"
29
+ ></glide-core-dropdown-option>
30
+
31
+ <glide-core-dropdown-option
32
+ label="Six"
33
+ value="six"
34
+ ></glide-core-dropdown-option>
35
+
36
+ <glide-core-dropdown-option
37
+ label="Seven"
38
+ value="seven"
39
+ ></glide-core-dropdown-option>
40
+
41
+ <glide-core-dropdown-option
42
+ label="Eight"
43
+ value="eight"
44
+ ></glide-core-dropdown-option>
45
+
46
+ <glide-core-dropdown-option
47
+ label="Nine"
48
+ value="nine"
49
+ ></glide-core-dropdown-option>
50
+
51
+ <glide-core-dropdown-option
52
+ label="Ten"
53
+ value="ten"
54
+ ></glide-core-dropdown-option>
55
+
56
+ <glide-core-dropdown-option
57
+ label="Eleven"
58
+ value="eleven"
59
+ ></glide-core-dropdown-option>
60
+ `;
61
+ it('is accessible', async () => {
62
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
63
+ ${defaultSlot}
64
+ </glide-core-dropdown>`);
65
+ await expect(component).to.be.accessible({
66
+ // Axe doesn't search within slots when determining whether an element
67
+ // has an ID that matches `aria-activedescendant` exists.
68
+ ignoredRules: ['aria-valid-attr-value'],
69
+ });
70
+ });
71
+ it('is filterable', async () => {
72
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
73
+ ${defaultSlot}
74
+ </glide-core-dropdown>`);
75
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
76
+ expect(input?.checkVisibility()).to.be.true;
77
+ });
78
+ it('uses `placeholder` as a placeholder when not `multiple` and no option is selected', async () => {
79
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
80
+ ${defaultSlot}
81
+ </glide-core-dropdown>`);
82
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
83
+ expect(input?.placeholder).to.equal('Placeholder');
84
+ });
@@ -0,0 +1,233 @@
1
+ import './dropdown.option.js';
2
+ import { ArgumentError } from 'ow';
3
+ import { expect, fixture, html } from '@open-wc/testing';
4
+ import { repeat } from 'lit/directives/repeat.js';
5
+ import GlideCoreDropdown from './dropdown.js';
6
+ import expectArgumentError from './library/expect-argument-error.js';
7
+ import sinon from 'sinon';
8
+ // You'll notice quite a few duplicated tests among the "*.single.ts", "*.multiple.ts",
9
+ // and "*.filterable.ts" test suites. The thinking is that a test warrants
10
+ // duplication whenever Dropdown's internal logic isn't shared among all three
11
+ // of those states or if one state goes down a significantly different code path.
12
+ //
13
+ // There are still gaps. And there are exceptions to avoid excessive duplication
14
+ // for the sake of organization. Many of the tests in `dropdown.test.interactions.ts`,
15
+ // for example, don't apply to the filterable case and so aren't common among all
16
+ // three states. They nonetheless reside there because moving them out and
17
+ // duplicating them in both `dropdown.test.interactions.single.ts` and
18
+ // `dropdown.test.interactions.multiple.ts` would add a ton of test weight.
19
+ GlideCoreDropdown.shadowRootOptions.mode = 'open';
20
+ it('registers', async () => {
21
+ expect(window.customElements.get('glide-core-dropdown')).to.equal(GlideCoreDropdown);
22
+ });
23
+ it('has defaults', async () => {
24
+ // Required attributes are supplied here and thus left unasserted below. The
25
+ // idea is that this test shouldn't fail to typecheck if these templates are
26
+ // eventually typechecked, which means supplying all required attributes and slots.
27
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
28
+ <glide-core-dropdown-option
29
+ label="Label"
30
+ value="value"
31
+ ></glide-core-dropdown-option>
32
+ </glide-core-dropdown>`);
33
+ expect(component.hasAttribute('disabled')).to.be.false;
34
+ expect(component.disabled).to.equal(false);
35
+ expect(component.getAttribute('name')).to.be.null;
36
+ expect(component.name).to.equal(undefined);
37
+ expect(component.hasAttribute('required')).to.be.false;
38
+ expect(component.required).to.equal(false);
39
+ expect(component.getAttribute('size')).to.equal('large');
40
+ expect(component.size).to.equal('large');
41
+ // Not reflected, so no attribute assertion is necessary.
42
+ expect(component.value).to.deep.equal([]);
43
+ });
44
+ it('can have a label', async () => {
45
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
46
+ <glide-core-dropdown-option
47
+ label="Label"
48
+ value="value"
49
+ ></glide-core-dropdown-option>
50
+ </glide-core-dropdown>`);
51
+ expect(component.getAttribute('label')).to.equal('Label');
52
+ expect(component.label).to.equal('Label');
53
+ });
54
+ it('can have a placeholder', async () => {
55
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
56
+ <glide-core-dropdown-option
57
+ label="Label"
58
+ value="value"
59
+ ></glide-core-dropdown-option>
60
+ </glide-core-dropdown>`);
61
+ expect(component.getAttribute('placeholder')).to.equal('Placeholder');
62
+ expect(component.placeholder).to.equal('Placeholder');
63
+ });
64
+ it('can have a description', async () => {
65
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
66
+ <div slot="description">Description</div>
67
+ <glide-core-dropdown-option
68
+ label="Label"
69
+ value="value"
70
+ ></glide-core-dropdown-option>
71
+ </glide-core-dropdown>`);
72
+ const assignedElements = component.shadowRoot
73
+ ?.querySelector('slot[name="description"]')
74
+ ?.assignedElements();
75
+ expect(assignedElements?.at(0)?.textContent).to.equal('Description');
76
+ });
77
+ it('can have a tooltip', async () => {
78
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
79
+ <glide-core-dropdown-option
80
+ label="Label"
81
+ value="value"
82
+ ></glide-core-dropdown-option>
83
+ <div slot="tooltip">Tooltip</div>
84
+ </glide-core-dropdown>`);
85
+ const assignedElements = component.shadowRoot
86
+ ?.querySelector('slot[name="tooltip"]')
87
+ ?.assignedElements();
88
+ expect(assignedElements?.at(0)?.textContent).to.equal('Tooltip');
89
+ });
90
+ it('can have a `name`', async () => {
91
+ const component = await fixture(html `<glide-core-dropdown
92
+ label="Label"
93
+ placeholder="Placeholder"
94
+ name="name"
95
+ >
96
+ <glide-core-dropdown-option
97
+ label="Label"
98
+ value="value"
99
+ ></glide-core-dropdown-option>
100
+ </glide-core-dropdown>`);
101
+ expect(component.getAttribute('name')).to.equal('name');
102
+ expect(component.name).to.equal('name');
103
+ });
104
+ it('can have a `size`', async () => {
105
+ const component = await fixture(html `<glide-core-dropdown
106
+ label="Label"
107
+ placeholder="Placeholder"
108
+ size="small"
109
+ >
110
+ <glide-core-dropdown-option
111
+ label="Label"
112
+ value="value"
113
+ ></glide-core-dropdown-option>
114
+ </glide-core-dropdown>`);
115
+ expect(component.getAttribute('size')).to.equal('small');
116
+ expect(component.size).to.equal('small');
117
+ const option = component.querySelector('glide-core-dropdown-option');
118
+ expect(option?.privateSize).to.equal('small');
119
+ });
120
+ it('can be `disabled`', async () => {
121
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" disabled>
122
+ <glide-core-dropdown-option
123
+ label="Label"
124
+ value="value"
125
+ ></glide-core-dropdown-option>
126
+ </glide-core-dropdown>`);
127
+ expect(component.hasAttribute('disabled')).to.be.true;
128
+ expect(component.disabled).to.equal(true);
129
+ });
130
+ it('can be `required`', async () => {
131
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" required>
132
+ <glide-core-dropdown-option
133
+ label="Label"
134
+ value="value"
135
+ ></glide-core-dropdown-option>
136
+ </glide-core-dropdown>`);
137
+ expect(component.hasAttribute('required')).to.be.true;
138
+ expect(component.required).to.equal(true);
139
+ });
140
+ it('can be `multiple`', async () => {
141
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
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
+ ></glide-core-dropdown-option>
151
+ </glide-core-dropdown>`);
152
+ expect(component.hasAttribute('multiple')).to.be.true;
153
+ expect(component.multiple).to.equal(true);
154
+ });
155
+ it('can be `select-all`', async () => {
156
+ const component = await fixture(html `<glide-core-dropdown
157
+ label="Label"
158
+ placeholder="Placeholder"
159
+ multiple
160
+ select-all
161
+ >
162
+ <glide-core-dropdown-option
163
+ label="Label"
164
+ value="value"
165
+ ></glide-core-dropdown-option>
166
+ </glide-core-dropdown>`);
167
+ expect(component.hasAttribute('select-all')).to.be.true;
168
+ expect(component.selectAll).to.equal(true);
169
+ });
170
+ it('activates the first option when no options are initially selected', async () => {
171
+ const component = await fixture(html `<glide-core-dropdown open>
172
+ <glide-core-dropdown-option
173
+ label="One"
174
+ value="one"
175
+ ></glide-core-dropdown-option>
176
+
177
+ <glide-core-dropdown-option
178
+ label="Two"
179
+ value="two"
180
+ ></glide-core-dropdown-option>
181
+ </glide-core-dropdown>`);
182
+ const options = component.querySelectorAll('glide-core-dropdown-option');
183
+ expect(options[0]?.privateActive).to.be.true;
184
+ expect(options[1]?.privateActive).to.be.false;
185
+ });
186
+ it('activates the last selected option when options are initially selected', async () => {
187
+ const component = await fixture(html `<glide-core-dropdown open>
188
+ <glide-core-dropdown-option
189
+ label="One"
190
+ value="one"
191
+ ></glide-core-dropdown-option>
192
+
193
+ <glide-core-dropdown-option
194
+ label="Two"
195
+ value="two"
196
+ selected
197
+ ></glide-core-dropdown-option>
198
+
199
+ <glide-core-dropdown-option
200
+ label="Three"
201
+ value="three"
202
+ selected
203
+ ></glide-core-dropdown-option>
204
+ </glide-core-dropdown>`);
205
+ const options = component.querySelectorAll('glide-core-dropdown-option');
206
+ expect(options[0]?.privateActive).to.be.false;
207
+ expect(options[1]?.privateActive).to.be.false;
208
+ expect(options[2]?.privateActive).to.be.true;
209
+ });
210
+ it('throws if the default slot is the incorrect type', async () => {
211
+ await expectArgumentError(() => {
212
+ return fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
213
+ <button>Button</button>
214
+ </glide-core-dropdown>`);
215
+ });
216
+ });
217
+ it('does not throw if the default slot only contains whitespace', async () => {
218
+ const spy = sinon.spy();
219
+ try {
220
+ await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
221
+ ${repeat([], () => html `<glide-core-dropdown-option
222
+ label="Option"
223
+ value="option"
224
+ ></glide-core-dropdown-option>`)}
225
+ </glide-core-dropdown>`);
226
+ }
227
+ catch (error) {
228
+ if (error instanceof ArgumentError) {
229
+ spy();
230
+ }
231
+ }
232
+ expect(spy.notCalled).to.be.true;
233
+ });