@api-client/ui 0.5.38 → 0.5.40

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 (299) hide show
  1. package/build/src/md/list/internals/ListItem.d.ts +24 -15
  2. package/build/src/md/list/internals/ListItem.d.ts.map +1 -1
  3. package/build/src/md/list/internals/ListItem.js +85 -59
  4. package/build/src/md/list/internals/ListItem.js.map +1 -1
  5. package/build/src/md/list/internals/ListItem.styles.js +11 -11
  6. package/build/src/md/list/internals/ListItem.styles.js.map +1 -1
  7. package/build/src/md/select/internals/Option.d.ts +4 -14
  8. package/build/src/md/select/internals/Option.d.ts.map +1 -1
  9. package/build/src/md/select/internals/Option.js +13 -28
  10. package/build/src/md/select/internals/Option.js.map +1 -1
  11. package/build/src/md/select/internals/Select.d.ts +1 -1
  12. package/build/src/md/select/internals/Select.d.ts.map +1 -1
  13. package/build/src/md/select/internals/Select.js +15 -5
  14. package/build/src/md/select/internals/Select.js.map +1 -1
  15. package/build/tsconfig.tsbuildinfo +1 -0
  16. package/package.json +1 -1
  17. package/src/md/list/internals/ListItem.styles.ts +11 -11
  18. package/src/md/list/internals/ListItem.ts +68 -43
  19. package/src/md/select/internals/Option.ts +14 -26
  20. package/src/md/select/internals/Select.ts +15 -5
  21. package/.aiexclude +0 -3
  22. package/.cursor/rules/html-and-css-best-practices.mdc +0 -63
  23. package/.cursor/rules/lit-best-practices.mdc +0 -89
  24. package/.editorconfig +0 -29
  25. package/.github/CONTRIBUTING.md +0 -24
  26. package/.github/instructions/html-and-css-best-practices.instructions.md +0 -70
  27. package/.github/instructions/lit-best-practices.instructions.md +0 -90
  28. package/.github/release.yml +0 -14
  29. package/.github/stale.yml +0 -23
  30. package/.github/workflows/auto-release.yml +0 -182
  31. package/.github/workflows/release.yml +0 -82
  32. package/.prettierrc.js +0 -14
  33. package/.vscode/settings.json +0 -18
  34. package/RELEASE.md +0 -163
  35. package/RELEASE_SETUP.md +0 -235
  36. package/build/src/demo/DemoPage.d.ts +0 -81
  37. package/build/src/demo/DemoPage.d.ts.map +0 -1
  38. package/build/src/demo/DemoPage.js +0 -175
  39. package/build/src/demo/DemoPage.js.map +0 -1
  40. package/build/src/demo/DemoStyles.d.ts +0 -3
  41. package/build/src/demo/DemoStyles.d.ts.map +0 -1
  42. package/build/src/demo/DemoStyles.js +0 -60
  43. package/build/src/demo/DemoStyles.js.map +0 -1
  44. package/build/test/elements/navigation/Navigation.test.d.ts +0 -3
  45. package/build/test/elements/navigation/Navigation.test.d.ts.map +0 -1
  46. package/build/test/elements/navigation/Navigation.test.js +0 -113
  47. package/build/test/elements/navigation/Navigation.test.js.map +0 -1
  48. package/commitlint.config.cjs +0 -2
  49. package/demo/elements/authorization/AuthPlugin.js +0 -57
  50. package/demo/elements/authorization/AuthProxy.js +0 -215
  51. package/demo/elements/authorization/api-key.html +0 -27
  52. package/demo/elements/authorization/api-key.ts +0 -44
  53. package/demo/elements/authorization/basic.html +0 -27
  54. package/demo/elements/authorization/basic.ts +0 -43
  55. package/demo/elements/authorization/bearer.html +0 -27
  56. package/demo/elements/authorization/bearer.ts +0 -43
  57. package/demo/elements/authorization/env.js +0 -8
  58. package/demo/elements/authorization/index.html +0 -44
  59. package/demo/elements/authorization/ntlm.html +0 -27
  60. package/demo/elements/authorization/ntlm.ts +0 -43
  61. package/demo/elements/authorization/oauth-authorize.html +0 -75
  62. package/demo/elements/authorization/oauth-authorize.ts +0 -40
  63. package/demo/elements/authorization/oauth-error.html +0 -18
  64. package/demo/elements/authorization/oauth-error.ts +0 -10
  65. package/demo/elements/authorization/oauth-popup.html +0 -36
  66. package/demo/elements/authorization/oauth2.html +0 -27
  67. package/demo/elements/authorization/oauth2.ts +0 -100
  68. package/demo/elements/authorization/oidc.html +0 -27
  69. package/demo/elements/authorization/oidc.ts +0 -139
  70. package/demo/elements/authorization/private.crt +0 -31
  71. package/demo/elements/authorization/private.csr +0 -28
  72. package/demo/elements/authorization/private.key +0 -51
  73. package/demo/elements/authorization/private.pem +0 -31
  74. package/demo/elements/authorization/redirect.html +0 -20
  75. package/demo/elements/authorization/ssl-commands.sh +0 -30
  76. package/demo/elements/authorization/ssl.conf +0 -24
  77. package/demo/elements/autocomplete/index.html +0 -64
  78. package/demo/elements/autocomplete/index.ts +0 -171
  79. package/demo/elements/code-editor/CodeEditorDemo.ts +0 -173
  80. package/demo/elements/code-editor/index.html +0 -19
  81. package/demo/elements/context-menu/DemoIcons.ts +0 -21
  82. package/demo/elements/context-menu/basic.html +0 -25
  83. package/demo/elements/context-menu/basic.ts +0 -119
  84. package/demo/elements/context-menu/custom-data.html +0 -25
  85. package/demo/elements/context-menu/custom-data.ts +0 -62
  86. package/demo/elements/context-menu/demo.css +0 -28
  87. package/demo/elements/context-menu/enabled-state.html +0 -25
  88. package/demo/elements/context-menu/enabled-state.ts +0 -73
  89. package/demo/elements/context-menu/icons.html +0 -25
  90. package/demo/elements/context-menu/icons.ts +0 -64
  91. package/demo/elements/context-menu/index.html +0 -43
  92. package/demo/elements/context-menu/nested.html +0 -25
  93. package/demo/elements/context-menu/nestedt.ts +0 -152
  94. package/demo/elements/context-menu/no-execute.html +0 -25
  95. package/demo/elements/context-menu/no-execute.ts +0 -134
  96. package/demo/elements/context-menu/radio-menu.html +0 -25
  97. package/demo/elements/context-menu/radio-menu.ts +0 -83
  98. package/demo/elements/context-menu/separators.html +0 -25
  99. package/demo/elements/context-menu/separators.ts +0 -172
  100. package/demo/elements/currency/index.html +0 -91
  101. package/demo/elements/currency/index.ts +0 -352
  102. package/demo/elements/environment/environment-editor.html +0 -20
  103. package/demo/elements/environment/environment-editor.ts +0 -49
  104. package/demo/elements/environment/index.html +0 -33
  105. package/demo/elements/environment/server-editor.html +0 -20
  106. package/demo/elements/environment/server-editor.ts +0 -67
  107. package/demo/elements/environment/variables-editor.html +0 -20
  108. package/demo/elements/environment/variables-editor.ts +0 -94
  109. package/demo/elements/har/har-viewer.html +0 -20
  110. package/demo/elements/har/har-viewer.ts +0 -76
  111. package/demo/elements/har/har1.har +0 -3044
  112. package/demo/elements/har/har2.json +0 -439
  113. package/demo/elements/har/index.html +0 -26
  114. package/demo/elements/highlight/example.md +0 -27
  115. package/demo/elements/highlight/index.html +0 -31
  116. package/demo/elements/highlight/marked-highlight.html +0 -132
  117. package/demo/elements/highlight/marked-highlight.ts +0 -22
  118. package/demo/elements/highlight/prism-highlight.html +0 -62
  119. package/demo/elements/highlight/prism-highlight.ts +0 -17
  120. package/demo/elements/http/body-editor.html +0 -17
  121. package/demo/elements/http/body-editor.ts +0 -115
  122. package/demo/elements/http/headers.html +0 -17
  123. package/demo/elements/http/headers.ts +0 -59
  124. package/demo/elements/http/http-assertions.html +0 -20
  125. package/demo/elements/http/http-assertions.ts +0 -89
  126. package/demo/elements/http/http-flows.html +0 -23
  127. package/demo/elements/http/http-flows.ts +0 -89
  128. package/demo/elements/http/index.html +0 -45
  129. package/demo/elements/http/request-editor.html +0 -26
  130. package/demo/elements/http/request-editor.ts +0 -197
  131. package/demo/elements/http/request-log.html +0 -16
  132. package/demo/elements/http/request-log.ts +0 -136
  133. package/demo/elements/http/url-editing.html +0 -17
  134. package/demo/elements/http/url-editing.ts +0 -112
  135. package/demo/elements/icons/index.html +0 -81
  136. package/demo/elements/icons/index.ts +0 -52
  137. package/demo/elements/index.html +0 -72
  138. package/demo/elements/mention-textarea/index.html +0 -19
  139. package/demo/elements/mention-textarea/index.ts +0 -205
  140. package/demo/elements/navigation/navigation-item.html +0 -49
  141. package/demo/elements/navigation/navigation-item.ts +0 -131
  142. package/demo/elements/navigation/navigation.html +0 -20
  143. package/demo/elements/navigation/navigation.ts +0 -45
  144. package/demo/elements/project/index.html +0 -29
  145. package/demo/elements/project/project-run-report.html +0 -20
  146. package/demo/elements/project/project-run-report.ts +0 -132
  147. package/demo/elements/project/request-editor.html +0 -23
  148. package/demo/elements/project/request-editor.ts +0 -232
  149. package/demo/elements/user/user-avatar.html +0 -17
  150. package/demo/elements/user/user-avatar.ts +0 -60
  151. package/demo/env.js +0 -4
  152. package/demo/index.html +0 -34
  153. package/demo/layout/index.html +0 -94
  154. package/demo/layout/index.ts +0 -190
  155. package/demo/md/DemoStyles.ts +0 -61
  156. package/demo/md/UiDemoPage.ts +0 -6
  157. package/demo/md/buttons/button.html +0 -121
  158. package/demo/md/buttons/button.ts +0 -246
  159. package/demo/md/buttons/group.html +0 -36
  160. package/demo/md/buttons/group.ts +0 -171
  161. package/demo/md/checkbox/index.html +0 -39
  162. package/demo/md/checkbox/index.ts +0 -220
  163. package/demo/md/chip/chip.html +0 -70
  164. package/demo/md/chip/chip.ts +0 -219
  165. package/demo/md/chip/pawel6c9a.jpg +0 -0
  166. package/demo/md/collapse/CustomDetail.ts +0 -89
  167. package/demo/md/collapse/collapse.html +0 -21
  168. package/demo/md/collapse/collapse.ts +0 -78
  169. package/demo/md/date-picker/date-picker.ts +0 -336
  170. package/demo/md/date-picker/index.html +0 -171
  171. package/demo/md/dialog/confirm-dialog.html +0 -49
  172. package/demo/md/dialog/confirm-dialog.ts +0 -121
  173. package/demo/md/dialog/dialog.html +0 -25
  174. package/demo/md/dialog/dialog.ts +0 -468
  175. package/demo/md/dropdown-list/index.html +0 -31
  176. package/demo/md/dropdown-list/index.ts +0 -158
  177. package/demo/md/icon-button/index.html +0 -122
  178. package/demo/md/icon-button/index.ts +0 -132
  179. package/demo/md/index.html +0 -73
  180. package/demo/md/inputs/input.html +0 -73
  181. package/demo/md/inputs/input.ts +0 -278
  182. package/demo/md/inputs/radio.html +0 -39
  183. package/demo/md/inputs/radio.ts +0 -156
  184. package/demo/md/inputs/switch.html +0 -45
  185. package/demo/md/inputs/switch.ts +0 -144
  186. package/demo/md/list/list.html +0 -65
  187. package/demo/md/list/list.ts +0 -204
  188. package/demo/md/listbox/listbox.html +0 -31
  189. package/demo/md/listbox/listbox.ts +0 -27
  190. package/demo/md/menu/index.html +0 -19
  191. package/demo/md/menu/index.ts +0 -514
  192. package/demo/md/notification/snack.html +0 -21
  193. package/demo/md/notification/snack.ts +0 -70
  194. package/demo/md/progress/progress.html +0 -46
  195. package/demo/md/progress/progress.ts +0 -161
  196. package/demo/md/segmented-button/index.html +0 -21
  197. package/demo/md/segmented-button/index.ts +0 -55
  198. package/demo/md/select/index.html +0 -16
  199. package/demo/md/select/index.ts +0 -207
  200. package/demo/md/tabs/tabs.html +0 -40
  201. package/demo/md/tabs/tabs.ts +0 -214
  202. package/demo/oauth-popup.html +0 -36
  203. package/demo/page.css +0 -8
  204. package/demo/resources/calendar-month.png +0 -0
  205. package/demo/resources/favorite.png +0 -0
  206. package/demo/resources/fingerprint.png +0 -0
  207. package/demo/resources/home-work.png +0 -0
  208. package/demo/resources/mood.png +0 -0
  209. package/demo/resources/print.png +0 -0
  210. package/demo/resources/stars.png +0 -0
  211. package/demo/resources/theaters.png +0 -0
  212. package/demo/tsconfig.json +0 -4
  213. package/eslint.config.js +0 -97
  214. package/scripts/copy-assets.js +0 -21
  215. package/scripts/release.js +0 -66
  216. package/src/demo/DemoPage.ts +0 -169
  217. package/src/demo/DemoStyles.ts +0 -60
  218. package/test/README.md +0 -375
  219. package/test/contextual-menu/ContextMenu.test.ts +0 -760
  220. package/test/contextual-menu/ContextMenuElement.test.ts +0 -569
  221. package/test/core/activity.spec.ts +0 -413
  222. package/test/core/activity_manager.spec.ts +0 -544
  223. package/test/core/application.spec.ts +0 -218
  224. package/test/core/fragment.spec.ts +0 -565
  225. package/test/core/fragment_manager.spec.ts +0 -404
  226. package/test/core/live_data.spec.ts +0 -558
  227. package/test/core/renderer.spec.ts +0 -113
  228. package/test/dom-assertions.test.ts +0 -182
  229. package/test/elements/MonacoSetup.ts +0 -65
  230. package/test/elements/authorization/basic-method.test.ts +0 -177
  231. package/test/elements/authorization/bearer-method.test.ts +0 -143
  232. package/test/elements/authorization/ntlm-method.test.ts +0 -219
  233. package/test/elements/authorization/oauth2-client-credentials-method.test.ts +0 -334
  234. package/test/elements/authorization/oauth2-code-method.test.ts +0 -320
  235. package/test/elements/authorization/oauth2-custom-grant-method.test.ts +0 -255
  236. package/test/elements/authorization/oauth2-device-code-method.test.ts +0 -371
  237. package/test/elements/authorization/oauth2-implicit-method.test.ts +0 -407
  238. package/test/elements/authorization/oauth2-jwt-method.test.ts +0 -217
  239. package/test/elements/authorization/oauth2-password-method.test.ts +0 -275
  240. package/test/elements/authorization/openid-method.test.ts +0 -591
  241. package/test/elements/autocomplete/autocomplete-input.spec.ts +0 -646
  242. package/test/elements/code-editor/code-editor.accessibility.test.ts +0 -298
  243. package/test/elements/code-editor/code-editor.test.ts +0 -574
  244. package/test/elements/currency/CurrencyPicker.accessibility.test.ts +0 -328
  245. package/test/elements/currency/CurrencyPicker.core.test.ts +0 -318
  246. package/test/elements/currency/CurrencyPicker.integration.test.ts +0 -482
  247. package/test/elements/currency/CurrencyPicker.test.ts +0 -486
  248. package/test/elements/data-table/DataTable.browser.test.ts +0 -649
  249. package/test/elements/har/HarUtils.test.ts +0 -45
  250. package/test/elements/har/HarViewerElement.test.ts +0 -687
  251. package/test/elements/har/test-data/har1.har +0 -3044
  252. package/test/elements/highlight/MarkedHighlightElement.test.ts +0 -452
  253. package/test/elements/highlight/PrismHighlightElement.test.ts +0 -79
  254. package/test/elements/highlight/PrismHighlighter.test.ts +0 -94
  255. package/test/elements/highlight/remoteSanitization.md +0 -1
  256. package/test/elements/highlight/test.md +0 -3
  257. package/test/elements/highlight/test1.md +0 -3
  258. package/test/elements/highlight/test2.md +0 -1
  259. package/test/elements/http/BodyFormdataEditorElement.test.ts +0 -482
  260. package/test/elements/http/BodyMultipartEditorElement.test.ts +0 -658
  261. package/test/elements/http/BodyRawEditorElement.test.ts +0 -90
  262. package/test/elements/http/CertificateAdd.test.ts +0 -457
  263. package/test/elements/http/HttpAssertions.test.ts +0 -994
  264. package/test/elements/http/HttpFlows.test.ts +0 -502
  265. package/test/elements/http/UrlEncodeUtils.test.ts +0 -202
  266. package/test/elements/layout/SplitItem.test.ts +0 -440
  267. package/test/elements/layout/SplitLayoutManager.test.ts +0 -1501
  268. package/test/elements/layout/SplitPanel.test.ts +0 -1109
  269. package/test/elements/mention-textarea/MentionTextArea.basic.test.ts +0 -114
  270. package/test/elements/mention-textarea/MentionTextArea.test.ts +0 -613
  271. package/test/elements/navigation/Navigation.test.ts +0 -120
  272. package/test/env.ts +0 -15
  273. package/test/events/EventTypes.test.ts +0 -363
  274. package/test/events/EventsTestHelpers.ts +0 -16
  275. package/test/helpers/TestUtils.ts +0 -243
  276. package/test/helpers/UiMock.ts +0 -185
  277. package/test/lib/Dom.test.ts +0 -231
  278. package/test/md/button/UiButton.test.ts +0 -347
  279. package/test/md/button/UiIconButton.test.ts +0 -155
  280. package/test/md/chip/UiChip.test.ts +0 -219
  281. package/test/md/collapse/UiCollapse.test.ts +0 -250
  282. package/test/md/collapse/flex-layout.test.ts +0 -105
  283. package/test/md/date-time/DateTime.test.ts +0 -348
  284. package/test/md/dialog/UiConfirmDialog.test.ts +0 -131
  285. package/test/md/dialog/UiDialog.test.ts +0 -759
  286. package/test/md/menu/Menu.test.ts +0 -855
  287. package/test/md/menu/MenuIntegration.test.ts +0 -426
  288. package/test/md/menu/MenuItem.test.ts +0 -652
  289. package/test/md/menu/SubMenu.test.ts +0 -410
  290. package/test/md/progress/UiCircularProgressElement.test.ts +0 -481
  291. package/test/md/progress/UiProgressElement.test.ts +0 -117
  292. package/test/md/progress/UiRangeElement.test.ts +0 -156
  293. package/test/md/select/Select.test.ts +0 -925
  294. package/test/plugins/takeScreenshotPlugin.js +0 -35
  295. package/test/setup.test.ts +0 -217
  296. package/test/setup.ts +0 -117
  297. package/test/tsconfig.json +0 -7
  298. package/web-dev-server.config.js +0 -21
  299. package/web-test-runner.config.js +0 -90
@@ -1,925 +0,0 @@
1
- import { assert, fixture, html, nextFrame, oneEvent } from '@open-wc/testing'
2
- import sinon from 'sinon'
3
- import UiSelect from '../../../src/md/select/internals/Select.js'
4
- import UiOption from '../../../src/md/select/internals/Option.js'
5
- import type { UiSelectChangeEvent } from '../../../src/md/select/internals/Select.js'
6
-
7
- import '../../../src/md/select/ui-select.js'
8
- import '../../../src/md/select/ui-option.js'
9
- import '../../../src/md/icons/ui-icon.js'
10
-
11
- describe('md', () => {
12
- describe('UiSelect', () => {
13
- async function basicFixture(): Promise<UiSelect> {
14
- return fixture(html`
15
- <ui-select label="Select an option">
16
- <ui-option value="apple">Apple</ui-option>
17
- <ui-option value="banana">Banana</ui-option>
18
- <ui-option value="cherry">Cherry</ui-option>
19
- </ui-select>
20
- `)
21
- }
22
-
23
- async function withValueFixture(): Promise<UiSelect> {
24
- return fixture(html`
25
- <ui-select label="Select an option" value="banana">
26
- <ui-option value="apple">Apple</ui-option>
27
- <ui-option value="banana">Banana</ui-option>
28
- <ui-option value="cherry">Cherry</ui-option>
29
- </ui-select>
30
- `)
31
- }
32
-
33
- async function requiredFixture(): Promise<UiSelect> {
34
- return fixture(html`
35
- <ui-select label="Required field" required>
36
- <ui-option value="apple">Apple</ui-option>
37
- <ui-option value="banana">Banana</ui-option>
38
- </ui-select>
39
- `)
40
- }
41
-
42
- async function disabledFixture(): Promise<UiSelect> {
43
- return fixture(html`
44
- <ui-select label="Disabled select" disabled>
45
- <ui-option value="apple">Apple</ui-option>
46
- <ui-option value="banana">Banana</ui-option>
47
- </ui-select>
48
- `)
49
- }
50
-
51
- async function formFixture(): Promise<HTMLFormElement> {
52
- return fixture(html`
53
- <form>
54
- <input name="text" value="test" />
55
- <ui-select name="fruit" label="Select fruit">
56
- <ui-option value="apple">Apple</ui-option>
57
- <ui-option value="banana">Banana</ui-option>
58
- </ui-select>
59
- </form>
60
- `)
61
- }
62
-
63
- async function invalidFixture(): Promise<UiSelect> {
64
- return fixture(html`
65
- <ui-select label="Invalid select" invalid invalidText="This field is required">
66
- <ui-option value="apple">Apple</ui-option>
67
- <ui-option value="banana">Banana</ui-option>
68
- </ui-select>
69
- `)
70
- }
71
-
72
- async function emptyFixture(): Promise<UiSelect> {
73
- return fixture(html`<ui-select label="Empty select"></ui-select>`)
74
- }
75
-
76
- async function selectedAttributeFixture(): Promise<UiSelect> {
77
- return fixture(html`
78
- <ui-select label="Select with pre-selected option">
79
- <ui-option value="apple">Apple</ui-option>
80
- <ui-option value="banana" selected>Banana</ui-option>
81
- <ui-option value="cherry">Cherry</ui-option>
82
- </ui-select>
83
- `)
84
- }
85
-
86
- async function multipleSelectedFixture(): Promise<UiSelect> {
87
- return fixture(html`
88
- <ui-select label="Select with multiple selected">
89
- <ui-option value="apple" selected>Apple</ui-option>
90
- <ui-option value="banana" selected>Banana</ui-option>
91
- <ui-option value="cherry">Cherry</ui-option>
92
- </ui-select>
93
- `)
94
- }
95
-
96
- async function selectedWithValueFixture(): Promise<UiSelect> {
97
- return fixture(html`
98
- <ui-select label="Select with both value and selected" value="cherry">
99
- <ui-option value="apple">Apple</ui-option>
100
- <ui-option value="banana" selected>Banana</ui-option>
101
- <ui-option value="cherry">Cherry</ui-option>
102
- </ui-select>
103
- `)
104
- }
105
-
106
- async function dynamicOptionsFixture(): Promise<UiSelect> {
107
- return fixture(html` <ui-select label="Dynamic options"> </ui-select> `)
108
- }
109
-
110
- describe('Basic functionality', () => {
111
- it('should create select element', async () => {
112
- const element = await basicFixture()
113
- assert.instanceOf(element, UiSelect)
114
- assert.equal(element.tagName.toLowerCase(), 'ui-select')
115
- })
116
-
117
- it('has formAssociated set', async () => {
118
- assert.isTrue(UiSelect.formAssociated)
119
- })
120
-
121
- it('should have correct default properties', async () => {
122
- const element = await basicFixture()
123
- assert.isUndefined(element.value)
124
- assert.isUndefined(element.name)
125
- assert.equal(element.label, 'Select an option')
126
- assert.isFalse(element.required)
127
- assert.isUndefined(element.invalid)
128
- assert.isUndefined(element.invalidText)
129
- assert.isFalse(element.disabled)
130
- assert.isFalse(element.open)
131
- assert.isNull(element.selectedItem)
132
- assert.equal(element.renderValue, '')
133
- })
134
-
135
- it('should set correct ARIA attributes', async () => {
136
- const element = await basicFixture()
137
- assert.equal(element.getAttribute('role'), 'combobox')
138
- assert.equal(element.getAttribute('aria-haspopup'), 'listbox')
139
- assert.equal(element.getAttribute('aria-controls'), 'menu')
140
- assert.equal(element.getAttribute('aria-label'), 'Select an option')
141
- assert.equal(element.tabIndex, 0)
142
- })
143
-
144
- it('should not have tabindex when disabled', async () => {
145
- const element = await disabledFixture()
146
- assert.equal(element.tabIndex, -1)
147
- })
148
- })
149
-
150
- describe('Value and selection', () => {
151
- it('should set value and select corresponding option', async () => {
152
- const element = await basicFixture()
153
- element.value = 'banana'
154
- await element.updateComplete
155
- // We need it here because the observer also awaits updateComplete
156
- await nextFrame()
157
-
158
- assert.equal(element.value, 'banana')
159
- assert.isNotNull(element.selectedItem)
160
- assert.equal(element.selectedItem!.value, 'banana')
161
- assert.equal(element.renderValue, 'Banana')
162
- })
163
-
164
- it('should initialize with preselected value', async () => {
165
- const element = await withValueFixture()
166
- await element.updateComplete
167
-
168
- assert.equal(element.value, 'banana')
169
- assert.isNotNull(element.selectedItem)
170
- assert.equal(element.selectedItem!.value, 'banana')
171
- assert.equal(element.renderValue, 'Banana')
172
- })
173
-
174
- it('should handle invalid value gracefully', async () => {
175
- const element = await basicFixture()
176
- element.value = 'nonexistent'
177
- await element.updateComplete
178
-
179
- assert.equal(element.value, 'nonexistent')
180
- assert.isNull(element.selectedItem)
181
- assert.equal(element.renderValue, '')
182
- })
183
-
184
- it('should clear selection when value is undefined', async () => {
185
- const element = await withValueFixture()
186
- await element.updateComplete
187
-
188
- element.value = undefined
189
- await element.updateComplete
190
- // We need it here because the observer also awaits updateComplete
191
- await nextFrame()
192
-
193
- assert.isUndefined(element.value, 'the value should be undefined')
194
- assert.isNull(element.selectedItem, 'selected item should be null')
195
- assert.equal(element.renderValue, '')
196
- })
197
-
198
- it('should discover selected attribute on options', async () => {
199
- const element = await selectedAttributeFixture()
200
- await element.updateComplete
201
-
202
- assert.equal(element.value, 'banana')
203
- assert.isNotNull(element.selectedItem)
204
- assert.equal(element.selectedItem!.value, 'banana')
205
- assert.equal(element.renderValue, 'Banana')
206
- })
207
-
208
- it('should handle multiple selected options by selecting the first one', async () => {
209
- const element = await multipleSelectedFixture()
210
- await element.updateComplete
211
- await nextFrame()
212
-
213
- // When multiple options have selected attribute, only the first one should be selected
214
- assert.equal(element.value, 'apple')
215
- assert.isNotNull(element.selectedItem)
216
- assert.equal(element.selectedItem!.value, 'apple') // First selected item
217
- assert.equal(element.renderValue, 'Apple') // Display value should match the first selected item
218
- })
219
-
220
- it('should prioritize value over selected attribute', async () => {
221
- const element = await selectedWithValueFixture()
222
- await element.updateComplete
223
-
224
- assert.equal(element.value, 'cherry')
225
- assert.isNotNull(element.selectedItem)
226
- assert.equal(element.selectedItem!.value, 'cherry')
227
- assert.equal(element.renderValue, 'Cherry')
228
- })
229
-
230
- it('should update value when options change dynamically', async () => {
231
- const element = await dynamicOptionsFixture()
232
- await element.updateComplete
233
-
234
- // Initially, there are no options, so value should be undefined
235
- assert.isUndefined(element.value)
236
-
237
- // Add options dynamically
238
- element.innerHTML = `
239
- <ui-option value="apple">Apple</ui-option>
240
- <ui-option value="banana" selected>Banana</ui-option>
241
- <ui-option value="cherry">Cherry</ui-option>
242
- `
243
- await element.updateComplete
244
- await nextFrame()
245
-
246
- // The value should now reflect the selected option
247
- assert.equal(element.value, 'banana')
248
- assert.isNotNull(element.selectedItem)
249
- assert.equal(element.selectedItem!.value, 'banana')
250
- assert.equal(element.renderValue, 'Banana')
251
- })
252
- })
253
-
254
- describe('Form integration', () => {
255
- it('should have no form when not in form', async () => {
256
- const element = await basicFixture()
257
- assert.isNull(element.form)
258
- })
259
-
260
- it('should have form when in a form', async () => {
261
- const form = await formFixture()
262
- const select = form.querySelector('ui-select')!
263
- assert.ok(select.form, 'has a form')
264
- assert.isTrue(select.form === form, 'has the parent form')
265
- })
266
-
267
- it('should participate in form submission', async () => {
268
- const form = await formFixture()
269
- const select = form.querySelector('ui-select')!
270
- select.value = 'apple'
271
- await select.updateComplete
272
-
273
- const formData = new FormData(form)
274
- assert.equal(formData.get('fruit'), 'apple')
275
- })
276
-
277
- it('should update form value on selection change', async () => {
278
- const form = await formFixture()
279
- const select = form.querySelector('ui-select')!
280
-
281
- // Simulate selection of 'banana'
282
- const bananaOption = select.querySelector('ui-option[value="banana"]') as UiOption
283
- select.handleSelect(new CustomEvent('select', { detail: { item: bananaOption } }))
284
- await select.updateComplete
285
-
286
- const formData = new FormData(form)
287
- assert.equal(formData.get('fruit'), 'banana', 'Form data should be "banana" after selection')
288
- })
289
-
290
- it('should clear form value when value is set to undefined', async () => {
291
- const form = await formFixture()
292
- const select = form.querySelector('ui-select')!
293
- select.value = 'apple'
294
- await select.updateComplete
295
-
296
- let formData = new FormData(form)
297
- assert.equal(formData.get('fruit'), 'apple', 'Form data should be "apple" initially')
298
-
299
- select.value = undefined
300
- await select.updateComplete
301
-
302
- formData = new FormData(form)
303
- assert.isNull(formData.get('fruit'), 'Form data should be null after clearing value')
304
- })
305
-
306
- it('should not submit when no value selected', async () => {
307
- const form = await formFixture()
308
- const formData = new FormData(form)
309
- assert.isNull(formData.get('fruit'))
310
- })
311
-
312
- it('should reset value on form reset', async () => {
313
- const form = await formFixture()
314
- const select = form.querySelector('ui-select')!
315
- select.value = 'apple'
316
- await select.updateComplete
317
-
318
- select.formResetCallback()
319
- assert.isUndefined(select.value)
320
- })
321
-
322
- it('should restore state', async () => {
323
- const element = await basicFixture()
324
- element.formStateRestoreCallback('cherry')
325
- assert.equal(element.value, 'cherry')
326
-
327
- element.formStateRestoreCallback(null)
328
- assert.isUndefined(element.value)
329
- })
330
- })
331
-
332
- describe('Validation', () => {
333
- it('should be valid by default', async () => {
334
- const element = await basicFixture()
335
- assert.isTrue(element.checkValidity())
336
- assert.isTrue(element.validity.valid)
337
- assert.equal(element.validationMessage, '')
338
- })
339
-
340
- it('should be invalid when required and no value', async () => {
341
- const element = await requiredFixture()
342
- element.validate()
343
- await element.updateComplete
344
-
345
- assert.isFalse(element.checkValidity())
346
- assert.isFalse(element.validity.valid)
347
- assert.isTrue(element.validity.valueMissing)
348
- assert.equal(element.validationMessage, 'Please select an item.')
349
- assert.isTrue(element.invalid)
350
- assert.equal(element.invalidText, 'Please select an item.')
351
- })
352
-
353
- it('should be valid when required and has value', async () => {
354
- const element = await requiredFixture()
355
- element.value = 'apple'
356
- await element.updateComplete
357
-
358
- assert.isTrue(element.checkValidity())
359
- assert.isTrue(element.validity.valid)
360
- assert.equal(element.validationMessage, '')
361
- assert.isFalse(element.invalid)
362
- })
363
-
364
- it('should display invalid state', async () => {
365
- const element = await invalidFixture()
366
- assert.isTrue(element.invalid)
367
- assert.equal(element.invalidText, 'This field is required')
368
- })
369
- })
370
-
371
- describe('Keyboard interaction', () => {
372
- it('should open dropdown on Enter key', async () => {
373
- const element = await basicFixture()
374
- assert.isFalse(element.open)
375
-
376
- element.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))
377
- await nextFrame()
378
-
379
- assert.isTrue(element.open)
380
- })
381
-
382
- it('should open dropdown on Space key', async () => {
383
- const element = await basicFixture()
384
- assert.isFalse(element.open)
385
-
386
- element.dispatchEvent(new KeyboardEvent('keydown', { key: ' ' }))
387
- await nextFrame()
388
-
389
- assert.isTrue(element.open)
390
- })
391
-
392
- it('should open dropdown on ArrowDown key', async () => {
393
- const element = await basicFixture()
394
- assert.isFalse(element.open)
395
-
396
- element.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
397
- await nextFrame()
398
-
399
- assert.isTrue(element.open)
400
- })
401
-
402
- it('should open dropdown on ArrowUp key', async () => {
403
- const element = await basicFixture()
404
- assert.isFalse(element.open)
405
-
406
- element.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
407
- await nextFrame()
408
-
409
- assert.isTrue(element.open)
410
- })
411
-
412
- it('should close dropdown on Escape key', async () => {
413
- const element = await basicFixture()
414
- element.open = true
415
- await element.updateComplete
416
-
417
- element.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }))
418
- await nextFrame()
419
-
420
- assert.isFalse(element.open)
421
- })
422
-
423
- it('should not respond to keyboard when disabled', async () => {
424
- const element = await disabledFixture()
425
- element.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))
426
- await nextFrame()
427
-
428
- assert.isFalse(element.open)
429
- })
430
-
431
- it('should handle Tab key when menu is open', async () => {
432
- const element = await basicFixture()
433
- element.open = true
434
- await element.updateComplete
435
-
436
- element.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab' }))
437
- await element.updateComplete
438
-
439
- assert.isFalse(element.open)
440
- })
441
- })
442
-
443
- describe('Mouse interaction', () => {
444
- it('should open dropdown on click', async () => {
445
- const element = await basicFixture()
446
- assert.isFalse(element.open)
447
-
448
- element.click()
449
- await nextFrame()
450
-
451
- assert.isTrue(element.open)
452
- })
453
-
454
- it('should not respond to click when disabled', async () => {
455
- const element = await disabledFixture()
456
- element.click()
457
- await nextFrame()
458
-
459
- assert.isFalse(element.open)
460
- })
461
-
462
- it('should close on blur when focus leaves component', async () => {
463
- const element = await basicFixture()
464
- element.open = true
465
- await element.updateComplete
466
-
467
- // Simulate blur event with no related target (focus leaving completely)
468
- element.dispatchEvent(new FocusEvent('blur', { relatedTarget: null }))
469
- await nextFrame()
470
-
471
- assert.isFalse(element.open)
472
- })
473
-
474
- it('should not close on blur when focus moves to menu', async () => {
475
- const element = await basicFixture()
476
- element.open = true
477
- await element.updateComplete
478
-
479
- const menu = element.shadowRoot!.querySelector('.menu')!
480
- // Simulate blur event with menu as related target
481
- element.dispatchEvent(new FocusEvent('blur', { relatedTarget: menu as HTMLElement }))
482
- await nextFrame()
483
-
484
- assert.isTrue(element.open)
485
- })
486
- })
487
-
488
- describe('Selection events', () => {
489
- it('should dispatch change event when selection changes', async () => {
490
- const element = await basicFixture()
491
- element.open = true
492
- await element.updateComplete
493
-
494
- const changePromise = oneEvent(element, 'change')
495
-
496
- // Simulate option selection
497
- const option = element.querySelector('ui-option[value="apple"]') as UiOption
498
- element.handleSelect(new CustomEvent('select', { detail: { item: option } }))
499
-
500
- const changeEvent = (await changePromise) as CustomEvent<UiSelectChangeEvent>
501
- assert.equal(changeEvent.detail.value, 'apple')
502
- assert.equal(changeEvent.detail.item, option)
503
- assert.isFalse(changeEvent.bubbles)
504
- assert.isTrue(changeEvent.composed)
505
- assert.isFalse(element.open) // Should close after selection
506
- })
507
-
508
- it('should dispatch open event when opening', async () => {
509
- const element = await basicFixture()
510
- await element.updateComplete
511
-
512
- const openPromise = oneEvent(element, 'open')
513
- element.open = true
514
- await element.updateComplete
515
-
516
- const openEvent = await openPromise
517
- assert.isFalse(openEvent.bubbles)
518
- assert.isTrue(openEvent.composed)
519
- })
520
-
521
- it('should dispatch close event when closing', async () => {
522
- const element = await basicFixture()
523
- element.open = true
524
- await element.updateComplete
525
-
526
- const closePromise = oneEvent(element, 'close')
527
- element.open = false
528
- await element.updateComplete
529
-
530
- const closeEvent = await closePromise
531
- assert.isFalse(closeEvent.bubbles)
532
- assert.isTrue(closeEvent.composed)
533
- })
534
- })
535
-
536
- describe('Menu integration', () => {
537
- it('should highlight selected item when menu opens', async () => {
538
- const element = await withValueFixture()
539
- await element.updateComplete
540
-
541
- // Check that menu shows popover when opened
542
- element.open = true
543
- await element.updateComplete
544
-
545
- const menu = element.shadowRoot!.querySelector('ui-menu')!
546
- assert.isTrue(menu.matches(':popover-open'))
547
- })
548
-
549
- it('should highlight first item when no selection and menu opens', async () => {
550
- const element = await basicFixture()
551
- await element.updateComplete
552
-
553
- // Check that menu opens correctly
554
- element.open = true
555
- await element.updateComplete
556
-
557
- const menu = element.shadowRoot!.querySelector('ui-menu')!
558
- assert.isTrue(menu.matches(':popover-open'))
559
- })
560
-
561
- it('should handle menu close event', async () => {
562
- const element = await basicFixture()
563
- element.open = true
564
- await element.updateComplete
565
-
566
- element.handleMenuClose()
567
- assert.isFalse(element.open)
568
- })
569
-
570
- it('should handle highlight change events', async () => {
571
- const element = await basicFixture()
572
- const option = element.querySelector('ui-option') as UiOption
573
- option.id = 'test-option'
574
-
575
- element.handleHighlightChange(
576
- new CustomEvent('highlightchange', {
577
- detail: { item: option },
578
- })
579
- )
580
-
581
- await element.updateComplete
582
-
583
- // Check that the highlight change was processed
584
- // by verifying the DOM reflects the active descendant
585
- const container = element.shadowRoot!.querySelector('.ui-select')!
586
- assert.equal(container.getAttribute('aria-activedescendant'), 'test-option')
587
- })
588
-
589
- it('should clear aria-activedescendant when no item highlighted', async () => {
590
- const element = await basicFixture()
591
- element.handleHighlightChange(
592
- new CustomEvent('highlightchange', {
593
- detail: { item: null },
594
- })
595
- )
596
-
597
- // Check that aria-activedescendant is cleared
598
- const container = element.shadowRoot!.querySelector('.ui-select')!
599
- assert.equal(container.getAttribute('aria-activedescendant'), '')
600
- })
601
- })
602
-
603
- describe('Accessibility', () => {
604
- it('should update aria-expanded when opening/closing', async () => {
605
- const element = await basicFixture()
606
- await element.updateComplete
607
-
608
- element.open = true
609
- await element.updateComplete
610
- assert.equal(element.getAttribute('aria-expanded'), 'true')
611
-
612
- element.open = false
613
- await element.updateComplete
614
- assert.equal(element.getAttribute('aria-expanded'), 'false')
615
- })
616
-
617
- it('should set aria-label from label property', async () => {
618
- const element = await basicFixture()
619
- element.label = 'Test label'
620
- await element.updateComplete
621
-
622
- assert.equal(element.getAttribute('aria-label'), 'Test label')
623
- })
624
-
625
- it('should remove aria-label when label is cleared', async () => {
626
- const element = await basicFixture()
627
- element.label = undefined
628
- await element.updateComplete
629
-
630
- assert.isFalse(element.hasAttribute('aria-label'))
631
- })
632
-
633
- it('should support aria-activedescendant', async () => {
634
- const element = await basicFixture()
635
- const option = element.querySelector('ui-option') as UiOption
636
- option.id = 'test-id'
637
-
638
- // Simulate highlight change to set aria-activedescendant
639
- element.handleHighlightChange(
640
- new CustomEvent('highlightchange', {
641
- detail: { item: option },
642
- })
643
- )
644
- await element.updateComplete
645
-
646
- const container = element.shadowRoot!.querySelector('.ui-select')!
647
- assert.equal(container.getAttribute('aria-activedescendant'), 'test-id')
648
- })
649
- })
650
-
651
- describe('Edge cases', () => {
652
- it('should handle empty option list', async () => {
653
- const element = await emptyFixture()
654
- element.value = 'nonexistent'
655
- await element.updateComplete
656
-
657
- assert.equal(element.value, 'nonexistent')
658
- assert.isNull(element.selectedItem)
659
- assert.equal(element.renderValue, '')
660
- })
661
-
662
- it('should handle setting open before menu is rendered', async () => {
663
- const element = await basicFixture()
664
- await element.updateComplete
665
-
666
- // This should not throw an error even with timing issues
667
- element.open = true
668
- await element.updateComplete
669
-
670
- assert.isTrue(element.open)
671
-
672
- element.open = false
673
- await element.updateComplete
674
-
675
- assert.isFalse(element.open)
676
- })
677
-
678
- it('should maintain focus during interaction', async () => {
679
- const element = await basicFixture()
680
- const focusSpy = sinon.spy(element, 'focus')
681
-
682
- // Simulate selection
683
- const option = element.querySelector('ui-option[value="apple"]') as UiOption
684
- element.handleSelect(new CustomEvent('select', { detail: { item: option } }))
685
-
686
- assert.isTrue(focusSpy.called)
687
- })
688
-
689
- it('should handle selection with prevented event', async () => {
690
- const element = await basicFixture()
691
- element.open = true
692
- await element.updateComplete
693
-
694
- const event = new CustomEvent('select', {
695
- detail: { item: element.querySelector('ui-option') as UiOption },
696
- })
697
- const stopPropagationSpy = sinon.spy(event, 'stopPropagation')
698
-
699
- element.handleSelect(event)
700
- assert.isTrue(stopPropagationSpy.called)
701
- })
702
- })
703
-
704
- describe('Rendering', () => {
705
- it('should render with correct classes', async () => {
706
- const element = await basicFixture()
707
- await element.updateComplete
708
-
709
- const container = element.shadowRoot!.querySelector('.ui-select')!
710
- assert.isTrue(container.classList.contains('ui-select'))
711
- assert.isFalse(container.classList.contains('open'))
712
- assert.isFalse(container.classList.contains('disabled'))
713
- })
714
-
715
- it('should render with open class when open', async () => {
716
- const element = await basicFixture()
717
- element.open = true
718
- await element.updateComplete
719
-
720
- const container = element.shadowRoot!.querySelector('.ui-select')!
721
- assert.isTrue(container.classList.contains('open'))
722
- })
723
-
724
- it('should render with disabled class when disabled', async () => {
725
- const element = await disabledFixture()
726
- await element.updateComplete
727
-
728
- const container = element.shadowRoot!.querySelector('.ui-select')!
729
- assert.isTrue(container.classList.contains('disabled'))
730
- })
731
-
732
- it('should render focus ring', async () => {
733
- const element = await basicFixture()
734
- await element.updateComplete
735
-
736
- const focusRing = element.shadowRoot!.querySelector('md-focus-ring')!
737
- assert.isNotNull(focusRing)
738
- assert.equal(focusRing.getAttribute('part'), 'focus-ring')
739
- })
740
-
741
- it('should render text field with correct properties', async () => {
742
- const element = await withValueFixture()
743
- await element.updateComplete
744
-
745
- const textField = element.shadowRoot!.querySelector('ui-outlined-text-field')!
746
- assert.equal(textField.label, 'Select an option')
747
- // The text field should show the render value of the selected option
748
- assert.equal(textField.value, element.renderValue)
749
- assert.isTrue(textField.hasAttribute('readonly'))
750
- assert.equal(textField.tabIndex, -1)
751
- assert.isTrue(textField.hasAttribute('inert'))
752
- assert.equal(textField.getAttribute('aria-hidden'), 'true')
753
- })
754
-
755
- it('should render dropdown icon', async () => {
756
- const element = await basicFixture()
757
- await element.updateComplete
758
-
759
- const icon = element.shadowRoot!.querySelector('ui-icon[slot="suffix"]')!
760
- assert.equal(icon.textContent!.trim(), 'arrow_drop_down')
761
- })
762
-
763
- it('should render menu with correct attributes', async () => {
764
- const element = await basicFixture()
765
- await element.updateComplete
766
-
767
- const menu = element.shadowRoot!.querySelector('ui-menu')!
768
- assert.equal(menu.id, 'menu')
769
- assert.equal(menu.getAttribute('popover'), 'auto')
770
- assert.equal(menu.getAttribute('selector'), 'ui-option')
771
- })
772
-
773
- it('should slot options correctly', async () => {
774
- const element = await basicFixture()
775
- await element.updateComplete
776
-
777
- const options = element.querySelectorAll('ui-option')
778
- assert.equal(options.length, 3)
779
- assert.equal(options[0].value, 'apple')
780
- assert.equal(options[1].value, 'banana')
781
- assert.equal(options[2].value, 'cherry')
782
- })
783
- })
784
-
785
- describe('Selected attribute discovery', () => {
786
- it('should discover and set value from selected attribute on initialization', async () => {
787
- const element = await selectedAttributeFixture()
788
- await element.updateComplete
789
- await nextFrame()
790
-
791
- assert.equal(element.value, 'banana', 'value should be set from selected option')
792
- assert.isNotNull(element.selectedItem, 'selected item should not be null')
793
- assert.equal(element.selectedItem!.value, 'banana', 'selected item should be the banana option')
794
- assert.equal(element.renderValue, 'Banana', 'render value should match selected option')
795
- })
796
-
797
- it('should handle case with no selected options', async () => {
798
- const element = await basicFixture()
799
- await element.updateComplete
800
- await nextFrame()
801
-
802
- assert.isUndefined(element.value, 'value should be undefined when no options are selected')
803
- assert.isNull(element.selectedItem, 'selected item should be null when no options are selected')
804
- assert.equal(element.renderValue, '', 'render value should be empty when no options are selected')
805
- })
806
-
807
- it('should select the first option when multiple options have selected attribute', async () => {
808
- const element = await multipleSelectedFixture()
809
- await element.updateComplete
810
- await nextFrame()
811
-
812
- assert.equal(element.value, 'apple', 'should select the first option with selected attribute')
813
- assert.isNotNull(element.selectedItem, 'selected item should not be null')
814
- assert.equal(element.selectedItem!.value, 'apple', 'selected item should be the first selected option')
815
- assert.equal(element.renderValue, 'Apple', 'render value should match first selected option')
816
- })
817
-
818
- it('should prioritize explicit value property over selected attribute', async () => {
819
- const element = await selectedWithValueFixture()
820
- await element.updateComplete
821
- await nextFrame()
822
-
823
- assert.equal(element.value, 'cherry', 'value property should take precedence')
824
- assert.isNotNull(element.selectedItem, 'selected item should not be null')
825
- assert.equal(element.selectedItem!.value, 'cherry', 'selected item should match value property')
826
- assert.equal(element.renderValue, 'Cherry', 'render value should match value property')
827
- })
828
-
829
- it('should rediscover selected options when value is cleared', async () => {
830
- const element = await selectedAttributeFixture()
831
- await element.updateComplete
832
- await nextFrame()
833
-
834
- // First, verify it's initialized correctly
835
- assert.equal(element.value, 'banana')
836
-
837
- // Now clear the value and it should fall back to selected attribute
838
- element.value = undefined
839
- await element.updateComplete
840
- await nextFrame()
841
-
842
- assert.equal(element.value, 'banana', 'should rediscover selected option when value is cleared')
843
- assert.isNotNull(element.selectedItem, 'selected item should not be null')
844
- assert.equal(element.selectedItem!.value, 'banana', 'selected item should be rediscovered')
845
- })
846
-
847
- it('should handle dynamically added options with selected attribute', async () => {
848
- const element = await dynamicOptionsFixture()
849
- await element.updateComplete
850
- await nextFrame()
851
-
852
- // Initially no options
853
- assert.isUndefined(element.value)
854
- assert.isNull(element.selectedItem)
855
-
856
- // Add options dynamically
857
- element.innerHTML = `
858
- <ui-option value="apple">Apple</ui-option>
859
- <ui-option value="banana" selected>Banana</ui-option>
860
- <ui-option value="cherry">Cherry</ui-option>
861
- `
862
-
863
- await element.updateComplete
864
- await nextFrame()
865
-
866
- assert.equal(element.value, 'banana', 'should discover selected option from dynamically added content')
867
- assert.isNotNull(element.selectedItem, 'selected item should not be null')
868
- assert.equal(
869
- (element.selectedItem as UiOption)!.value,
870
- 'banana',
871
- 'selected item should be the dynamically added selected option'
872
- )
873
- })
874
-
875
- it('should update when selected attribute is added to existing option', async () => {
876
- const element = await basicFixture()
877
- await element.updateComplete
878
- await nextFrame()
879
-
880
- // Initially no selection
881
- assert.isUndefined(element.value)
882
- assert.isNull(element.selectedItem)
883
-
884
- // Add selected attribute to an option
885
- const bananaOption = element.querySelector('ui-option[value="banana"]') as UiOption
886
- bananaOption.selected = true
887
-
888
- // Trigger setCurrentOption manually since we changed the DOM
889
- await (element as UiSelect & { setCurrentOption(): Promise<void> }).setCurrentOption()
890
- await element.updateComplete
891
- await nextFrame()
892
-
893
- assert.equal(element.value, 'banana', 'should discover newly selected option')
894
- assert.isNotNull(element.selectedItem, 'selected item should not be null')
895
- assert.equal(
896
- (element.selectedItem as UiOption)!.value,
897
- 'banana',
898
- 'selected item should be the newly selected option'
899
- )
900
- })
901
-
902
- it('should clear selection when selected attribute is removed from all options', async () => {
903
- const element = await selectedAttributeFixture()
904
- await element.updateComplete
905
- await nextFrame()
906
-
907
- // Initially has selection
908
- assert.equal(element.value, 'banana')
909
-
910
- // Remove selected attribute
911
- const bananaOption = element.querySelector('ui-option[value="banana"]') as UiOption
912
- bananaOption.selected = false
913
-
914
- // Clear the value to trigger rediscovery
915
- element.value = undefined
916
- await element.updateComplete
917
- await nextFrame()
918
-
919
- assert.isUndefined(element.value, 'value should be undefined when no options are selected')
920
- assert.isNull(element.selectedItem, 'selected item should be null when no options are selected')
921
- assert.equal(element.renderValue, '', 'render value should be empty when no options are selected')
922
- })
923
- })
924
- })
925
- })