wcs-core 7.3.0 → 7.4.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 (251) hide show
  1. package/README.md +11 -9
  2. package/design-tokens/dist/sncf-groupe-root-scoped.css +227 -227
  3. package/design-tokens/dist/sncf-groupe.css +227 -227
  4. package/design-tokens/dist/sncf-holding-root-scoped.css +227 -227
  5. package/design-tokens/dist/sncf-holding.css +227 -227
  6. package/design-tokens/dist/sncf-reseau-root-scoped.css +227 -227
  7. package/design-tokens/dist/sncf-reseau.css +227 -227
  8. package/design-tokens/dist/sncf-voyageurs-root-scoped.css +242 -242
  9. package/design-tokens/dist/sncf-voyageurs.css +242 -242
  10. package/dist/cjs/{popper-8d6e7fca.js → popper-1b61df21.js} +10 -17
  11. package/dist/cjs/popper-1b61df21.js.map +1 -0
  12. package/dist/cjs/wcs-breadcrumb.cjs.entry.js +1 -1
  13. package/dist/cjs/wcs-breadcrumb.cjs.entry.js.map +1 -1
  14. package/dist/cjs/wcs-com-nav-item.cjs.entry.js +1 -1
  15. package/dist/cjs/wcs-com-nav-item.cjs.entry.js.map +1 -1
  16. package/dist/cjs/wcs-com-nav.cjs.entry.js +3 -3
  17. package/dist/cjs/wcs-com-nav.cjs.entry.js.map +1 -1
  18. package/dist/cjs/wcs-dropdown.cjs.entry.js +1 -1
  19. package/dist/cjs/wcs-error_3.cjs.entry.js +1 -1
  20. package/dist/cjs/wcs-error_3.cjs.entry.js.map +1 -1
  21. package/dist/cjs/wcs-galactic-menu.cjs.entry.js +1 -1
  22. package/dist/cjs/wcs-grid.cjs.entry.js +5 -4
  23. package/dist/cjs/wcs-grid.cjs.entry.js.map +1 -1
  24. package/dist/cjs/wcs-horizontal-stepper.cjs.entry.js +3 -2
  25. package/dist/cjs/wcs-horizontal-stepper.cjs.entry.js.map +1 -1
  26. package/dist/cjs/wcs-modal.cjs.entry.js +2 -2
  27. package/dist/cjs/wcs-modal.cjs.entry.js.map +1 -1
  28. package/dist/cjs/wcs-select_2.cjs.entry.js +59 -24
  29. package/dist/cjs/wcs-select_2.cjs.entry.js.map +1 -1
  30. package/dist/cjs/wcs-tabs.cjs.entry.js +1 -1
  31. package/dist/cjs/wcs-tooltip.cjs.entry.js +1 -1
  32. package/dist/collection/components/accordion/{accordion.e2e.js → accordion.e2e.playwright.js} +51 -55
  33. package/dist/collection/components/accordion/accordion.e2e.playwright.js.map +1 -0
  34. package/dist/collection/components/accordion-panel/accordion-panel.js +1 -1
  35. package/dist/collection/components/alert/alert.e2e.playwright.js +125 -0
  36. package/dist/collection/components/alert/alert.e2e.playwright.js.map +1 -0
  37. package/dist/collection/components/alert-drawer/alert-drawer.e2e.playwright.js +107 -0
  38. package/dist/collection/components/alert-drawer/alert-drawer.e2e.playwright.js.map +1 -0
  39. package/dist/collection/components/breadcrumb/breadcrumb.e2e.playwright.js +188 -0
  40. package/dist/collection/components/breadcrumb/breadcrumb.e2e.playwright.js.map +1 -0
  41. package/dist/collection/components/breadcrumb/breadcrumb.js +2 -2
  42. package/dist/collection/components/breadcrumb/breadcrumb.js.map +1 -1
  43. package/dist/collection/components/button/button.e2e.playwright.js +26 -0
  44. package/dist/collection/components/button/button.e2e.playwright.js.map +1 -0
  45. package/dist/collection/components/button/button.js +1 -1
  46. package/dist/collection/components/checkbox/checkbox.e2e.playwright.js +39 -0
  47. package/dist/collection/components/checkbox/checkbox.e2e.playwright.js.map +1 -0
  48. package/dist/collection/components/checkbox/checkbox.js +1 -1
  49. package/dist/collection/components/chip/chip.e2e.playwright.js +190 -0
  50. package/dist/collection/components/chip/chip.e2e.playwright.js.map +1 -0
  51. package/dist/collection/components/com-nav/com-nav.css +15 -0
  52. package/dist/collection/components/com-nav/{com-nav.e2e.js → com-nav.e2e.playwright.js} +60 -44
  53. package/dist/collection/components/com-nav/com-nav.e2e.playwright.js.map +1 -0
  54. package/dist/collection/components/com-nav/com-nav.js +3 -3
  55. package/dist/collection/components/com-nav/com-nav.js.map +1 -1
  56. package/dist/collection/components/com-nav-category/com-nav-category.js +1 -1
  57. package/dist/collection/components/com-nav-item/com-nav-item.css +2 -2
  58. package/dist/collection/components/com-nav-submenu/com-nav-submenu.js +1 -1
  59. package/dist/collection/components/counter/counter.e2e.playwright.js +187 -0
  60. package/dist/collection/components/counter/counter.e2e.playwright.js.map +1 -0
  61. package/dist/collection/components/counter/counter.js +1 -1
  62. package/dist/collection/components/dropdown/dropdown.e2e.playwright.js +320 -0
  63. package/dist/collection/components/dropdown/dropdown.e2e.playwright.js.map +1 -0
  64. package/dist/collection/components/dropdown/dropdown.js +1 -1
  65. package/dist/collection/components/editable-field/editable-field.e2e.playwright.js +156 -0
  66. package/dist/collection/components/editable-field/editable-field.e2e.playwright.js.map +1 -0
  67. package/dist/collection/components/form-field/form-field.e2e.playwright.js +104 -0
  68. package/dist/collection/components/form-field/form-field.e2e.playwright.js.map +1 -0
  69. package/dist/collection/components/galactic-menu/galactic-menu.js +1 -1
  70. package/dist/collection/components/grid/grid.e2e.playwright.js +153 -0
  71. package/dist/collection/components/grid/grid.e2e.playwright.js.map +1 -0
  72. package/dist/collection/components/grid/grid.js +6 -5
  73. package/dist/collection/components/grid/grid.js.map +1 -1
  74. package/dist/collection/components/grid-column/grid-column.js +1 -1
  75. package/dist/collection/components/grid-pagination/grid-pagination.js +1 -1
  76. package/dist/collection/components/header/header.js +1 -1
  77. package/dist/collection/components/horizontal-stepper/horizontal-step.js +2 -1
  78. package/dist/collection/components/horizontal-stepper/horizontal-step.js.map +1 -1
  79. package/dist/collection/components/horizontal-stepper/horizontal-stepper-interface.js.map +1 -1
  80. package/dist/collection/components/horizontal-stepper/horizontal-stepper.js +5 -1
  81. package/dist/collection/components/horizontal-stepper/horizontal-stepper.js.map +1 -1
  82. package/dist/collection/components/icon/icon.js +1 -1
  83. package/dist/collection/components/input/input.e2e.playwright.js +157 -0
  84. package/dist/collection/components/input/input.e2e.playwright.js.map +1 -0
  85. package/dist/collection/components/input/input.js +2 -2
  86. package/dist/collection/components/label/label.css +4 -6
  87. package/dist/collection/components/label/label.js +1 -1
  88. package/dist/collection/components/mat-icon/mat-icon.js +1 -1
  89. package/dist/collection/components/modal/modal.css +4 -0
  90. package/dist/collection/components/modal/modal.e2e.playwright.js +35 -0
  91. package/dist/collection/components/modal/modal.e2e.playwright.js.map +1 -0
  92. package/dist/collection/components/modal/modal.js +2 -2
  93. package/dist/collection/components/modal/modal.js.map +1 -1
  94. package/dist/collection/components/native-select/native-select.js +1 -1
  95. package/dist/collection/components/nav/nav.js +1 -1
  96. package/dist/collection/components/progress-bar/progress-bar.js +1 -1
  97. package/dist/collection/components/progress-radial/progress-radial.js +1 -1
  98. package/dist/collection/components/radio/radio.js +1 -1
  99. package/dist/collection/components/radio-group/radio-group.e2e.playwright.js +231 -0
  100. package/dist/collection/components/radio-group/radio-group.e2e.playwright.js.map +1 -0
  101. package/dist/collection/components/radio-group/radio-group.js +1 -1
  102. package/dist/collection/components/select/select.e2e.playwright.js +1702 -0
  103. package/dist/collection/components/select/select.e2e.playwright.js.map +1 -0
  104. package/dist/collection/components/select/select.js +49 -20
  105. package/dist/collection/components/select/select.js.map +1 -1
  106. package/dist/collection/components/select-option/select-option.js +3 -3
  107. package/dist/collection/components/select-option/select-option.js.map +1 -1
  108. package/dist/collection/components/switch/switch.e2e.playwright.js +40 -0
  109. package/dist/collection/components/switch/switch.e2e.playwright.js.map +1 -0
  110. package/dist/collection/components/switch/switch.js +1 -1
  111. package/dist/collection/components/tabs/tabs.e2e.playwright.js +205 -0
  112. package/dist/collection/components/tabs/tabs.e2e.playwright.js.map +1 -0
  113. package/dist/collection/components/tabs/tabs.js +1 -1
  114. package/dist/collection/components/textarea/textarea.e2e.playwright.js +133 -0
  115. package/dist/collection/components/textarea/textarea.e2e.playwright.js.map +1 -0
  116. package/dist/collection/components/textarea/textarea.js +1 -1
  117. package/dist/collection/utils/playwright/test-expect.js +2 -0
  118. package/dist/collection/utils/playwright/test-expect.js.map +1 -0
  119. package/dist/collection/utils/playwright/test.js +16 -0
  120. package/dist/collection/utils/playwright/test.js.map +1 -0
  121. package/dist/esm/{popper-e491c314.js → popper-ac238961.js} +10 -17
  122. package/dist/esm/popper-ac238961.js.map +1 -0
  123. package/dist/esm/wcs-breadcrumb.entry.js +1 -1
  124. package/dist/esm/wcs-breadcrumb.entry.js.map +1 -1
  125. package/dist/esm/wcs-com-nav-item.entry.js +1 -1
  126. package/dist/esm/wcs-com-nav-item.entry.js.map +1 -1
  127. package/dist/esm/wcs-com-nav.entry.js +3 -3
  128. package/dist/esm/wcs-com-nav.entry.js.map +1 -1
  129. package/dist/esm/wcs-dropdown.entry.js +1 -1
  130. package/dist/esm/wcs-error_3.entry.js +1 -1
  131. package/dist/esm/wcs-error_3.entry.js.map +1 -1
  132. package/dist/esm/wcs-galactic-menu.entry.js +1 -1
  133. package/dist/esm/wcs-grid.entry.js +5 -4
  134. package/dist/esm/wcs-grid.entry.js.map +1 -1
  135. package/dist/esm/wcs-horizontal-stepper.entry.js +3 -2
  136. package/dist/esm/wcs-horizontal-stepper.entry.js.map +1 -1
  137. package/dist/esm/wcs-modal.entry.js +2 -2
  138. package/dist/esm/wcs-modal.entry.js.map +1 -1
  139. package/dist/esm/wcs-select_2.entry.js +59 -24
  140. package/dist/esm/wcs-select_2.entry.js.map +1 -1
  141. package/dist/esm/wcs-tabs.entry.js +1 -1
  142. package/dist/esm/wcs-tooltip.entry.js +1 -1
  143. package/dist/types/components/accordion/accordion.e2e.playwright.d.ts +1 -0
  144. package/dist/types/components/alert/alert.e2e.playwright.d.ts +1 -0
  145. package/dist/types/components/alert-drawer/alert-drawer.e2e.playwright.d.ts +1 -0
  146. package/dist/types/components/breadcrumb/breadcrumb.e2e.playwright.d.ts +1 -0
  147. package/dist/types/components/button/button.e2e.playwright.d.ts +1 -0
  148. package/dist/types/components/checkbox/checkbox.e2e.playwright.d.ts +1 -0
  149. package/dist/types/components/chip/chip.e2e.playwright.d.ts +1 -0
  150. package/dist/types/components/com-nav/com-nav.e2e.playwright.d.ts +1 -0
  151. package/dist/types/components/counter/counter.e2e.playwright.d.ts +1 -0
  152. package/dist/types/components/dropdown/dropdown.e2e.playwright.d.ts +1 -0
  153. package/dist/types/components/editable-field/editable-field.e2e.playwright.d.ts +1 -0
  154. package/dist/types/components/form-field/form-field.e2e.playwright.d.ts +1 -0
  155. package/dist/types/components/grid/grid.e2e.playwright.d.ts +1 -0
  156. package/dist/types/components/horizontal-stepper/horizontal-stepper-interface.d.ts +2 -0
  157. package/dist/types/components/horizontal-stepper/horizontal-stepper.d.ts +4 -0
  158. package/dist/types/components/input/input.e2e.playwright.d.ts +1 -0
  159. package/dist/types/components/modal/modal.e2e.playwright.d.ts +1 -0
  160. package/dist/types/components/radio-group/radio-group.e2e.playwright.d.ts +1 -0
  161. package/dist/types/components/select/select.d.ts +7 -1
  162. package/dist/types/components/select/select.e2e.playwright.d.ts +1 -0
  163. package/dist/types/components/switch/switch.e2e.playwright.d.ts +1 -0
  164. package/dist/types/components/tabs/tabs.e2e.playwright.d.ts +1 -0
  165. package/dist/types/components/textarea/textarea.e2e.playwright.d.ts +1 -0
  166. package/dist/types/components.d.ts +12 -0
  167. package/dist/types/utils/playwright/test-expect.d.ts +33 -0
  168. package/dist/types/utils/playwright/test.d.ts +7 -0
  169. package/dist/wcs/{p-8e9bd0f1.entry.js → p-0326f834.entry.js} +2 -2
  170. package/dist/wcs/{p-8e9bd0f1.entry.js.map → p-0326f834.entry.js.map} +1 -1
  171. package/dist/wcs/p-2221bf0c.entry.js +16 -0
  172. package/dist/wcs/p-2221bf0c.entry.js.map +1 -0
  173. package/dist/wcs/p-4ae08567.entry.js +2 -0
  174. package/dist/wcs/p-4ae08567.entry.js.map +1 -0
  175. package/dist/wcs/p-4e2d6227.entry.js +2 -0
  176. package/dist/wcs/p-4e2d6227.entry.js.map +1 -0
  177. package/dist/wcs/p-8332a7e3.entry.js +2 -0
  178. package/dist/wcs/p-8332a7e3.entry.js.map +1 -0
  179. package/dist/wcs/{p-ec383729.entry.js → p-9b76b8e6.entry.js} +2 -2
  180. package/dist/wcs/{p-ec383729.entry.js.map → p-9b76b8e6.entry.js.map} +1 -1
  181. package/dist/wcs/{p-1f593d06.entry.js → p-abd8d5a0.entry.js} +2 -2
  182. package/dist/wcs/{p-622f7403.entry.js → p-c6f8c45c.entry.js} +2 -2
  183. package/dist/wcs/{p-a94e685c.entry.js → p-db7ba599.entry.js} +2 -2
  184. package/dist/wcs/p-e1fb3625.js +2 -0
  185. package/dist/wcs/p-e1fb3625.js.map +1 -0
  186. package/dist/wcs/{p-a956dc84.entry.js → p-f2f7595e.entry.js} +2 -2
  187. package/dist/wcs/{p-a956dc84.entry.js.map → p-f2f7595e.entry.js.map} +1 -1
  188. package/dist/wcs/p-fbd68522.entry.js +2 -0
  189. package/dist/wcs/p-fbd68522.entry.js.map +1 -0
  190. package/dist/wcs/{p-8c2605fd.entry.js → p-fe303f58.entry.js} +2 -2
  191. package/dist/wcs/wcs.esm.js +1 -1
  192. package/package.json +18 -24
  193. package/dist/cjs/popper-8d6e7fca.js.map +0 -1
  194. package/dist/collection/components/accordion/accordion.e2e.js.map +0 -1
  195. package/dist/collection/components/alert/alert.e2e.js +0 -142
  196. package/dist/collection/components/alert/alert.e2e.js.map +0 -1
  197. package/dist/collection/components/alert-drawer/alert-drawer.e2e.js +0 -111
  198. package/dist/collection/components/alert-drawer/alert-drawer.e2e.js.map +0 -1
  199. package/dist/collection/components/breadcrumb/breadcrumb.e2e.js +0 -223
  200. package/dist/collection/components/breadcrumb/breadcrumb.e2e.js.map +0 -1
  201. package/dist/collection/components/button/button.e2e.js +0 -25
  202. package/dist/collection/components/button/button.e2e.js.map +0 -1
  203. package/dist/collection/components/checkbox/checkbox.e2e.js +0 -45
  204. package/dist/collection/components/checkbox/checkbox.e2e.js.map +0 -1
  205. package/dist/collection/components/chip/chip.e2e.js +0 -209
  206. package/dist/collection/components/chip/chip.e2e.js.map +0 -1
  207. package/dist/collection/components/com-nav/com-nav.e2e.js.map +0 -1
  208. package/dist/collection/components/counter/counter.e2e.js +0 -206
  209. package/dist/collection/components/counter/counter.e2e.js.map +0 -1
  210. package/dist/collection/components/dropdown/dropdown.e2e.js +0 -156
  211. package/dist/collection/components/dropdown/dropdown.e2e.js.map +0 -1
  212. package/dist/collection/components/editable-field/editable-field.e2e.js +0 -176
  213. package/dist/collection/components/editable-field/editable-field.e2e.js.map +0 -1
  214. package/dist/collection/components/form-field/form-field.e2e.js +0 -122
  215. package/dist/collection/components/form-field/form-field.e2e.js.map +0 -1
  216. package/dist/collection/components/grid/grid.e2e.js +0 -147
  217. package/dist/collection/components/grid/grid.e2e.js.map +0 -1
  218. package/dist/collection/components/input/input.e2e.js +0 -152
  219. package/dist/collection/components/input/input.e2e.js.map +0 -1
  220. package/dist/collection/components/modal/modal.e2e.js +0 -36
  221. package/dist/collection/components/modal/modal.e2e.js.map +0 -1
  222. package/dist/collection/components/radio-group/radio-group.e2e.js +0 -239
  223. package/dist/collection/components/radio-group/radio-group.e2e.js.map +0 -1
  224. package/dist/collection/components/select/select.e2e.js +0 -1081
  225. package/dist/collection/components/select/select.e2e.js.map +0 -1
  226. package/dist/collection/components/switch/switch.e2e.js +0 -45
  227. package/dist/collection/components/switch/switch.e2e.js.map +0 -1
  228. package/dist/collection/components/tabs/tabs.e2e.js +0 -207
  229. package/dist/collection/components/tabs/tabs.e2e.js.map +0 -1
  230. package/dist/collection/components/textarea/textarea.e2e.js +0 -132
  231. package/dist/collection/components/textarea/textarea.e2e.js.map +0 -1
  232. package/dist/collection/utils/tests.js +0 -23
  233. package/dist/collection/utils/tests.js.map +0 -1
  234. package/dist/esm/popper-e491c314.js.map +0 -1
  235. package/dist/types/utils/tests.d.ts +0 -4
  236. package/dist/wcs/p-0dd07842.entry.js +0 -2
  237. package/dist/wcs/p-0dd07842.entry.js.map +0 -1
  238. package/dist/wcs/p-0f864e86.js +0 -2
  239. package/dist/wcs/p-0f864e86.js.map +0 -1
  240. package/dist/wcs/p-1244daa0.entry.js +0 -2
  241. package/dist/wcs/p-1244daa0.entry.js.map +0 -1
  242. package/dist/wcs/p-1fbe0328.entry.js +0 -2
  243. package/dist/wcs/p-1fbe0328.entry.js.map +0 -1
  244. package/dist/wcs/p-b94a09b6.entry.js +0 -16
  245. package/dist/wcs/p-b94a09b6.entry.js.map +0 -1
  246. package/dist/wcs/p-fd187bce.entry.js +0 -2
  247. package/dist/wcs/p-fd187bce.entry.js.map +0 -1
  248. /package/dist/wcs/{p-1f593d06.entry.js.map → p-abd8d5a0.entry.js.map} +0 -0
  249. /package/dist/wcs/{p-622f7403.entry.js.map → p-c6f8c45c.entry.js.map} +0 -0
  250. /package/dist/wcs/{p-a94e685c.entry.js.map → p-db7ba599.entry.js.map} +0 -0
  251. /package/dist/wcs/{p-8c2605fd.entry.js.map → p-fe303f58.entry.js.map} +0 -0
@@ -0,0 +1,1702 @@
1
+ import { expect } from "@playwright/test";
2
+ import { test } from "@stencil/playwright";
3
+ import { setWcsContent } from "../../utils/playwright/test";
4
+ async function focusAutocompleteInput(select) {
5
+ await select.click();
6
+ await select.click();
7
+ }
8
+ test.describe('Select component', () => {
9
+ test('Expands when clicked', async ({ page }) => {
10
+ // Given
11
+ await setWcsContent(page, `
12
+ <wcs-select>
13
+ <wcs-select-option value="1">One</wcs-select-option>
14
+ </wcs-select>
15
+ `);
16
+ const select = page.locator('wcs-select');
17
+ // When
18
+ await select.click();
19
+ // Then
20
+ await expect(select).toHaveClass(/expanded/);
21
+ });
22
+ test('Expands using the open method', async ({ page }) => {
23
+ // Given
24
+ await setWcsContent(page, `
25
+ <wcs-select>
26
+ <wcs-select-option value="1">One</wcs-select-option>
27
+ </wcs-select>
28
+ `);
29
+ const select = page.locator('wcs-select');
30
+ // When
31
+ await select.evaluate((el) => el.open());
32
+ // Then
33
+ await expect(select).toHaveClass(/expanded/);
34
+ });
35
+ test('Closes using the open method', async ({ page }) => {
36
+ // Given
37
+ await setWcsContent(page, `
38
+ <wcs-select>
39
+ <wcs-select-option value="1">One</wcs-select-option>
40
+ </wcs-select>
41
+ `);
42
+ const select = page.locator('wcs-select');
43
+ // When
44
+ await select.click();
45
+ await select.evaluate((el) => el.close());
46
+ // Then
47
+ await expect(select).not.toHaveClass(/expanded/);
48
+ });
49
+ test('Closes when user click outside', async ({ page }) => {
50
+ // Given
51
+ await setWcsContent(page, `
52
+ <wcs-select>
53
+ <wcs-select-option value="1">One</wcs-select-option>
54
+ </wcs-select>
55
+ <div class="outside" style="margin-top: 300px; width: 100px; height: 100px;"></div>
56
+ `);
57
+ const select = page.locator('wcs-select');
58
+ const outside = page.locator('div.outside');
59
+ // When
60
+ await select.click();
61
+ await outside.click();
62
+ // Then
63
+ await expect(select).not.toHaveClass(/expanded/);
64
+ });
65
+ test('Closes when user click on another select', async ({ page }) => {
66
+ // Given
67
+ await page.setViewportSize({ width: 1024, height: 1600 });
68
+ await setWcsContent(page, `
69
+ <div style="display: flex">
70
+ <wcs-select id="select-1">
71
+ <wcs-select-option value="1">One</wcs-select-option>
72
+ <wcs-select-option value="2">Two</wcs-select-option>
73
+ <wcs-select-option value="3">Three</wcs-select-option>
74
+ </wcs-select>
75
+ <wcs-select id="select-2">
76
+ <wcs-select-option value="1">One</wcs-select-option>
77
+ <wcs-select-option value="2">Two</wcs-select-option>
78
+ <wcs-select-option value="3">Three</wcs-select-option>
79
+ </wcs-select>
80
+ </div>
81
+ `);
82
+ const select1 = page.locator('#select-1');
83
+ const select2 = page.locator('#select-2');
84
+ // When
85
+ await select1.click();
86
+ // Then
87
+ await expect(select1).toHaveClass(/expanded/);
88
+ await select2.click(); // select another select component in page
89
+ await expect(select1).not.toHaveClass(/expanded/);
90
+ await expect(select2).toHaveClass(/expanded/);
91
+ });
92
+ test('Let us select a value and fire event correctly', async ({ page }) => {
93
+ // Given
94
+ await setWcsContent(page, `
95
+ <wcs-select>
96
+ <wcs-select-option value="1">One</wcs-select-option>
97
+ </wcs-select>
98
+ `);
99
+ const select = page.locator('wcs-select');
100
+ const firstOption = page.locator('wcs-select > wcs-select-option');
101
+ const changeSpy = await page.spyOnEvent('wcsChange');
102
+ // When
103
+ await select.click();
104
+ await expect(select).toHaveClass(/expanded/);
105
+ await firstOption.click();
106
+ await page.waitForChanges();
107
+ // Then
108
+ expect(changeSpy).toHaveReceivedEventTimes(1);
109
+ expect(changeSpy).toHaveReceivedEventDetail({ value: '1' });
110
+ // Vérifier le label dans le shadow DOM
111
+ const label = select.locator('label').first();
112
+ await expect(label).toHaveText('One');
113
+ });
114
+ test.describe('select event', () => {
115
+ test('should not emit event if we set the value in js', async ({ page }) => {
116
+ // Given
117
+ await setWcsContent(page, `
118
+ <wcs-select value="1">
119
+ <wcs-select-option value="1">One</wcs-select-option>
120
+ <wcs-select-option value="2">Two</wcs-select-option>
121
+ </wcs-select>
122
+ `);
123
+ const select = page.locator('wcs-select');
124
+ const changeSpy = await page.spyOnEvent('wcsChange');
125
+ // When
126
+ await select.evaluate((el) => el.value = '2');
127
+ await page.waitForChanges();
128
+ // Then
129
+ expect(changeSpy).toHaveReceivedEventTimes(0);
130
+ });
131
+ });
132
+ test.describe('setSelectedValue', () => {
133
+ test('Let user change selected value programmatically', async ({ page }) => {
134
+ // Given
135
+ await setWcsContent(page, `
136
+ <wcs-select>
137
+ <wcs-select-option value="1">One</wcs-select-option>
138
+ <wcs-select-option value="2">Two</wcs-select-option>
139
+ </wcs-select>
140
+ `);
141
+ const select = page.locator('wcs-select');
142
+ // When
143
+ await select.evaluate((el) => el.value = '2');
144
+ // Then
145
+ const label = page.locator('label').first();
146
+ await expect(label).toHaveText('Two');
147
+ });
148
+ test('Let user change selected values programmatically', async ({ page }) => {
149
+ // Given
150
+ await setWcsContent(page, `
151
+ <wcs-select multiple>
152
+ <wcs-select-option value="1">One</wcs-select-option>
153
+ <wcs-select-option value="2">Two</wcs-select-option>
154
+ <wcs-select-option value="3">Three</wcs-select-option>
155
+ </wcs-select>
156
+ `);
157
+ const select = page.locator('wcs-select');
158
+ // When
159
+ await select.evaluate((el) => el.value = ['2', '3']);
160
+ await page.waitForTimeout(50);
161
+ // Then
162
+ const label = page.locator('label').first();
163
+ await expect(label).toHaveText('Two, Three');
164
+ });
165
+ });
166
+ test('Is focusable', async ({ page }) => {
167
+ // Given
168
+ await setWcsContent(page, `
169
+ <wcs-select>
170
+ <wcs-select-option value="1">One</wcs-select-option>
171
+ </wcs-select>
172
+ `);
173
+ const select = page.locator('wcs-select');
174
+ // When
175
+ await select.focus();
176
+ // Then
177
+ await expect(select).toBeFocused();
178
+ });
179
+ test.describe('Disabled', () => {
180
+ test('Must not expand when disabled', async ({ page }) => {
181
+ // Given
182
+ await setWcsContent(page, `
183
+ <wcs-select disabled>
184
+ <wcs-select-option value="1">One</wcs-select-option>
185
+ </wcs-select>
186
+ `);
187
+ const select = page.locator('wcs-select');
188
+ // When
189
+ await select.click({ force: true });
190
+ // Then
191
+ await expect(select).not.toHaveClass(/expanded/);
192
+ });
193
+ test('Is not focusable when disabled', async ({ page }) => {
194
+ // Given
195
+ await setWcsContent(page, `
196
+ <wcs-select disabled>
197
+ <wcs-select-option value="1">One</wcs-select-option>
198
+ </wcs-select>
199
+ `);
200
+ const select = page.locator('wcs-select');
201
+ // When
202
+ await select.focus();
203
+ // Then
204
+ await expect(select).not.toBeFocused();
205
+ });
206
+ });
207
+ test.describe('Multiple', () => {
208
+ test('Musn\'t close when we select a value', async ({ page }) => {
209
+ // Given
210
+ await setWcsContent(page, `
211
+ <wcs-select multiple>
212
+ <wcs-select-option value="1">One</wcs-select-option>
213
+ </wcs-select>
214
+ `);
215
+ const select = page.locator('wcs-select');
216
+ const firstOption = page.locator('wcs-select > wcs-select-option');
217
+ // When
218
+ await select.click();
219
+ await expect(select).toHaveClass(/expanded/);
220
+ await firstOption.click();
221
+ await page.waitForChanges();
222
+ // Then
223
+ await expect(select).toHaveClass(/expanded/);
224
+ });
225
+ test('Allows to select multiple values', async ({ page }) => {
226
+ // Given
227
+ await setWcsContent(page, `
228
+ <wcs-select multiple>
229
+ <wcs-select-option value="1">One</wcs-select-option>
230
+ <wcs-select-option value="2">Two</wcs-select-option>
231
+ </wcs-select>
232
+ `);
233
+ const select = page.locator('wcs-select');
234
+ const options = page.locator('wcs-select > wcs-select-option');
235
+ const changeSpy = await page.spyOnEvent('wcsChange');
236
+ // When
237
+ await select.click();
238
+ await expect(select).toHaveClass(/expanded/);
239
+ await options.nth(0).click();
240
+ await page.waitForChanges();
241
+ await options.nth(1).click();
242
+ await page.waitForChanges();
243
+ // Then
244
+ expect(changeSpy).toHaveReceivedEventTimes(2);
245
+ expect(changeSpy).toHaveNthReceivedEventDetail(1, { value: ['1', '2'] });
246
+ });
247
+ test('Allows to unselect a value', async ({ page }) => {
248
+ // Given
249
+ await setWcsContent(page, `
250
+ <wcs-select multiple>
251
+ <wcs-select-option value="1">One</wcs-select-option>
252
+ <wcs-select-option value="2">Two</wcs-select-option>
253
+ <wcs-select-option value="3">Three</wcs-select-option>
254
+ </wcs-select>
255
+ `);
256
+ const select = page.locator('wcs-select');
257
+ const options = page.locator('wcs-select > wcs-select-option');
258
+ const changeSpy = await page.spyOnEvent('wcsChange');
259
+ // When
260
+ await select.click();
261
+ await expect(select).toHaveClass(/expanded/);
262
+ await options.nth(0).click();
263
+ await page.waitForChanges();
264
+ await options.nth(1).click();
265
+ await page.waitForChanges();
266
+ await options.nth(0).click();
267
+ await page.waitForChanges();
268
+ // Then
269
+ expect(changeSpy).toHaveReceivedEventTimes(3);
270
+ expect(changeSpy).toHaveNthReceivedEventDetail(2, { value: ['2'] });
271
+ });
272
+ test('Displays all values separated by a comma', async ({ page }) => {
273
+ // Given
274
+ await setWcsContent(page, `
275
+ <wcs-select multiple>
276
+ <wcs-select-option value="1">One</wcs-select-option>
277
+ <wcs-select-option value="2">Two</wcs-select-option>
278
+ <wcs-select-option value="3">Three</wcs-select-option>
279
+ </wcs-select>
280
+ `);
281
+ const select = page.locator('wcs-select');
282
+ const options = page.locator('wcs-select > wcs-select-option');
283
+ // When
284
+ await select.click();
285
+ await expect(select).toHaveClass(/expanded/);
286
+ await options.nth(0).click();
287
+ await options.nth(1).click();
288
+ await options.nth(2).click();
289
+ // Then
290
+ const label = select.locator('label').first();
291
+ await expect(label).toHaveText('One, Two, Three');
292
+ });
293
+ test('Tells the option that they should display as multiple', async ({ page }) => {
294
+ // Given
295
+ await setWcsContent(page, `
296
+ <wcs-select multiple>
297
+ <wcs-select-option value="1">One</wcs-select-option>
298
+ </wcs-select>
299
+ `);
300
+ const option = page.locator('wcs-select-option').first();
301
+ // Then
302
+ await expect(option).toHaveAttribute('multiple');
303
+ });
304
+ test('Propagate event when values are select', async ({ page }) => {
305
+ // Given
306
+ await setWcsContent(page, `
307
+ <wcs-select multiple>
308
+ <wcs-select-option value="1">One</wcs-select-option>
309
+ <wcs-select-option value="2">Two</wcs-select-option>
310
+ </wcs-select>
311
+ `);
312
+ const select = page.locator('wcs-select');
313
+ const options = page.locator('wcs-select > wcs-select-option');
314
+ const changeSpy = await page.spyOnEvent('wcsChange');
315
+ // When
316
+ await select.click();
317
+ await expect(select).toHaveClass(/expanded/);
318
+ await options.nth(0).click();
319
+ await page.waitForChanges();
320
+ await options.nth(1).click();
321
+ await page.waitForChanges();
322
+ // Then
323
+ expect(changeSpy).toHaveReceivedEventTimes(2);
324
+ expect(changeSpy).toHaveNthReceivedEventDetail(1, { value: ['1', '2'] });
325
+ });
326
+ });
327
+ test.describe('Keyboard navigation when select is closed and not multiple', () => {
328
+ test('select value of first option enabled on Down Arrow key pressed', async ({ page }) => {
329
+ // Given
330
+ await setWcsContent(page, `
331
+ <wcs-select>
332
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
333
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
334
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
335
+ </wcs-select>
336
+ `);
337
+ const select = page.locator('wcs-select');
338
+ const changeSpy = await page.spyOnEvent('wcsChange');
339
+ // When
340
+ await select.focus();
341
+ await page.keyboard.press('ArrowDown');
342
+ await page.waitForChanges();
343
+ // Then
344
+ const label = select.locator('label').first();
345
+ await expect(label).toHaveText('Option 2');
346
+ expect(changeSpy).toHaveReceivedEventTimes(1);
347
+ expect(changeSpy).toHaveFirstReceivedEventDetail({ value: 'option2' });
348
+ });
349
+ test('select value of last option enabled on PageDown key pressed', async ({ page }) => {
350
+ // Given
351
+ await setWcsContent(page, `
352
+ <wcs-select>
353
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
354
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
355
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
356
+ </wcs-select>
357
+ `);
358
+ const select = page.locator('wcs-select');
359
+ const changeSpy = await page.spyOnEvent('wcsChange');
360
+ // When
361
+ await select.focus();
362
+ await page.keyboard.press('PageDown');
363
+ await page.waitForChanges();
364
+ // Then
365
+ const label = select.locator('label').first();
366
+ await expect(label).toHaveText('Option 3');
367
+ expect(changeSpy).toHaveReceivedEventTimes(1);
368
+ expect(changeSpy).toHaveFirstReceivedEventDetail({ value: 'option3' });
369
+ });
370
+ test('select value of first option enabled on PageUp key pressed', async ({ page }) => {
371
+ // Given
372
+ await setWcsContent(page, `
373
+ <wcs-select>
374
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
375
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
376
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
377
+ </wcs-select>
378
+ `);
379
+ const select = page.locator('wcs-select');
380
+ const changeSpy = await page.spyOnEvent('wcsChange');
381
+ // When
382
+ await select.focus();
383
+ await page.keyboard.press('PageUp');
384
+ await page.waitForChanges();
385
+ // Then
386
+ const label = select.locator('label').first();
387
+ await expect(label).toHaveText('Option 2');
388
+ expect(changeSpy).toHaveReceivedEventTimes(1);
389
+ expect(changeSpy).toHaveFirstReceivedEventDetail({ value: 'option2' });
390
+ });
391
+ test('open the overlay on Enter key press', async ({ page }) => {
392
+ // Given
393
+ await setWcsContent(page, `
394
+ <wcs-select>
395
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
396
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
397
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
398
+ </wcs-select>
399
+ `);
400
+ const select = page.locator('wcs-select');
401
+ // When
402
+ await select.focus();
403
+ await page.keyboard.press('Enter');
404
+ // Then
405
+ await expect(select).toHaveClass(/expanded/);
406
+ });
407
+ test('open the overlay on Alt + Down Arrow key pressed', async ({ page }) => {
408
+ // Given
409
+ await setWcsContent(page, `
410
+ <wcs-select>
411
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
412
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
413
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
414
+ </wcs-select>
415
+ `);
416
+ const select = page.locator('wcs-select');
417
+ // When
418
+ await select.focus();
419
+ await page.keyboard.down('Alt');
420
+ await page.keyboard.press('ArrowDown');
421
+ await page.keyboard.up('Alt');
422
+ // Then
423
+ await expect(select).toHaveClass(/expanded/);
424
+ });
425
+ test('focuses last selected option when opening with keyboard after programmatic value change', async ({ page }) => {
426
+ // Given
427
+ await setWcsContent(page, `
428
+ <wcs-select>
429
+ <wcs-select-option value="option1">Option 1</wcs-select-option>
430
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
431
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
432
+ </wcs-select>
433
+ `);
434
+ const select = page.locator('wcs-select');
435
+ // When
436
+ await select.evaluate((el) => el.value = 'option2');
437
+ await page.waitForTimeout(50);
438
+ await select.focus();
439
+ await page.keyboard.press('Enter'); // Open select with keyboard
440
+ // Then
441
+ const focusedOption = page.locator('wcs-select-option:focus');
442
+ await expect(focusedOption).toHaveAttribute('value', 'option2');
443
+ });
444
+ });
445
+ test.describe('Keyboard navigation when select is opened and not multiple', () => {
446
+ test('close the overlay on Escape key pressed and focus select control', async ({ page }) => {
447
+ // Given
448
+ await setWcsContent(page, `
449
+ <wcs-select>
450
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
451
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
452
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
453
+ </wcs-select>
454
+ `);
455
+ const select = page.locator('wcs-select');
456
+ // Open the overlay
457
+ await select.focus();
458
+ await page.keyboard.press('Enter');
459
+ await expect(select).toHaveClass(/expanded/);
460
+ // When
461
+ await page.keyboard.press('Escape');
462
+ // Then
463
+ await expect(select).not.toHaveClass(/expanded/);
464
+ await expect(select).toBeFocused();
465
+ });
466
+ test('close the overlay on Alt + ArrowUp keys pressed and focus select control', async ({ page }) => {
467
+ // Given
468
+ await setWcsContent(page, `
469
+ <wcs-select>
470
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
471
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
472
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
473
+ </wcs-select>
474
+ `);
475
+ const select = page.locator('wcs-select');
476
+ // Open the overlay
477
+ await select.focus();
478
+ await page.keyboard.press('Enter');
479
+ await expect(select).toHaveClass(/expanded/);
480
+ // When
481
+ await page.keyboard.down('Alt');
482
+ await page.keyboard.press('ArrowUp');
483
+ await page.keyboard.up('Alt');
484
+ // Then
485
+ await expect(select).not.toHaveClass(/expanded/);
486
+ await expect(select).toBeFocused();
487
+ });
488
+ test('close the overlay on Tab key pressed', async ({ page }) => {
489
+ // Given
490
+ await setWcsContent(page, `
491
+ <wcs-select>
492
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
493
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
494
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
495
+ </wcs-select>
496
+ `);
497
+ const select = page.locator('wcs-select');
498
+ // Open the overlay
499
+ await select.focus();
500
+ await page.keyboard.press('Enter');
501
+ await expect(select).toHaveClass(/expanded/);
502
+ // When
503
+ await page.keyboard.press('Tab');
504
+ // Then
505
+ await expect(select).not.toHaveClass(/expanded/);
506
+ });
507
+ test('close the overlay on Tab + Shift keys pressed', async ({ page }) => {
508
+ // Given
509
+ await setWcsContent(page, `
510
+ <wcs-select>
511
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
512
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
513
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
514
+ </wcs-select>
515
+ `);
516
+ const select = page.locator('wcs-select');
517
+ // Open the overlay
518
+ await select.focus();
519
+ await page.keyboard.press('Enter');
520
+ await expect(select).toHaveClass(/expanded/);
521
+ // When
522
+ await page.keyboard.down('Shift');
523
+ await page.keyboard.press('Tab');
524
+ await page.keyboard.up('Shift');
525
+ // Then
526
+ await expect(select).not.toHaveClass(/expanded/);
527
+ });
528
+ test('choose the current option on Enter key pressed', async ({ page }) => {
529
+ // Given
530
+ await setWcsContent(page, `
531
+ <wcs-select>
532
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
533
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
534
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
535
+ </wcs-select>
536
+ `);
537
+ const select = page.locator('wcs-select');
538
+ const changeSpy = await page.spyOnEvent('wcsChange');
539
+ // Open the overlay
540
+ await select.focus();
541
+ await page.keyboard.press('Enter');
542
+ await expect(select).toHaveClass(/expanded/);
543
+ // When
544
+ await page.keyboard.press('Enter');
545
+ await page.waitForChanges();
546
+ // Then
547
+ const label = select.locator('label').first();
548
+ await expect(label).toHaveText('Option 2');
549
+ expect(changeSpy).toHaveReceivedEventTimes(1);
550
+ expect(changeSpy).toHaveFirstReceivedEventDetail({ value: 'option2' });
551
+ });
552
+ test('move focus to next option on Down Arrow key down', async ({ page }) => {
553
+ // Given
554
+ await setWcsContent(page, `
555
+ <wcs-select>
556
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
557
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
558
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
559
+ </wcs-select>
560
+ `);
561
+ const select = page.locator('wcs-select');
562
+ const changeSpy = await page.spyOnEvent('wcsChange');
563
+ // Open the overlay
564
+ await select.focus();
565
+ await page.keyboard.press('Enter');
566
+ await expect(select).toHaveClass(/expanded/);
567
+ // When
568
+ await page.keyboard.press('ArrowDown');
569
+ // Then
570
+ const focusedOption = page.locator('wcs-select-option:focus');
571
+ await expect(focusedOption).toHaveAttribute('value', 'option3');
572
+ await expect(async () => {
573
+ expect(changeSpy).toHaveReceivedEventTimes(0);
574
+ }).toPass();
575
+ });
576
+ });
577
+ test.describe('Keyboard navigation when select is closed and multiple', () => {
578
+ test('move focus into the first enabled option on Down Arrow key pressed', async ({ page }) => {
579
+ // Given
580
+ await setWcsContent(page, `
581
+ <wcs-select multiple="">
582
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
583
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
584
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
585
+ </wcs-select>
586
+ `);
587
+ const select = page.locator('wcs-select');
588
+ const changeSpy = await page.spyOnEvent('wcsChange');
589
+ // When
590
+ await select.focus();
591
+ await page.keyboard.press('ArrowDown');
592
+ // Then
593
+ const focusedOption = page.locator('wcs-select-option:focus');
594
+ await expect(focusedOption).toHaveAttribute('value', 'option2');
595
+ await expect(async () => {
596
+ expect(changeSpy).toHaveReceivedEventTimes(0);
597
+ }).toPass();
598
+ });
599
+ test('move focus into the first enabled option on Enter key pressed', async ({ page }) => {
600
+ // Given
601
+ await setWcsContent(page, `
602
+ <wcs-select multiple="">
603
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
604
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
605
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
606
+ </wcs-select>
607
+ `);
608
+ const select = page.locator('wcs-select');
609
+ const changeSpy = await page.spyOnEvent('wcsChange');
610
+ // When
611
+ await select.focus();
612
+ await page.keyboard.press('Enter');
613
+ // Then
614
+ await expect(select).toHaveClass(/expanded/);
615
+ const focusedOption = page.locator('wcs-select-option:focus');
616
+ await expect(focusedOption).toHaveAttribute('value', 'option2');
617
+ await expect(async () => {
618
+ expect(changeSpy).toHaveReceivedEventTimes(0);
619
+ }).toPass();
620
+ });
621
+ test('focuses last selected option when opening with keyboard after programmatic value change', async ({ page }) => {
622
+ // Given
623
+ await setWcsContent(page, `
624
+ <wcs-select multiple>
625
+ <wcs-select-option value="option1">Option 1</wcs-select-option>
626
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
627
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
628
+ </wcs-select>
629
+ `);
630
+ const select = page.locator('wcs-select');
631
+ // When
632
+ await select.evaluate((el) => el.value = ['option1', 'option2']);
633
+ await select.focus();
634
+ await page.keyboard.press('Enter'); // Open select with keyboard
635
+ // Then
636
+ await expect(select).toHaveClass(/expanded/);
637
+ const focusedOption = page.locator('wcs-select-option:focus');
638
+ await expect(focusedOption).toHaveAttribute('value', 'option2'); // Should focus the last option in the array
639
+ });
640
+ });
641
+ test.describe('Keyboard navigation when select opened and multiple', () => {
642
+ test('close the overlay on Tab key pressed and not focus an checkbox', async ({ page }) => {
643
+ // Given
644
+ await setWcsContent(page, `
645
+ <wcs-select multiple="">
646
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
647
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
648
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
649
+ </wcs-select>
650
+ `);
651
+ const select = page.locator('wcs-select');
652
+ // Open the overlay
653
+ await select.focus();
654
+ await page.keyboard.press('Enter');
655
+ await expect(select).toHaveClass(/expanded/);
656
+ // When
657
+ await page.keyboard.press('Tab');
658
+ // Then
659
+ await expect(select).not.toHaveClass(/expanded/);
660
+ });
661
+ });
662
+ test.describe('Options', () => {
663
+ test('Adds selected attribute to selected option', async ({ page }) => {
664
+ // Given
665
+ await setWcsContent(page, `
666
+ <wcs-select>
667
+ <wcs-select-option value="1">One</wcs-select-option>
668
+ </wcs-select>
669
+ `);
670
+ const select = page.locator('wcs-select');
671
+ const option = page.locator('wcs-select > wcs-select-option');
672
+ // When
673
+ await select.click();
674
+ await expect(select).toHaveClass(/expanded/);
675
+ await option.click();
676
+ // Then
677
+ await expect(option).toHaveAttribute('selected');
678
+ });
679
+ test('Removes selected attribute from previously selected options', async ({ page }) => {
680
+ // Given
681
+ await setWcsContent(page, `
682
+ <wcs-select>
683
+ <wcs-select-option value="1">One</wcs-select-option>
684
+ <wcs-select-option value="2">Two</wcs-select-option>
685
+ </wcs-select>
686
+ `);
687
+ const select = page.locator('wcs-select');
688
+ const options = page.locator('wcs-select > wcs-select-option');
689
+ // When
690
+ await select.click();
691
+ await expect(select).toHaveClass(/expanded/);
692
+ await options.nth(0).click();
693
+ await select.click(); // As it is not multiple we need to open it once again
694
+ await expect(select).toHaveClass(/expanded/);
695
+ await options.nth(1).click();
696
+ // Then
697
+ await expect(options.nth(0)).not.toHaveAttribute('selected');
698
+ await expect(options.nth(1)).toHaveAttribute('selected');
699
+ });
700
+ test('Must not let a user select a disabled option', async ({ page }) => {
701
+ // Given
702
+ await setWcsContent(page, `
703
+ <wcs-select>
704
+ <wcs-select-option value="1" disabled>One</wcs-select-option>
705
+ </wcs-select>
706
+ `);
707
+ const select = page.locator('wcs-select');
708
+ const option = page.locator('wcs-select > wcs-select-option');
709
+ // When
710
+ await select.click();
711
+ await expect(select).toHaveClass(/expanded/);
712
+ // Use dispatchEvent instead of click since disabled options may not be clickable
713
+ await option.dispatchEvent('click');
714
+ // Then
715
+ await expect(select).not.toHaveAttribute('value');
716
+ });
717
+ });
718
+ test('Propagate wcsSelectChangeEvent when a new value is selected', async ({ page }) => {
719
+ // Given
720
+ await setWcsContent(page, `
721
+ <wcs-select>
722
+ <wcs-select-option value="1">One</wcs-select-option>
723
+ </wcs-select>
724
+ `);
725
+ const select = page.locator('wcs-select');
726
+ const option = page.locator('wcs-select > wcs-select-option');
727
+ const changeSpy = await page.spyOnEvent('wcsChange');
728
+ // When
729
+ await select.click();
730
+ await expect(select).toHaveClass(/expanded/);
731
+ await option.click();
732
+ await page.waitForChanges();
733
+ // Then
734
+ expect(changeSpy).toHaveReceivedEventTimes(1);
735
+ expect(changeSpy).toHaveFirstReceivedEventDetail({ value: '1' });
736
+ });
737
+ test.describe('Focus management', () => {
738
+ test('after selection, focus is on the correct element', async ({ page }) => {
739
+ // Given
740
+ await setWcsContent(page, `
741
+ <wcs-select>
742
+ <wcs-select-option value="1">One</wcs-select-option>
743
+ <wcs-select-option value="2">Two</wcs-select-option>
744
+ </wcs-select>
745
+ `);
746
+ const select = page.locator('wcs-select');
747
+ // When
748
+ await select.focus();
749
+ await page.keyboard.press('Enter');
750
+ await expect(select).toHaveClass(/expanded/);
751
+ await page.keyboard.press('ArrowDown');
752
+ // Then
753
+ const focusedOption = page.locator('wcs-select-option:focus');
754
+ await expect(focusedOption).toHaveAttribute('value', '2');
755
+ });
756
+ });
757
+ test('[Autocomplete] Input field is focusable', async ({ page }) => {
758
+ // Given
759
+ await setWcsContent(page, `
760
+ <wcs-select autocomplete="true">
761
+ <wcs-select-option value="1">One</wcs-select-option>
762
+ </wcs-select>
763
+ `);
764
+ const select = page.locator('wcs-select');
765
+ const nativeInput = page.locator('wcs-select input.autocomplete-field');
766
+ // When - Click to focus
767
+ await select.click();
768
+ // Then
769
+ await expect(nativeInput).toBeFocused();
770
+ });
771
+ test('[Autocomplete] filter is cleared when the select value is set to a falsy value', async ({ page }) => {
772
+ // Given
773
+ await setWcsContent(page, `
774
+ <wcs-select autocomplete>
775
+ <wcs-select-option value="1">One</wcs-select-option>
776
+ <wcs-select-option value="2">Two</wcs-select-option>
777
+ <wcs-select-option value="3">Three</wcs-select-option>
778
+ <wcs-select-option value="4">Four</wcs-select-option>
779
+ </wcs-select>
780
+ `);
781
+ const select = page.locator('wcs-select');
782
+ // When
783
+ await select.click();
784
+ await page.keyboard.type('One');
785
+ const firstSelectOption = page.locator('wcs-select > wcs-select-option').first();
786
+ await firstSelectOption.click();
787
+ await select.evaluate((el) => el.value = '');
788
+ await page.waitForTimeout(50);
789
+ // Then
790
+ await select.click();
791
+ await expect(select).toHaveClass(/expanded/);
792
+ const availableOptions = await page.locator('wcs-select > wcs-select-option:not([hidden])').count();
793
+ expect(availableOptions).toBe(4);
794
+ });
795
+ test('[Autocomplete] should not opened when initial value is set', async ({ page }) => {
796
+ // Given - When
797
+ await setWcsContent(page, `
798
+ <wcs-select autocomplete value="1">
799
+ <wcs-select-option value="1">One</wcs-select-option>
800
+ <wcs-select-option value="2">Two</wcs-select-option>
801
+ <wcs-select-option value="3">Three</wcs-select-option>
802
+ <wcs-select-option value="4">Four</wcs-select-option>
803
+ </wcs-select>
804
+ `);
805
+ const select = page.locator('wcs-select');
806
+ // Then
807
+ await expect(select).not.toHaveClass(/expanded/);
808
+ });
809
+ test('[Autocomplete] should not opened when set value programmatically', async ({ page }) => {
810
+ // Given - When
811
+ await setWcsContent(page, `
812
+ <wcs-select autocomplete value="1">
813
+ <wcs-select-option value="1">One</wcs-select-option>
814
+ <wcs-select-option value="2">Two</wcs-select-option>
815
+ <wcs-select-option value="3">Three</wcs-select-option>
816
+ <wcs-select-option value="4">Four</wcs-select-option>
817
+ </wcs-select>
818
+ `);
819
+ const select = page.locator('wcs-select');
820
+ await select.evaluate((el) => el.value = '1');
821
+ await page.waitForTimeout(50);
822
+ // Then
823
+ await expect(select).not.toHaveClass(/expanded/);
824
+ });
825
+ test('[Autocomplete] should opened when set value with user interaction', async ({ page }) => {
826
+ // Given
827
+ await setWcsContent(page, `
828
+ <wcs-select autocomplete>
829
+ <wcs-select-option value="1">One</wcs-select-option>
830
+ <wcs-select-option value="2">Two</wcs-select-option>
831
+ <wcs-select-option value="3">Three</wcs-select-option>
832
+ <wcs-select-option value="4">Four</wcs-select-option>
833
+ </wcs-select>
834
+ `);
835
+ const select = page.locator('wcs-select');
836
+ // When
837
+ await select.click();
838
+ await page.keyboard.type('O');
839
+ // Then
840
+ await expect(select).toHaveClass(/expanded/);
841
+ });
842
+ test.describe('[Autocomplete] Keyboard navigation when select closed', () => {
843
+ test('open listbox and move focus into the first enabled option on Arrow Down pressed', async ({ page }) => {
844
+ // Given
845
+ await setWcsContent(page, `
846
+ <wcs-select autocomplete="">
847
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
848
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
849
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
850
+ </wcs-select>
851
+ `);
852
+ const select = page.locator('wcs-select');
853
+ // When
854
+ await select.click();
855
+ await page.keyboard.press('ArrowDown');
856
+ // Then
857
+ const visuallyFocusedOption = page.locator('wcs-select-option[highlighted]');
858
+ await expect(visuallyFocusedOption).toHaveCount(1);
859
+ await expect(visuallyFocusedOption).toHaveAttribute('value', 'option2');
860
+ await expect(select).toHaveClass(/expanded/);
861
+ });
862
+ test('open listbox without moveing on Alt + Arrow Down pressed', async ({ page }) => {
863
+ // Given
864
+ await setWcsContent(page, `
865
+ <wcs-select autocomplete="">
866
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
867
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
868
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
869
+ </wcs-select>
870
+ `);
871
+ const select = page.locator('wcs-select');
872
+ // When
873
+ await select.click();
874
+ await page.keyboard.down('Alt');
875
+ await page.keyboard.press('ArrowDown');
876
+ await page.keyboard.up('Alt');
877
+ // Then
878
+ await expect(select).toHaveClass(/expanded/);
879
+ const anyVisuallyFocusedOption = page.locator('wcs-select-option[highlighted]');
880
+ await expect(anyVisuallyFocusedOption).toHaveCount(0);
881
+ });
882
+ test('clear textbox on Escape pressed', async ({ page }) => {
883
+ // Given
884
+ await setWcsContent(page, `
885
+ <wcs-select autocomplete="">
886
+ <wcs-select-option value="option1" disabled>Option 1</wcs-select-option>
887
+ <wcs-select-option value="option2">Option 2</wcs-select-option>
888
+ <wcs-select-option value="option3">Option 3</wcs-select-option>
889
+ </wcs-select>
890
+ `);
891
+ const select = page.locator('wcs-select');
892
+ // When
893
+ await select.click(); // Focus the input (delegate focus)
894
+ await page.keyboard.type('test');
895
+ await page.waitForTimeout(50);
896
+ await page.keyboard.press('Escape'); // Close the listbox
897
+ await page.waitForTimeout(50);
898
+ await expect(select).not.toHaveClass(/expanded/);
899
+ await page.keyboard.press('Escape'); // Clear the textbox
900
+ await page.waitForTimeout(50);
901
+ // Then
902
+ const nativeInput = page.locator('wcs-select input.autocomplete-field');
903
+ await expect(nativeInput).toHaveValue('');
904
+ });
905
+ });
906
+ test.describe('[Autocomplete] Keyboard navigation when select expanded', () => {
907
+ test('close listbox on Escape', async ({ page }) => {
908
+ // Given
909
+ await setWcsContent(page, `
910
+ <wcs-select autocomplete="">
911
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
912
+ <wcs-select-option value="option2">Banana</wcs-select-option>
913
+ <wcs-select-option value="option3">Peach</wcs-select-option>
914
+ </wcs-select>
915
+ `);
916
+ const select = page.locator('wcs-select');
917
+ // When
918
+ await select.click();
919
+ await expect(select).toHaveClass(/expanded/);
920
+ await page.keyboard.press('Escape');
921
+ // Then
922
+ await expect(select).not.toHaveClass(/expanded/);
923
+ });
924
+ test('stay opened on Enter when no option are highlighted', async ({ page }) => {
925
+ // Given
926
+ await setWcsContent(page, `
927
+ <wcs-select autocomplete="">
928
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
929
+ <wcs-select-option value="option2">Banana</wcs-select-option>
930
+ <wcs-select-option value="option3">Peach</wcs-select-option>
931
+ </wcs-select>
932
+ `);
933
+ const select = page.locator('wcs-select');
934
+ // When
935
+ await select.click();
936
+ await page.keyboard.press('Enter');
937
+ // Then
938
+ await expect(select).toHaveClass(/expanded/);
939
+ });
940
+ test('Close overlay when an highlighted option is selected with Enter keypress', async ({ page }) => {
941
+ // Given
942
+ await setWcsContent(page, `
943
+ <wcs-select autocomplete="">
944
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
945
+ <wcs-select-option value="option2">Banana</wcs-select-option>
946
+ <wcs-select-option value="option3">Peach</wcs-select-option>
947
+ </wcs-select>
948
+ `);
949
+ const select = page.locator('wcs-select');
950
+ // When
951
+ await select.click();
952
+ await page.keyboard.press('ArrowDown');
953
+ await page.keyboard.press('Enter');
954
+ // Then
955
+ await expect(select).not.toHaveClass(/expanded/);
956
+ });
957
+ test('focus last option on Arrow Up', async ({ page }) => {
958
+ // Given
959
+ await setWcsContent(page, `
960
+ <wcs-select autocomplete="">
961
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
962
+ <wcs-select-option value="option2">Banana</wcs-select-option>
963
+ <wcs-select-option value="option3">Peach</wcs-select-option>
964
+ </wcs-select>
965
+ `);
966
+ const select = page.locator('wcs-select');
967
+ // When
968
+ await focusAutocompleteInput(select);
969
+ await page.keyboard.press('ArrowUp');
970
+ // Then
971
+ const lastDisabledSelectOption = page.locator('wcs-select-option:not([disabled])').last();
972
+ await expect(lastDisabledSelectOption).toHaveAttribute('highlighted', '');
973
+ });
974
+ test('focus first option on Arrow Down', async ({ page }) => {
975
+ // Given
976
+ await setWcsContent(page, `
977
+ <wcs-select autocomplete="">
978
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
979
+ <wcs-select-option value="option2">Banana</wcs-select-option>
980
+ <wcs-select-option value="option3">Peach</wcs-select-option>
981
+ </wcs-select>
982
+ `);
983
+ const select = page.locator('wcs-select');
984
+ // When
985
+ await select.click();
986
+ await page.keyboard.press('ArrowDown');
987
+ const firstNotDisabledSelectOption = page.locator('wcs-select-option:not([disabled])').first();
988
+ // Then
989
+ await expect(select).toHaveClass(/expanded/);
990
+ await expect(firstNotDisabledSelectOption).toHaveAttribute('highlighted', '');
991
+ });
992
+ test('replace text, close listbox, focus textbox on Enter', async ({ page }) => {
993
+ // Given
994
+ await setWcsContent(page, `
995
+ <wcs-select autocomplete="">
996
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
997
+ <wcs-select-option value="option2">Banana</wcs-select-option>
998
+ <wcs-select-option value="option3">Peach</wcs-select-option>
999
+ </wcs-select>
1000
+ `);
1001
+ const select = page.locator('wcs-select');
1002
+ // When
1003
+ await select.click();
1004
+ await page.keyboard.press('ArrowDown');
1005
+ await expect(select).toHaveClass(/expanded/);
1006
+ const firstNotDisabledSelectOption = page.locator('wcs-select-option:not([disabled])').first();
1007
+ await expect(firstNotDisabledSelectOption).toHaveAttribute('highlighted', '');
1008
+ await expect(firstNotDisabledSelectOption).toHaveAttribute('value', 'option2');
1009
+ await page.keyboard.press('Enter');
1010
+ // Then
1011
+ await expect(select).not.toHaveClass(/expanded/);
1012
+ const nativeInput = page.locator('wcs-select input.autocomplete-field');
1013
+ await expect(nativeInput).toHaveValue('Banana');
1014
+ // Check input is focused
1015
+ await expect(nativeInput).toBeFocused();
1016
+ });
1017
+ test('cycle to next option when Arrow Down', async ({ page }) => {
1018
+ // Given
1019
+ await setWcsContent(page, `
1020
+ <wcs-select autocomplete="">
1021
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
1022
+ <wcs-select-option value="option2">Banana</wcs-select-option>
1023
+ <wcs-select-option value="option3">Peach</wcs-select-option>
1024
+ </wcs-select>
1025
+ `);
1026
+ const select = page.locator('wcs-select');
1027
+ // When
1028
+ await focusAutocompleteInput(select);
1029
+ await page.keyboard.press('ArrowDown'); // Going to option2
1030
+ await page.keyboard.press('ArrowDown'); // Going to option3
1031
+ await page.keyboard.press('ArrowDown'); // Going back to option2
1032
+ // Then
1033
+ const visuallyFocusedOption = page.locator('wcs-select-option[highlighted]');
1034
+ await expect(visuallyFocusedOption).toHaveAttribute('value', 'option2');
1035
+ });
1036
+ test('cycle to previous option when Arrow Up', async ({ page }) => {
1037
+ // Given
1038
+ await setWcsContent(page, `
1039
+ <wcs-select autocomplete="">
1040
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
1041
+ <wcs-select-option value="option2">Banana</wcs-select-option>
1042
+ <wcs-select-option value="option3">Peach</wcs-select-option>
1043
+ </wcs-select>
1044
+ `);
1045
+ const select = page.locator('wcs-select');
1046
+ // When
1047
+ await focusAutocompleteInput(select);
1048
+ const inputAutocomplete = select.locator('input.autocomplete-field');
1049
+ await expect(inputAutocomplete).toBeFocused();
1050
+ await page.keyboard.press('ArrowUp'); // Going to option3
1051
+ await page.keyboard.press('ArrowUp'); // Going to option2
1052
+ await page.keyboard.press('ArrowUp'); // Going back to option3
1053
+ // Then
1054
+ const visuallyFocusedOption = page.locator('wcs-select-option[highlighted]');
1055
+ await expect(visuallyFocusedOption).toHaveAttribute('value', 'option3');
1056
+ });
1057
+ test('focus textbox, filter listbox, remove visual focus from listbox when any printable character', async ({ page }) => {
1058
+ // Given
1059
+ await setWcsContent(page, `
1060
+ <wcs-select autocomplete="">
1061
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
1062
+ <wcs-select-option value="option2">Banana</wcs-select-option>
1063
+ <wcs-select-option value="option3">Peach</wcs-select-option>
1064
+ </wcs-select>
1065
+ `);
1066
+ const select = page.locator('wcs-select');
1067
+ const inputAutocomplete = select.locator('input.autocomplete-field');
1068
+ // When
1069
+ await select.click();
1070
+ await expect(inputAutocomplete).toBeFocused();
1071
+ await page.keyboard.press('a');
1072
+ // Then
1073
+ // Check input is focused
1074
+ await expect(inputAutocomplete).toBeFocused();
1075
+ // Check filter is applied (fewer options visible)
1076
+ const visibleOptions = await page.locator('wcs-select-option:not([aria-hidden="true"])').count();
1077
+ expect(visibleOptions).toBeLessThan(3);
1078
+ // Check no option is highlighted
1079
+ const visuallyFocusedOption = page.locator('wcs-select-option[highlighted]');
1080
+ await expect(visuallyFocusedOption).toHaveCount(0);
1081
+ });
1082
+ test('close listbox, focus textbox on Escape', async ({ page }) => {
1083
+ // Given
1084
+ await setWcsContent(page, `
1085
+ <wcs-select autocomplete="">
1086
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
1087
+ <wcs-select-option value="option2">Banana</wcs-select-option>
1088
+ <wcs-select-option value="option3">Peach</wcs-select-option>
1089
+ </wcs-select>
1090
+ `);
1091
+ const select = page.locator('wcs-select');
1092
+ // When
1093
+ await select.click();
1094
+ await expect(select).toHaveClass(/expanded/);
1095
+ await page.keyboard.press('Escape');
1096
+ // Then
1097
+ await expect(select).not.toHaveClass(/expanded/);
1098
+ const inputAutocomplete = select.locator('input.autocomplete-field');
1099
+ await expect(inputAutocomplete).toBeFocused();
1100
+ });
1101
+ test('focus textbox, move cursor when Left or Right Arrow', async ({ page }) => {
1102
+ // Given
1103
+ await setWcsContent(page, `
1104
+ <wcs-select autocomplete="">
1105
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
1106
+ <wcs-select-option value="option2">Banana</wcs-select-option>
1107
+ <wcs-select-option value="option3">Peach</wcs-select-option>
1108
+ </wcs-select>
1109
+ `);
1110
+ const select = page.locator('wcs-select');
1111
+ const inputAutocomplete = select.locator('input.autocomplete-field');
1112
+ const typedText = 'test';
1113
+ // When
1114
+ await select.click();
1115
+ await expect(select).toHaveClass(/expanded/);
1116
+ await page.keyboard.type(typedText);
1117
+ await page.keyboard.press('ArrowLeft');
1118
+ await page.keyboard.press('ArrowRight');
1119
+ // Then
1120
+ await expect(inputAutocomplete).toBeFocused();
1121
+ const cursorPositionAfter = await select.evaluate((el) => {
1122
+ var _a;
1123
+ const input = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('input.autocomplete-field');
1124
+ return input === null || input === void 0 ? void 0 : input.selectionStart;
1125
+ });
1126
+ expect(cursorPositionAfter).toBe(typedText.length);
1127
+ });
1128
+ test('focus textbox, move cursor to the start of the text when Home pressed', async ({ page }) => {
1129
+ // Given
1130
+ await setWcsContent(page, `
1131
+ <wcs-select autocomplete="">
1132
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
1133
+ <wcs-select-option value="option2">Banana</wcs-select-option>
1134
+ <wcs-select-option value="option3">Peach</wcs-select-option>
1135
+ </wcs-select>
1136
+ `);
1137
+ const select = page.locator('wcs-select');
1138
+ const inputAutocomplete = select.locator('input.autocomplete-field');
1139
+ const typedText = 'test';
1140
+ // When
1141
+ await select.click();
1142
+ await page.keyboard.type(typedText);
1143
+ await page.keyboard.press('Home');
1144
+ // Then
1145
+ await expect(inputAutocomplete).toBeFocused();
1146
+ const cursorPositionAfter = await select.evaluate((el) => {
1147
+ var _a;
1148
+ const input = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('input.autocomplete-field');
1149
+ return input === null || input === void 0 ? void 0 : input.selectionStart;
1150
+ });
1151
+ expect(cursorPositionAfter).toBe(0);
1152
+ });
1153
+ test('focus textbox, move cursor to the end of the text when End pressed', async ({ page }) => {
1154
+ // Given
1155
+ await setWcsContent(page, `
1156
+ <wcs-select autocomplete="">
1157
+ <wcs-select-option value="option1" disabled>Apple</wcs-select-option>
1158
+ <wcs-select-option value="option2">Banana</wcs-select-option>
1159
+ <wcs-select-option value="option3">Peach</wcs-select-option>
1160
+ </wcs-select>
1161
+ `);
1162
+ const select = page.locator('wcs-select');
1163
+ const inputAutocomplete = select.locator('input.autocomplete-field');
1164
+ const typedText = 'test';
1165
+ // When
1166
+ await select.click();
1167
+ await page.keyboard.press('t');
1168
+ await page.keyboard.press('e');
1169
+ await page.keyboard.press('s');
1170
+ await page.keyboard.press('t');
1171
+ await page.keyboard.press('End');
1172
+ // Then
1173
+ await expect(inputAutocomplete).toBeFocused();
1174
+ const cursorPositionAfter = await select.evaluate((el) => {
1175
+ var _a;
1176
+ const input = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('input.autocomplete-field');
1177
+ return input === null || input === void 0 ? void 0 : input.selectionStart;
1178
+ });
1179
+ expect(cursorPositionAfter).toBe(typedText.length);
1180
+ });
1181
+ });
1182
+ test('Should handle asynchronous options loading with an initial value and update the label', async ({ page }) => {
1183
+ // Given
1184
+ await setWcsContent(page, `
1185
+ <wcs-select value="2">
1186
+ </wcs-select>
1187
+ `);
1188
+ const select = page.locator('wcs-select');
1189
+ const label = page.locator('label').first();
1190
+ // Verify no label initially (element exists but has no text content)
1191
+ await expect(label).toHaveText('');
1192
+ // When - Add options dynamically
1193
+ await select.evaluate((el) => {
1194
+ el.innerHTML = `
1195
+ <wcs-select-option value="1">One</wcs-select-option>
1196
+ <wcs-select-option value="2">Two</wcs-select-option>
1197
+ <wcs-select-option value="3">Three</wcs-select-option>
1198
+ <wcs-select-option value="4">Four</wcs-select-option>
1199
+ `;
1200
+ });
1201
+ // Then - Verify label is updated
1202
+ await expect(label).toHaveText('Two');
1203
+ });
1204
+ test('[Multiple] Should handle asynchronous options loading with an initial value and update the label', async ({ page }) => {
1205
+ // Given
1206
+ await setWcsContent(page, `
1207
+ <wcs-select multiple>
1208
+ </wcs-select>
1209
+ `);
1210
+ const select = page.locator('wcs-select');
1211
+ const label = page.locator('label').first();
1212
+ await select.evaluate((el) => el.value = ['2', '3']);
1213
+ // Verify no label initially (element exists but has no text content)
1214
+ await expect(label).toHaveText('');
1215
+ // When - Add options dynamically
1216
+ await select.evaluate((el) => {
1217
+ el.innerHTML = `
1218
+ <wcs-select-option value="1">One</wcs-select-option>
1219
+ <wcs-select-option value="2">Two</wcs-select-option>
1220
+ <wcs-select-option value="3">Three</wcs-select-option>
1221
+ <wcs-select-option value="4">Four</wcs-select-option>
1222
+ `;
1223
+ });
1224
+ // Then - Verify label is updated
1225
+ await expect(label).toHaveText('Two, Three');
1226
+ });
1227
+ test('[ServerMode] Should synchronise selected value after slot change', async ({ page }) => {
1228
+ await setWcsContent(page, `
1229
+ <wcs-select autocomplete server-mode value="3">
1230
+ <wcs-select-option value="1">One</wcs-select-option>
1231
+ <wcs-select-option value="2">Two</wcs-select-option>
1232
+ <wcs-select-option value="3">Three</wcs-select-option>
1233
+ <wcs-select-option value="4">Four</wcs-select-option>
1234
+ </wcs-select>
1235
+ `);
1236
+ const options = [
1237
+ {
1238
+ value: '1',
1239
+ displayText: 'One'
1240
+ },
1241
+ {
1242
+ value: '2',
1243
+ displayText: 'Two'
1244
+ },
1245
+ {
1246
+ value: '3',
1247
+ displayText: 'Three'
1248
+ },
1249
+ {
1250
+ value: '4',
1251
+ displayText: 'Four'
1252
+ }
1253
+ ];
1254
+ const select = page.locator('wcs-select');
1255
+ const autocompleteInput = page.locator('input.autocomplete-field'); // initially the value is "Three"
1256
+ const optionThree = page.locator('wcs-select-option[value="3"]');
1257
+ await select.evaluate((el, options) => {
1258
+ el.addEventListener('wcsFilterChange', (event) => {
1259
+ const htmlSelectOptions = options
1260
+ .filter((o) => o.displayText.toLowerCase().includes(event.detail.value.toLowerCase()))
1261
+ .map((o) => `<wcs-select-option value="${o.value}">${o.displayText}</wcs-select-option>`);
1262
+ el.innerHTML = htmlSelectOptions.join('');
1263
+ });
1264
+ }, options);
1265
+ await autocompleteInput.press('End'); // place at the end of input
1266
+ await autocompleteInput.press('Backspace'); // "Thre"
1267
+ await autocompleteInput.press('Backspace'); // "Thr"
1268
+ await page.waitForChanges();
1269
+ await expect(optionThree).toHaveAttribute('selected');
1270
+ });
1271
+ test('[ServerMode] Should not reset displayText if options are changes asynchronously', async ({ page }) => {
1272
+ await setWcsContent(page, `
1273
+ <wcs-select autocomplete server-mode>
1274
+ </wcs-select>
1275
+ `);
1276
+ const select = page.locator('wcs-select');
1277
+ await select.evaluate((el) => el.value = '2');
1278
+ await page.waitForChanges();
1279
+ const options = [
1280
+ {
1281
+ value: '1',
1282
+ displayText: 'One'
1283
+ },
1284
+ {
1285
+ value: '2',
1286
+ displayText: 'Two'
1287
+ },
1288
+ {
1289
+ value: '3',
1290
+ displayText: 'Three'
1291
+ },
1292
+ {
1293
+ value: '4',
1294
+ displayText: 'Four'
1295
+ }
1296
+ ];
1297
+ await select.evaluate((el, options) => {
1298
+ el.addEventListener('wcsFilterChange', (event) => {
1299
+ const htmlSelectOptions = options
1300
+ .filter((o) => o.displayText.toLowerCase().includes(event.detail.value))
1301
+ .map((o) => `<wcs-select-option value="${o.value}">${o.displayText}</wcs-select-option>`);
1302
+ el.innerHTML = htmlSelectOptions.join('');
1303
+ });
1304
+ }, options);
1305
+ const autocompleteInput = select.locator('input.autocomplete-field');
1306
+ // Before options are asynchronously added, the input value should still be empty (no matching option yet)
1307
+ await expect(autocompleteInput).toHaveJSProperty('value', '');
1308
+ // Add options
1309
+ await page.$eval('wcs-select', (el) => {
1310
+ el.innerHTML = `
1311
+ <wcs-select-option value="1">One</wcs-select-option>
1312
+ <wcs-select-option value="2">Two</wcs-select-option>
1313
+ <wcs-select-option value="3">Three</wcs-select-option>
1314
+ <wcs-select-option value="4">Four</wcs-select-option>
1315
+ `;
1316
+ });
1317
+ await page.waitForChanges();
1318
+ // After async insertion, the component should have propagated the displayText to the input value
1319
+ await expect(autocompleteInput).toHaveJSProperty('value', 'Two');
1320
+ await autocompleteInput.press('End'); // place at the end of input
1321
+ await autocompleteInput.press('Backspace'); // "Tw"
1322
+ await autocompleteInput.press('Backspace'); // "T"
1323
+ await autocompleteInput.press('Backspace'); // ""
1324
+ await autocompleteInput.press('o');
1325
+ await autocompleteInput.press('n');
1326
+ await page.waitForChanges();
1327
+ await select.evaluate((el) => el.value = '3');
1328
+ await page.waitForChanges();
1329
+ await expect(autocompleteInput).toHaveJSProperty('value', 'Three');
1330
+ });
1331
+ test('[ServerMode][Autocomplete] Emits filter change events while typing and when clearing after selection', async ({ page }) => {
1332
+ await setWcsContent(page, `
1333
+ <wcs-select autocomplete server-mode>
1334
+ <wcs-select-option value="ain">Ain</wcs-select-option>
1335
+ <wcs-select-option value="aude">Aude</wcs-select-option>
1336
+ <wcs-select-option value="ardeche">Ardèche</wcs-select-option>
1337
+ <wcs-select-option value="bas-rhin">Bas-Rhin</wcs-select-option>
1338
+ </wcs-select>
1339
+ `);
1340
+ const options = [
1341
+ {
1342
+ value: 'ain',
1343
+ displayText: 'Ain'
1344
+ },
1345
+ {
1346
+ value: 'aude',
1347
+ displayText: 'Aude'
1348
+ },
1349
+ {
1350
+ value: 'ardeche',
1351
+ displayText: 'Ardèche'
1352
+ },
1353
+ {
1354
+ value: 'bas-rhin',
1355
+ displayText: 'Bas-Rhin'
1356
+ }
1357
+ ];
1358
+ const select = page.locator('wcs-select');
1359
+ await select.evaluate((el) => el.open());
1360
+ await page.waitForChanges();
1361
+ await select.evaluate((el, options) => {
1362
+ el.addEventListener('wcsFilterChange', (event) => {
1363
+ const htmlSelectOptions = options
1364
+ .filter((o) => o.displayText.toLowerCase().includes(event.detail.value.toLowerCase()))
1365
+ .map((o) => `<wcs-select-option value="${o.value}">${o.displayText}</wcs-select-option>`);
1366
+ el.innerHTML = htmlSelectOptions.join('');
1367
+ });
1368
+ }, options);
1369
+ const filterChangeSpy = await select.spyOnEvent('wcsFilterChange');
1370
+ const input = page.locator('input.autocomplete-field');
1371
+ // Type 'ain' to filter
1372
+ await input.press('a');
1373
+ await input.press('i');
1374
+ await input.press('n');
1375
+ await page.waitForChanges();
1376
+ expect(filterChangeSpy).toHaveReceivedEventTimes(3);
1377
+ expect(filterChangeSpy).toHaveNthReceivedEventDetail(0, { value: 'a' });
1378
+ expect(filterChangeSpy).toHaveNthReceivedEventDetail(1, { value: 'ai' });
1379
+ expect(filterChangeSpy).toHaveNthReceivedEventDetail(2, { value: 'ain' });
1380
+ // Select Ain: find option and click (should emit a filter event)
1381
+ const optionAin = page.locator('wcs-select > wcs-select-option[value="ain"]');
1382
+ expect(optionAin).not.toBeNull();
1383
+ await optionAin.click();
1384
+ await page.waitForChanges();
1385
+ // We ensure that we receive 3 typing events + 1 event of selection. It's important for consummers
1386
+ // in order to re-fetch the value of the selected option
1387
+ expect(filterChangeSpy).toHaveReceivedEventTimes(4);
1388
+ // Input value replaced by selected option label
1389
+ await expect(input).toHaveJSProperty('value', 'Ain');
1390
+ expect(filterChangeSpy).toHaveNthReceivedEventDetail(3, { value: 'Ain' });
1391
+ await input.press('Backspace'); // Ai
1392
+ await page.waitForChanges();
1393
+ expect(filterChangeSpy).toHaveNthReceivedEventDetail(4, { value: 'Ai' });
1394
+ await input.press('Backspace'); // A
1395
+ await page.waitForChanges();
1396
+ expect(filterChangeSpy).toHaveNthReceivedEventDetail(5, { value: 'A' });
1397
+ await input.press('Backspace'); // vide
1398
+ await page.waitForChanges();
1399
+ expect(filterChangeSpy).toHaveNthReceivedEventDetail(6, { value: '' });
1400
+ // Field must stay empty (no hydration after manual clear)
1401
+ await expect(input).toHaveJSProperty('value', '');
1402
+ });
1403
+ test('[ServerMode][Autocomplete] Should not override user input with the selected option label when the options list changes', async ({ page }) => {
1404
+ await setWcsContent(page, `
1405
+ <wcs-select autocomplete server-mode>
1406
+ <wcs-select-option value="ain">Ain</wcs-select-option>
1407
+ <wcs-select-option value="aude">Aude</wcs-select-option>
1408
+ <wcs-select-option value="ardeche">Ardèche</wcs-select-option>
1409
+ <wcs-select-option value="bas-rhin">Bas-Rhin</wcs-select-option>
1410
+ </wcs-select>
1411
+ `);
1412
+ const options = [
1413
+ {
1414
+ value: 'ain',
1415
+ displayText: 'Ain'
1416
+ },
1417
+ {
1418
+ value: 'aude',
1419
+ displayText: 'Aude'
1420
+ },
1421
+ {
1422
+ value: 'ardeche',
1423
+ displayText: 'Ardèche'
1424
+ },
1425
+ {
1426
+ value: 'bas-rhin',
1427
+ displayText: 'Bas-Rhin'
1428
+ }
1429
+ ];
1430
+ const select = page.locator('wcs-select');
1431
+ await select.evaluate((el) => el.value = 'ain');
1432
+ await page.waitForChanges();
1433
+ await select.evaluate((el, options) => {
1434
+ el.addEventListener('wcsFilterChange', (event) => {
1435
+ const htmlSelectOptions = options
1436
+ .filter((o) => o.displayText.includes(event.detail.value))
1437
+ .map((o) => `<wcs-select-option value="${o.value}">${o.displayText}</wcs-select-option>`);
1438
+ el.innerHTML = htmlSelectOptions.join('');
1439
+ });
1440
+ }, options);
1441
+ const input = page.locator('input.autocomplete-field');
1442
+ // on sélectionne une valeur => autocomplete = valeur qu'on a sélectionné
1443
+ await expect(input).toHaveJSProperty('value', 'Ain');
1444
+ await input.press('End'); // place at the end of input
1445
+ await input.press('Backspace');
1446
+ await input.press('Backspace');
1447
+ await page.waitForChanges();
1448
+ await expect(input).toHaveJSProperty('value', 'A');
1449
+ });
1450
+ test('[ServerMode][Autocomplete] should display option label in input when dynamically adding options', async ({ page }) => {
1451
+ await setWcsContent(page, `
1452
+ <wcs-select autocomplete server-mode>
1453
+ </wcs-select>
1454
+ `);
1455
+ const select = page.locator('wcs-select');
1456
+ const input = page.locator('input.autocomplete-field');
1457
+ await select.evaluate((el) => el.value = '1');
1458
+ await page.waitForChanges();
1459
+ await expect(input).toHaveJSProperty('value', '');
1460
+ await page.$eval('wcs-select', (el) => {
1461
+ el.innerHTML = `
1462
+ <wcs-select-option value="1">Un</wcs-select-option>
1463
+ `;
1464
+ });
1465
+ await page.waitForChanges();
1466
+ await expect(input).toHaveJSProperty('value', 'Un');
1467
+ await input.evaluate((el) => el.value = 'Trois');
1468
+ await select.evaluate((el) => el.value = '2');
1469
+ await page.waitForChanges();
1470
+ await expect(input).toHaveJSProperty('value', '');
1471
+ await page.$eval('wcs-select', (el) => {
1472
+ el.innerHTML = `
1473
+ <wcs-select-option value="2">Deux</wcs-select-option>
1474
+ `;
1475
+ });
1476
+ await expect(input).toHaveJSProperty('value', 'Deux');
1477
+ });
1478
+ test('[ServerMode][Autocomplete] should restore selected option label on blur when current value is not in filtered options', async ({ page }) => {
1479
+ await setWcsContent(page, `
1480
+ <wcs-select autocomplete server-mode value="3">
1481
+ <wcs-select-option value="1">Un</wcs-select-option>
1482
+ <wcs-select-option value="2">Deux</wcs-select-option>
1483
+ <wcs-select-option value="3">Trois</wcs-select-option>
1484
+ <wcs-select-option value="4">Quatre</wcs-select-option>
1485
+ <wcs-select-option value="5">Cinq</wcs-select-option>
1486
+ </wcs-select>
1487
+ <button style="margin-top: 600px">Test</button>
1488
+ `);
1489
+ const options = [
1490
+ {
1491
+ value: 1,
1492
+ displayText: 'Un'
1493
+ },
1494
+ {
1495
+ value: 2,
1496
+ displayText: 'Deux'
1497
+ },
1498
+ {
1499
+ value: 3,
1500
+ displayText: 'Trois'
1501
+ },
1502
+ {
1503
+ value: 4,
1504
+ displayText: 'Quatre'
1505
+ },
1506
+ {
1507
+ value: 5,
1508
+ displayText: 'Cinq'
1509
+ },
1510
+ {
1511
+ value: 6,
1512
+ displayText: 'Six'
1513
+ },
1514
+ ];
1515
+ const select = page.locator('wcs-select');
1516
+ const button = page.locator('button');
1517
+ const input = page.locator('input.autocomplete-field');
1518
+ await select.evaluate((el, options) => {
1519
+ el.addEventListener('wcsFilterChange', (event) => {
1520
+ const htmlSelectOptions = options
1521
+ .filter((o) => o.displayText.includes(event.detail.value))
1522
+ .map((o) => `<wcs-select-option value="${o.value}">${o.displayText}</wcs-select-option>`);
1523
+ el.innerHTML = htmlSelectOptions.join('');
1524
+ });
1525
+ }, options);
1526
+ await expect(input).toHaveJSProperty('value', 'Trois');
1527
+ await input.press('End'); // place at the end of input
1528
+ await input.press('Backspace'); // Troi
1529
+ await input.press('Backspace'); // tro
1530
+ await input.press('Backspace'); // tr
1531
+ await input.press('Backspace'); // t
1532
+ await input.press('Backspace'); //
1533
+ await input.press('u'); // u
1534
+ await page.waitForChanges();
1535
+ await expect(select).toHaveJSProperty('value', '3');
1536
+ await expect(input).toHaveJSProperty('value', 'u');
1537
+ await button.focus();
1538
+ await button.click(); // blur the select
1539
+ await expect(input).toHaveJSProperty('value', 'Trois');
1540
+ });
1541
+ test('[ServerMode][Autocomplete] should clear and restore input label when value is changed and options are updated during component lifecycle', async ({ page }) => {
1542
+ await setWcsContent(page, `
1543
+ <wcs-select autocomplete server-mode value="3">
1544
+ </wcs-select>
1545
+ <button style="margin-top: 600px">Test</button>
1546
+ `);
1547
+ const select = page.locator('wcs-select');
1548
+ const button = page.locator('button');
1549
+ const input = page.locator('input.autocomplete-field');
1550
+ await page.$eval('wcs-select', (el) => {
1551
+ el.innerHTML = `
1552
+ <wcs-select-option value="1">Un</wcs-select-option>
1553
+ <wcs-select-option value="2">Deux</wcs-select-option>
1554
+ <wcs-select-option value="3">Trois</wcs-select-option>
1555
+ `;
1556
+ });
1557
+ await page.waitForChanges();
1558
+ await expect(select).toHaveJSProperty('value', '3');
1559
+ await expect(input).toHaveJSProperty('value', 'Trois');
1560
+ await input.press('End'); // place at the end of input
1561
+ await input.press('Backspace'); // Troi
1562
+ await input.press('Backspace'); // Tro
1563
+ await select.evaluate((el) => (el.value = '4'));
1564
+ await page.waitForChanges();
1565
+ await expect(select).toHaveJSProperty('value', '4');
1566
+ await expect(input).toHaveJSProperty('value', '');
1567
+ await page.$eval('wcs-select', (el) => {
1568
+ el.innerHTML = `
1569
+ <wcs-select-option value="4">Quatre</wcs-select-option>
1570
+ <wcs-select-option value="5">Cinq</wcs-select-option>
1571
+ <wcs-select-option value="6">Six</wcs-select-option>
1572
+ `;
1573
+ });
1574
+ await page.waitForChanges();
1575
+ await expect(select).toHaveJSProperty('value', '4');
1576
+ await expect(input).toHaveJSProperty('value', 'Quatre');
1577
+ await button.focus();
1578
+ await expect(input).toHaveJSProperty('value', 'Quatre');
1579
+ });
1580
+ test('[ServerMode][Autocomplete] should assign the filter again and emit the filterChange event when the user reselects the current value after filtering', async ({ page }) => {
1581
+ const options = [{
1582
+ value: 1,
1583
+ displayText: 'Ain'
1584
+ },
1585
+ {
1586
+ value: 2,
1587
+ displayText: 'Aisne'
1588
+ },
1589
+ {
1590
+ value: 3,
1591
+ displayText: 'Rhône'
1592
+ }
1593
+ ];
1594
+ await setWcsContent(page, `
1595
+ <wcs-select autocomplete server-mode>
1596
+ <wcs-select-option value="1">Ain</wcs-select-option>
1597
+ <wcs-select-option value="2">Aisne</wcs-select-option>
1598
+ <wcs-select-option value="3">Rhône</wcs-select-option>
1599
+ </wcs-select>
1600
+ `);
1601
+ const select = page.locator('wcs-select');
1602
+ const ainOption = page.locator('wcs-select-option[value="1"]');
1603
+ const aisneOption = page.locator('wcs-select-option[value="2"]');
1604
+ const rhoneOption = page.locator('wcs-select-option[value="3"]');
1605
+ const input = page.locator('input.autocomplete-field');
1606
+ await select.evaluate((el, options) => {
1607
+ el.addEventListener('wcsFilterChange', (event) => {
1608
+ const htmlSelectOptions = options
1609
+ .filter((o) => o.displayText.includes(event.detail.value))
1610
+ .map((o) => `<wcs-select-option value="${o.value}">${o.displayText}</wcs-select-option>`);
1611
+ el.innerHTML = htmlSelectOptions.join('');
1612
+ });
1613
+ }, options);
1614
+ await select.click(); // open
1615
+ await aisneOption.click();
1616
+ await expect(select).toHaveJSProperty('value', '2');
1617
+ await expect(input).toHaveJSProperty('value', 'Aisne');
1618
+ await select.click(); // the select juste close because we select options open
1619
+ await page.waitForChanges();
1620
+ await expect(ainOption).not.toBeVisible();
1621
+ await expect(aisneOption).toBeVisible();
1622
+ await expect(rhoneOption).not.toBeVisible();
1623
+ await input.press('Backspace'); // Aisn
1624
+ await input.press('Backspace'); // Ais
1625
+ await input.press('Backspace'); // Ai
1626
+ await input.press('Backspace'); // A
1627
+ await input.press('Backspace'); //
1628
+ await expect(ainOption).toBeVisible();
1629
+ await expect(aisneOption).toBeVisible();
1630
+ await expect(rhoneOption).toBeVisible();
1631
+ await aisneOption.click();
1632
+ await select.click();
1633
+ await page.waitForChanges();
1634
+ await expect(ainOption).not.toBeVisible();
1635
+ await expect(aisneOption).toBeVisible();
1636
+ await expect(rhoneOption).not.toBeVisible();
1637
+ });
1638
+ test('[ServerMode][Autocomplete] should reset autocompleteValue to value when blurring', async ({ page }) => {
1639
+ await setWcsContent(page, `
1640
+ <wcs-select autocomplete server-mode>
1641
+ <wcs-select-option value="1">Ain</wcs-select-option>
1642
+ <wcs-select-option value="2">Aisne</wcs-select-option>
1643
+ <wcs-select-option value="3">Rhône</wcs-select-option>
1644
+ </wcs-select>
1645
+
1646
+ <button id="element-to-blur" style="margin: 500px">Blur me</button>
1647
+ `);
1648
+ const options = [{
1649
+ value: 1,
1650
+ displayText: 'Ain'
1651
+ },
1652
+ {
1653
+ value: 2,
1654
+ displayText: 'Aisne'
1655
+ },
1656
+ {
1657
+ value: 3,
1658
+ displayText: 'Rhône'
1659
+ }
1660
+ ];
1661
+ const select = page.locator('wcs-select');
1662
+ const ainOption = page.locator('wcs-select-option[value="1"]');
1663
+ const aisneOption = page.locator('wcs-select-option[value="2"]');
1664
+ const rhoneOption = page.locator('wcs-select-option[value="3"]');
1665
+ const input = page.locator('input.autocomplete-field');
1666
+ const blurButton = page.locator('#element-to-blur');
1667
+ await select.evaluate((el, options) => {
1668
+ el.addEventListener('wcsFilterChange', (event) => {
1669
+ const htmlSelectOptions = options
1670
+ .filter((o) => o.displayText.includes(event.detail.value))
1671
+ .map((o) => `<wcs-select-option value="${o.value}">${o.displayText}</wcs-select-option>`);
1672
+ el.innerHTML = htmlSelectOptions.join('');
1673
+ });
1674
+ }, options);
1675
+ await select.click(); // open
1676
+ await aisneOption.click();
1677
+ await page.waitForChanges();
1678
+ await expect(select).toHaveJSProperty('value', '2');
1679
+ await expect(input).toHaveJSProperty('value', 'Aisne');
1680
+ await select.click(); // the select juste close because we select options open
1681
+ await page.waitForChanges();
1682
+ await expect(ainOption).not.toBeVisible();
1683
+ await expect(aisneOption).toBeVisible();
1684
+ await expect(rhoneOption).not.toBeVisible();
1685
+ await input.press('Backspace'); // Aisn
1686
+ await input.press('Backspace'); // Ais
1687
+ await input.press('Backspace'); // Ai
1688
+ await input.press('Backspace'); // A
1689
+ await input.press('Backspace'); //
1690
+ await expect(ainOption).toBeVisible();
1691
+ await expect(aisneOption).toBeVisible();
1692
+ await expect(rhoneOption).toBeVisible();
1693
+ await blurButton.click();
1694
+ await expect(select).toHaveJSProperty('value', '2');
1695
+ await expect(input).toHaveJSProperty('value', 'Aisne');
1696
+ await select.click();
1697
+ await expect(ainOption).not.toBeVisible();
1698
+ await expect(aisneOption).toBeVisible();
1699
+ await expect(rhoneOption).not.toBeVisible();
1700
+ });
1701
+ });
1702
+ //# sourceMappingURL=select.e2e.playwright.js.map