@api-client/ui 0.5.39 → 0.5.41
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.
- package/build/src/elements/contextual-menu/{internals/ContextualMenu.d.ts → ContextualMenu.d.ts} +11 -6
- package/build/src/elements/contextual-menu/ContextualMenu.d.ts.map +1 -0
- package/build/src/elements/contextual-menu/{internals/ContextualMenu.js → ContextualMenu.js} +25 -3
- package/build/src/elements/contextual-menu/ContextualMenu.js.map +1 -0
- package/build/src/elements/contextual-menu/internals/types.d.ts +16 -7
- package/build/src/elements/contextual-menu/internals/types.d.ts.map +1 -1
- package/build/src/elements/contextual-menu/internals/types.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -0
- package/package.json +1 -1
- package/src/elements/contextual-menu/{internals/ContextualMenu.ts → ContextualMenu.ts} +31 -7
- package/src/elements/contextual-menu/internals/types.ts +17 -7
- package/.aiexclude +0 -3
- package/.cursor/rules/html-and-css-best-practices.mdc +0 -63
- package/.cursor/rules/lit-best-practices.mdc +0 -89
- package/.editorconfig +0 -29
- package/.github/CONTRIBUTING.md +0 -24
- package/.github/instructions/html-and-css-best-practices.instructions.md +0 -70
- package/.github/instructions/lit-best-practices.instructions.md +0 -90
- package/.github/release.yml +0 -14
- package/.github/stale.yml +0 -23
- package/.github/workflows/auto-release.yml +0 -182
- package/.github/workflows/release.yml +0 -82
- package/.prettierrc.js +0 -14
- package/.vscode/settings.json +0 -18
- package/RELEASE.md +0 -163
- package/RELEASE_SETUP.md +0 -235
- package/build/src/demo/DemoPage.d.ts +0 -81
- package/build/src/demo/DemoPage.d.ts.map +0 -1
- package/build/src/demo/DemoPage.js +0 -175
- package/build/src/demo/DemoPage.js.map +0 -1
- package/build/src/demo/DemoStyles.d.ts +0 -3
- package/build/src/demo/DemoStyles.d.ts.map +0 -1
- package/build/src/demo/DemoStyles.js +0 -60
- package/build/src/demo/DemoStyles.js.map +0 -1
- package/build/src/elements/contextual-menu/internals/ContextualMenu.d.ts.map +0 -1
- package/build/src/elements/contextual-menu/internals/ContextualMenu.js.map +0 -1
- package/build/test/elements/navigation/Navigation.test.d.ts +0 -3
- package/build/test/elements/navigation/Navigation.test.d.ts.map +0 -1
- package/build/test/elements/navigation/Navigation.test.js +0 -113
- package/build/test/elements/navigation/Navigation.test.js.map +0 -1
- package/commitlint.config.cjs +0 -2
- package/demo/elements/authorization/AuthPlugin.js +0 -57
- package/demo/elements/authorization/AuthProxy.js +0 -215
- package/demo/elements/authorization/api-key.html +0 -27
- package/demo/elements/authorization/api-key.ts +0 -44
- package/demo/elements/authorization/basic.html +0 -27
- package/demo/elements/authorization/basic.ts +0 -43
- package/demo/elements/authorization/bearer.html +0 -27
- package/demo/elements/authorization/bearer.ts +0 -43
- package/demo/elements/authorization/env.js +0 -8
- package/demo/elements/authorization/index.html +0 -44
- package/demo/elements/authorization/ntlm.html +0 -27
- package/demo/elements/authorization/ntlm.ts +0 -43
- package/demo/elements/authorization/oauth-authorize.html +0 -75
- package/demo/elements/authorization/oauth-authorize.ts +0 -40
- package/demo/elements/authorization/oauth-error.html +0 -18
- package/demo/elements/authorization/oauth-error.ts +0 -10
- package/demo/elements/authorization/oauth-popup.html +0 -36
- package/demo/elements/authorization/oauth2.html +0 -27
- package/demo/elements/authorization/oauth2.ts +0 -100
- package/demo/elements/authorization/oidc.html +0 -27
- package/demo/elements/authorization/oidc.ts +0 -139
- package/demo/elements/authorization/private.crt +0 -31
- package/demo/elements/authorization/private.csr +0 -28
- package/demo/elements/authorization/private.key +0 -51
- package/demo/elements/authorization/private.pem +0 -31
- package/demo/elements/authorization/redirect.html +0 -20
- package/demo/elements/authorization/ssl-commands.sh +0 -30
- package/demo/elements/authorization/ssl.conf +0 -24
- package/demo/elements/autocomplete/index.html +0 -64
- package/demo/elements/autocomplete/index.ts +0 -171
- package/demo/elements/code-editor/CodeEditorDemo.ts +0 -173
- package/demo/elements/code-editor/index.html +0 -19
- package/demo/elements/context-menu/DemoIcons.ts +0 -21
- package/demo/elements/context-menu/basic.html +0 -25
- package/demo/elements/context-menu/basic.ts +0 -119
- package/demo/elements/context-menu/custom-data.html +0 -25
- package/demo/elements/context-menu/custom-data.ts +0 -62
- package/demo/elements/context-menu/demo.css +0 -28
- package/demo/elements/context-menu/enabled-state.html +0 -25
- package/demo/elements/context-menu/enabled-state.ts +0 -73
- package/demo/elements/context-menu/icons.html +0 -25
- package/demo/elements/context-menu/icons.ts +0 -64
- package/demo/elements/context-menu/index.html +0 -43
- package/demo/elements/context-menu/nested.html +0 -25
- package/demo/elements/context-menu/nestedt.ts +0 -152
- package/demo/elements/context-menu/no-execute.html +0 -25
- package/demo/elements/context-menu/no-execute.ts +0 -134
- package/demo/elements/context-menu/radio-menu.html +0 -25
- package/demo/elements/context-menu/radio-menu.ts +0 -83
- package/demo/elements/context-menu/separators.html +0 -25
- package/demo/elements/context-menu/separators.ts +0 -172
- package/demo/elements/currency/index.html +0 -91
- package/demo/elements/currency/index.ts +0 -352
- package/demo/elements/environment/environment-editor.html +0 -20
- package/demo/elements/environment/environment-editor.ts +0 -49
- package/demo/elements/environment/index.html +0 -33
- package/demo/elements/environment/server-editor.html +0 -20
- package/demo/elements/environment/server-editor.ts +0 -67
- package/demo/elements/environment/variables-editor.html +0 -20
- package/demo/elements/environment/variables-editor.ts +0 -94
- package/demo/elements/har/har-viewer.html +0 -20
- package/demo/elements/har/har-viewer.ts +0 -76
- package/demo/elements/har/har1.har +0 -3044
- package/demo/elements/har/har2.json +0 -439
- package/demo/elements/har/index.html +0 -26
- package/demo/elements/highlight/example.md +0 -27
- package/demo/elements/highlight/index.html +0 -31
- package/demo/elements/highlight/marked-highlight.html +0 -132
- package/demo/elements/highlight/marked-highlight.ts +0 -22
- package/demo/elements/highlight/prism-highlight.html +0 -62
- package/demo/elements/highlight/prism-highlight.ts +0 -17
- package/demo/elements/http/body-editor.html +0 -17
- package/demo/elements/http/body-editor.ts +0 -115
- package/demo/elements/http/headers.html +0 -17
- package/demo/elements/http/headers.ts +0 -59
- package/demo/elements/http/http-assertions.html +0 -20
- package/demo/elements/http/http-assertions.ts +0 -89
- package/demo/elements/http/http-flows.html +0 -23
- package/demo/elements/http/http-flows.ts +0 -89
- package/demo/elements/http/index.html +0 -45
- package/demo/elements/http/request-editor.html +0 -26
- package/demo/elements/http/request-editor.ts +0 -197
- package/demo/elements/http/request-log.html +0 -16
- package/demo/elements/http/request-log.ts +0 -136
- package/demo/elements/http/url-editing.html +0 -17
- package/demo/elements/http/url-editing.ts +0 -112
- package/demo/elements/icons/index.html +0 -81
- package/demo/elements/icons/index.ts +0 -52
- package/demo/elements/index.html +0 -72
- package/demo/elements/mention-textarea/index.html +0 -19
- package/demo/elements/mention-textarea/index.ts +0 -205
- package/demo/elements/navigation/navigation-item.html +0 -49
- package/demo/elements/navigation/navigation-item.ts +0 -131
- package/demo/elements/navigation/navigation.html +0 -20
- package/demo/elements/navigation/navigation.ts +0 -45
- package/demo/elements/project/index.html +0 -29
- package/demo/elements/project/project-run-report.html +0 -20
- package/demo/elements/project/project-run-report.ts +0 -132
- package/demo/elements/project/request-editor.html +0 -23
- package/demo/elements/project/request-editor.ts +0 -232
- package/demo/elements/user/user-avatar.html +0 -17
- package/demo/elements/user/user-avatar.ts +0 -60
- package/demo/env.js +0 -4
- package/demo/index.html +0 -34
- package/demo/layout/index.html +0 -94
- package/demo/layout/index.ts +0 -190
- package/demo/md/DemoStyles.ts +0 -61
- package/demo/md/UiDemoPage.ts +0 -6
- package/demo/md/buttons/button.html +0 -121
- package/demo/md/buttons/button.ts +0 -246
- package/demo/md/buttons/group.html +0 -36
- package/demo/md/buttons/group.ts +0 -171
- package/demo/md/checkbox/index.html +0 -39
- package/demo/md/checkbox/index.ts +0 -220
- package/demo/md/chip/chip.html +0 -70
- package/demo/md/chip/chip.ts +0 -219
- package/demo/md/chip/pawel6c9a.jpg +0 -0
- package/demo/md/collapse/CustomDetail.ts +0 -89
- package/demo/md/collapse/collapse.html +0 -21
- package/demo/md/collapse/collapse.ts +0 -78
- package/demo/md/date-picker/date-picker.ts +0 -336
- package/demo/md/date-picker/index.html +0 -171
- package/demo/md/dialog/confirm-dialog.html +0 -49
- package/demo/md/dialog/confirm-dialog.ts +0 -121
- package/demo/md/dialog/dialog.html +0 -25
- package/demo/md/dialog/dialog.ts +0 -468
- package/demo/md/dropdown-list/index.html +0 -31
- package/demo/md/dropdown-list/index.ts +0 -158
- package/demo/md/icon-button/index.html +0 -122
- package/demo/md/icon-button/index.ts +0 -132
- package/demo/md/index.html +0 -73
- package/demo/md/inputs/input.html +0 -73
- package/demo/md/inputs/input.ts +0 -278
- package/demo/md/inputs/radio.html +0 -39
- package/demo/md/inputs/radio.ts +0 -156
- package/demo/md/inputs/switch.html +0 -45
- package/demo/md/inputs/switch.ts +0 -144
- package/demo/md/list/list.html +0 -65
- package/demo/md/list/list.ts +0 -204
- package/demo/md/listbox/listbox.html +0 -31
- package/demo/md/listbox/listbox.ts +0 -27
- package/demo/md/menu/index.html +0 -19
- package/demo/md/menu/index.ts +0 -514
- package/demo/md/notification/snack.html +0 -21
- package/demo/md/notification/snack.ts +0 -70
- package/demo/md/progress/progress.html +0 -46
- package/demo/md/progress/progress.ts +0 -161
- package/demo/md/segmented-button/index.html +0 -21
- package/demo/md/segmented-button/index.ts +0 -55
- package/demo/md/select/index.html +0 -16
- package/demo/md/select/index.ts +0 -217
- package/demo/md/tabs/tabs.html +0 -40
- package/demo/md/tabs/tabs.ts +0 -214
- package/demo/oauth-popup.html +0 -36
- package/demo/page.css +0 -8
- package/demo/resources/calendar-month.png +0 -0
- package/demo/resources/favorite.png +0 -0
- package/demo/resources/fingerprint.png +0 -0
- package/demo/resources/home-work.png +0 -0
- package/demo/resources/mood.png +0 -0
- package/demo/resources/print.png +0 -0
- package/demo/resources/stars.png +0 -0
- package/demo/resources/theaters.png +0 -0
- package/demo/tsconfig.json +0 -4
- package/eslint.config.js +0 -97
- package/scripts/copy-assets.js +0 -21
- package/scripts/release.js +0 -66
- package/src/demo/DemoPage.ts +0 -169
- package/src/demo/DemoStyles.ts +0 -60
- package/test/README.md +0 -375
- package/test/contextual-menu/ContextMenu.test.ts +0 -760
- package/test/contextual-menu/ContextMenuElement.test.ts +0 -569
- package/test/core/activity.spec.ts +0 -413
- package/test/core/activity_manager.spec.ts +0 -544
- package/test/core/application.spec.ts +0 -218
- package/test/core/fragment.spec.ts +0 -565
- package/test/core/fragment_manager.spec.ts +0 -404
- package/test/core/live_data.spec.ts +0 -558
- package/test/core/renderer.spec.ts +0 -113
- package/test/dom-assertions.test.ts +0 -182
- package/test/elements/MonacoSetup.ts +0 -65
- package/test/elements/authorization/basic-method.test.ts +0 -177
- package/test/elements/authorization/bearer-method.test.ts +0 -143
- package/test/elements/authorization/ntlm-method.test.ts +0 -219
- package/test/elements/authorization/oauth2-client-credentials-method.test.ts +0 -334
- package/test/elements/authorization/oauth2-code-method.test.ts +0 -320
- package/test/elements/authorization/oauth2-custom-grant-method.test.ts +0 -255
- package/test/elements/authorization/oauth2-device-code-method.test.ts +0 -371
- package/test/elements/authorization/oauth2-implicit-method.test.ts +0 -407
- package/test/elements/authorization/oauth2-jwt-method.test.ts +0 -217
- package/test/elements/authorization/oauth2-password-method.test.ts +0 -275
- package/test/elements/authorization/openid-method.test.ts +0 -591
- package/test/elements/autocomplete/autocomplete-input.spec.ts +0 -646
- package/test/elements/code-editor/code-editor.accessibility.test.ts +0 -298
- package/test/elements/code-editor/code-editor.test.ts +0 -574
- package/test/elements/currency/CurrencyPicker.accessibility.test.ts +0 -328
- package/test/elements/currency/CurrencyPicker.core.test.ts +0 -318
- package/test/elements/currency/CurrencyPicker.integration.test.ts +0 -482
- package/test/elements/currency/CurrencyPicker.test.ts +0 -486
- package/test/elements/data-table/DataTable.browser.test.ts +0 -649
- package/test/elements/har/HarUtils.test.ts +0 -45
- package/test/elements/har/HarViewerElement.test.ts +0 -687
- package/test/elements/har/test-data/har1.har +0 -3044
- package/test/elements/highlight/MarkedHighlightElement.test.ts +0 -452
- package/test/elements/highlight/PrismHighlightElement.test.ts +0 -79
- package/test/elements/highlight/PrismHighlighter.test.ts +0 -94
- package/test/elements/highlight/remoteSanitization.md +0 -1
- package/test/elements/highlight/test.md +0 -3
- package/test/elements/highlight/test1.md +0 -3
- package/test/elements/highlight/test2.md +0 -1
- package/test/elements/http/BodyFormdataEditorElement.test.ts +0 -482
- package/test/elements/http/BodyMultipartEditorElement.test.ts +0 -658
- package/test/elements/http/BodyRawEditorElement.test.ts +0 -90
- package/test/elements/http/CertificateAdd.test.ts +0 -457
- package/test/elements/http/HttpAssertions.test.ts +0 -994
- package/test/elements/http/HttpFlows.test.ts +0 -502
- package/test/elements/http/UrlEncodeUtils.test.ts +0 -202
- package/test/elements/layout/SplitItem.test.ts +0 -440
- package/test/elements/layout/SplitLayoutManager.test.ts +0 -1501
- package/test/elements/layout/SplitPanel.test.ts +0 -1109
- package/test/elements/mention-textarea/MentionTextArea.basic.test.ts +0 -114
- package/test/elements/mention-textarea/MentionTextArea.test.ts +0 -613
- package/test/elements/navigation/Navigation.test.ts +0 -120
- package/test/env.ts +0 -15
- package/test/events/EventTypes.test.ts +0 -363
- package/test/events/EventsTestHelpers.ts +0 -16
- package/test/helpers/TestUtils.ts +0 -243
- package/test/helpers/UiMock.ts +0 -185
- package/test/lib/Dom.test.ts +0 -231
- package/test/md/button/UiButton.test.ts +0 -347
- package/test/md/button/UiIconButton.test.ts +0 -155
- package/test/md/chip/UiChip.test.ts +0 -219
- package/test/md/collapse/UiCollapse.test.ts +0 -250
- package/test/md/collapse/flex-layout.test.ts +0 -105
- package/test/md/date-time/DateTime.test.ts +0 -348
- package/test/md/dialog/UiConfirmDialog.test.ts +0 -131
- package/test/md/dialog/UiDialog.test.ts +0 -759
- package/test/md/menu/Menu.test.ts +0 -855
- package/test/md/menu/MenuIntegration.test.ts +0 -426
- package/test/md/menu/MenuItem.test.ts +0 -652
- package/test/md/menu/SubMenu.test.ts +0 -410
- package/test/md/progress/UiCircularProgressElement.test.ts +0 -481
- package/test/md/progress/UiProgressElement.test.ts +0 -117
- package/test/md/progress/UiRangeElement.test.ts +0 -156
- package/test/md/select/Select.test.ts +0 -925
- package/test/plugins/takeScreenshotPlugin.js +0 -35
- package/test/setup.test.ts +0 -217
- package/test/setup.ts +0 -117
- package/test/tsconfig.json +0 -7
- package/web-dev-server.config.js +0 -21
- package/web-test-runner.config.js +0 -90
|
@@ -1,482 +0,0 @@
|
|
|
1
|
-
import { fixture, assert, html } from '@open-wc/testing'
|
|
2
|
-
import CurrencyPicker from '../../../src/elements/currency/internals/Picker.js'
|
|
3
|
-
import sinon from 'sinon'
|
|
4
|
-
import '../../../src/elements/currency/currency-picker.js'
|
|
5
|
-
|
|
6
|
-
describe('CurrencyPicker - Integration', () => {
|
|
7
|
-
describe('Form Integration', () => {
|
|
8
|
-
async function formFixture(): Promise<{ form: HTMLFormElement; picker: CurrencyPicker }> {
|
|
9
|
-
const form = (await fixture(html`
|
|
10
|
-
<form>
|
|
11
|
-
<currency-picker name="currencies" label="Select Currencies" .selected="${['USD']}"></currency-picker>
|
|
12
|
-
<button type="submit">Submit</button>
|
|
13
|
-
</form>
|
|
14
|
-
`)) as HTMLFormElement
|
|
15
|
-
const picker = form.querySelector('currency-picker') as CurrencyPicker
|
|
16
|
-
return { form, picker }
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async function multiFormFixture(): Promise<{
|
|
20
|
-
form: HTMLFormElement
|
|
21
|
-
picker1: CurrencyPicker
|
|
22
|
-
picker2: CurrencyPicker
|
|
23
|
-
}> {
|
|
24
|
-
const form = (await fixture(html`
|
|
25
|
-
<form>
|
|
26
|
-
<currency-picker name="baseCurrency" label="Base Currency" .selected="${['USD']}"></currency-picker>
|
|
27
|
-
<currency-picker
|
|
28
|
-
name="targetCurrencies"
|
|
29
|
-
label="Target Currencies"
|
|
30
|
-
multi
|
|
31
|
-
.selected="${['EUR', 'GBP']}"
|
|
32
|
-
></currency-picker>
|
|
33
|
-
<button type="submit">Submit</button>
|
|
34
|
-
</form>
|
|
35
|
-
`)) as HTMLFormElement
|
|
36
|
-
const picker1 = form.querySelector('currency-picker[name="baseCurrency"]') as CurrencyPicker
|
|
37
|
-
const picker2 = form.querySelector('currency-picker[name="targetCurrencies"]') as CurrencyPicker
|
|
38
|
-
return { form, picker1, picker2 }
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
it('should submit form data correctly', async () => {
|
|
42
|
-
const { form } = await formFixture()
|
|
43
|
-
|
|
44
|
-
const formData = new FormData(form)
|
|
45
|
-
assert.equal(formData.get('currencies'), 'USD')
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
it('should update form data when selection changes', async () => {
|
|
49
|
-
const { form, picker } = await formFixture()
|
|
50
|
-
|
|
51
|
-
// Enable multi-select for this test
|
|
52
|
-
picker.multi = true
|
|
53
|
-
picker.selected = ['EUR', 'GBP']
|
|
54
|
-
await picker.updateComplete
|
|
55
|
-
|
|
56
|
-
const formData = new FormData(form)
|
|
57
|
-
assert.equal(formData.get('currencies'), 'EUR,GBP')
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('should handle form validation', async () => {
|
|
61
|
-
const { form, picker } = await formFixture()
|
|
62
|
-
picker.required = true
|
|
63
|
-
|
|
64
|
-
// Clear selection to trigger validation
|
|
65
|
-
picker.selected = []
|
|
66
|
-
await picker.updateComplete
|
|
67
|
-
|
|
68
|
-
const isValid = form.checkValidity()
|
|
69
|
-
assert.isFalse(isValid)
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
it('should reset with form reset', async () => {
|
|
73
|
-
const { form, picker } = await formFixture()
|
|
74
|
-
|
|
75
|
-
picker.selected = ['EUR', 'GBP']
|
|
76
|
-
await picker.updateComplete
|
|
77
|
-
|
|
78
|
-
form.reset()
|
|
79
|
-
await picker.updateComplete
|
|
80
|
-
|
|
81
|
-
assert.deepEqual(picker.selected, [])
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('should handle multiple pickers in one form', async () => {
|
|
85
|
-
const { form } = await multiFormFixture()
|
|
86
|
-
|
|
87
|
-
const formData = new FormData(form)
|
|
88
|
-
assert.equal(formData.get('baseCurrency'), 'USD')
|
|
89
|
-
assert.equal(formData.get('targetCurrencies'), 'EUR,GBP')
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
it('should maintain independent state for multiple pickers', async () => {
|
|
93
|
-
const { form, picker1, picker2 } = await multiFormFixture()
|
|
94
|
-
|
|
95
|
-
picker1.selected = ['JPY']
|
|
96
|
-
picker2.selected = ['CAD', 'AUD']
|
|
97
|
-
await Promise.all([picker1.updateComplete, picker2.updateComplete])
|
|
98
|
-
|
|
99
|
-
const formData = new FormData(form)
|
|
100
|
-
assert.equal(formData.get('baseCurrency'), 'JPY')
|
|
101
|
-
assert.equal(formData.get('targetCurrencies'), 'CAD,AUD')
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
it('should prevent a form from submitting', async () => {
|
|
105
|
-
const { form, picker } = await formFixture()
|
|
106
|
-
|
|
107
|
-
// Set required first, then clear selection to trigger validation
|
|
108
|
-
picker.required = true
|
|
109
|
-
await picker.updateComplete
|
|
110
|
-
|
|
111
|
-
picker.selected = ['USD'] // Set a value first
|
|
112
|
-
await picker.updateComplete
|
|
113
|
-
picker.selected = [] // Then clear to trigger validation
|
|
114
|
-
await picker.updateComplete
|
|
115
|
-
|
|
116
|
-
// Check that error state is set (indicating validation failed)
|
|
117
|
-
const isInvalid = !picker.validity.valid
|
|
118
|
-
const selectElement = picker.shadowRoot?.querySelector('ui-select')
|
|
119
|
-
const hasAriaInvalid = selectElement?.getAttribute('aria-invalid') === 'true'
|
|
120
|
-
|
|
121
|
-
assert.isTrue(isInvalid, 'Component should be in invalid state when validation fails')
|
|
122
|
-
assert.isTrue(hasAriaInvalid, 'Select element should have aria-invalid=true when validation fails')
|
|
123
|
-
|
|
124
|
-
const spy = sinon.spy()
|
|
125
|
-
form.addEventListener('submit', spy)
|
|
126
|
-
const submitButton = form.querySelector('button[type="submit"]') as HTMLButtonElement
|
|
127
|
-
submitButton.click()
|
|
128
|
-
|
|
129
|
-
assert.isFalse(spy.called)
|
|
130
|
-
})
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
describe('Real-world Usage Scenarios', () => {
|
|
134
|
-
async function ecommerceFixture(): Promise<{
|
|
135
|
-
container: HTMLElement
|
|
136
|
-
baseCurrencyPicker: CurrencyPicker
|
|
137
|
-
displayCurrenciesPicker: CurrencyPicker
|
|
138
|
-
}> {
|
|
139
|
-
const container = (await fixture(html`
|
|
140
|
-
<div class="ecommerce-settings">
|
|
141
|
-
<h2>Currency Settings</h2>
|
|
142
|
-
<currency-picker
|
|
143
|
-
name="baseCurrency"
|
|
144
|
-
label="Base Currency"
|
|
145
|
-
required
|
|
146
|
-
.allowedCurrencies="${['USD', 'EUR', 'GBP']}"
|
|
147
|
-
></currency-picker>
|
|
148
|
-
|
|
149
|
-
<currency-picker
|
|
150
|
-
name="displayCurrencies"
|
|
151
|
-
label="Display Currencies"
|
|
152
|
-
multi
|
|
153
|
-
required
|
|
154
|
-
.allowedCurrencies="${['USD', 'EUR', 'GBP', 'JPY', 'CAD']}"
|
|
155
|
-
></currency-picker>
|
|
156
|
-
</div>
|
|
157
|
-
`)) as HTMLElement
|
|
158
|
-
|
|
159
|
-
const baseCurrencyPicker = container.querySelector('[name="baseCurrency"]') as CurrencyPicker
|
|
160
|
-
const displayCurrenciesPicker = container.querySelector('[name="displayCurrencies"]') as CurrencyPicker
|
|
161
|
-
|
|
162
|
-
return { container, baseCurrencyPicker, displayCurrenciesPicker }
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
async function tradingFixture(): Promise<{
|
|
166
|
-
container: HTMLElement
|
|
167
|
-
fromPicker: CurrencyPicker
|
|
168
|
-
toPicker: CurrencyPicker
|
|
169
|
-
}> {
|
|
170
|
-
const container = (await fixture(html`
|
|
171
|
-
<div class="currency-exchange">
|
|
172
|
-
<h2>Currency Exchange</h2>
|
|
173
|
-
<currency-picker name="fromCurrency" label="From Currency" required .selected="${['USD']}"></currency-picker>
|
|
174
|
-
|
|
175
|
-
<currency-picker name="toCurrency" label="To Currency" required .selected="${['EUR']}"></currency-picker>
|
|
176
|
-
</div>
|
|
177
|
-
`)) as HTMLElement
|
|
178
|
-
|
|
179
|
-
const fromPicker = container.querySelector('[name="fromCurrency"]') as CurrencyPicker
|
|
180
|
-
const toPicker = container.querySelector('[name="toCurrency"]') as CurrencyPicker
|
|
181
|
-
|
|
182
|
-
return { container, fromPicker, toPicker }
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
it('should handle ecommerce currency settings scenario', async () => {
|
|
186
|
-
const { baseCurrencyPicker, displayCurrenciesPicker } = await ecommerceFixture()
|
|
187
|
-
|
|
188
|
-
// Set up typical ecommerce configuration
|
|
189
|
-
baseCurrencyPicker.selected = ['USD']
|
|
190
|
-
displayCurrenciesPicker.selected = ['USD', 'EUR', 'GBP']
|
|
191
|
-
|
|
192
|
-
await Promise.all([baseCurrencyPicker.updateComplete, displayCurrenciesPicker.updateComplete])
|
|
193
|
-
|
|
194
|
-
// Verify configuration
|
|
195
|
-
assert.deepEqual(baseCurrencyPicker.selected, ['USD'])
|
|
196
|
-
assert.deepEqual(displayCurrenciesPicker.selected, ['USD', 'EUR', 'GBP'])
|
|
197
|
-
|
|
198
|
-
// Verify base currency is included in display currencies
|
|
199
|
-
assert.include(displayCurrenciesPicker.selected, baseCurrencyPicker.selected[0])
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
it('should handle currency trading pair scenario', async () => {
|
|
203
|
-
const { fromPicker, toPicker } = await tradingFixture()
|
|
204
|
-
|
|
205
|
-
// Simulate changing trading pair
|
|
206
|
-
fromPicker.selected = ['GBP']
|
|
207
|
-
toPicker.selected = ['JPY']
|
|
208
|
-
|
|
209
|
-
await Promise.all([fromPicker.updateComplete, toPicker.updateComplete])
|
|
210
|
-
|
|
211
|
-
// Verify the pair is set correctly
|
|
212
|
-
assert.deepEqual(fromPicker.selected, ['GBP'])
|
|
213
|
-
assert.deepEqual(toPicker.selected, ['JPY'])
|
|
214
|
-
|
|
215
|
-
// Verify they have different selections
|
|
216
|
-
assert.notDeepEqual(fromPicker.selected, toPicker.selected)
|
|
217
|
-
})
|
|
218
|
-
|
|
219
|
-
it('should handle dynamic allowed currencies based on business rules', async () => {
|
|
220
|
-
const { baseCurrencyPicker, displayCurrenciesPicker } = await ecommerceFixture()
|
|
221
|
-
|
|
222
|
-
// Simulate business rule: display currencies depend on base currency
|
|
223
|
-
baseCurrencyPicker.selected = ['EUR']
|
|
224
|
-
await baseCurrencyPicker.updateComplete
|
|
225
|
-
|
|
226
|
-
// Update allowed display currencies based on base currency
|
|
227
|
-
if (baseCurrencyPicker.selected[0] === 'EUR') {
|
|
228
|
-
displayCurrenciesPicker.allowedCurrencies = ['EUR', 'GBP', 'USD']
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
await displayCurrenciesPicker.updateComplete
|
|
232
|
-
|
|
233
|
-
// Verify the business rule is applied
|
|
234
|
-
assert.deepEqual(displayCurrenciesPicker.allowedCurrencies, ['EUR', 'GBP', 'USD'])
|
|
235
|
-
})
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
describe('Error Recovery Scenarios', () => {
|
|
239
|
-
async function errorRecoveryFixture(): Promise<CurrencyPicker> {
|
|
240
|
-
return fixture(html` <currency-picker required showErrors label="Test Currency Picker"></currency-picker> `)
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
it('should recover from validation errors', async () => {
|
|
244
|
-
const picker = await errorRecoveryFixture()
|
|
245
|
-
|
|
246
|
-
// Trigger validation error
|
|
247
|
-
picker.selected = []
|
|
248
|
-
await picker.updateComplete
|
|
249
|
-
|
|
250
|
-
// Verify error state
|
|
251
|
-
assert.isTrue(!picker.validity.valid, 'Component should be in invalid state')
|
|
252
|
-
|
|
253
|
-
// Recover by selecting a currency
|
|
254
|
-
picker.selected = ['USD']
|
|
255
|
-
await picker.updateComplete
|
|
256
|
-
|
|
257
|
-
// Verify recovery
|
|
258
|
-
assert.isTrue(picker.validity.valid, 'Component should be in valid state after recovery')
|
|
259
|
-
})
|
|
260
|
-
|
|
261
|
-
it('should handle invalid data gracefully', async () => {
|
|
262
|
-
const picker = await errorRecoveryFixture()
|
|
263
|
-
|
|
264
|
-
// Set invalid currency codes
|
|
265
|
-
picker.selected = ['INVALID1', 'INVALID2', 'USD']
|
|
266
|
-
await picker.updateComplete
|
|
267
|
-
|
|
268
|
-
// Should filter out invalid codes and keep valid ones
|
|
269
|
-
assert.include(picker.selected, 'USD')
|
|
270
|
-
assert.notInclude(picker.selected, 'INVALID1')
|
|
271
|
-
assert.notInclude(picker.selected, 'INVALID2')
|
|
272
|
-
})
|
|
273
|
-
|
|
274
|
-
it('should maintain functionality after error recovery', async () => {
|
|
275
|
-
const picker = await errorRecoveryFixture()
|
|
276
|
-
picker.multi = true
|
|
277
|
-
|
|
278
|
-
// Cause and recover from error
|
|
279
|
-
picker.selected = ['INVALID']
|
|
280
|
-
await picker.updateComplete
|
|
281
|
-
|
|
282
|
-
picker.selected = ['USD']
|
|
283
|
-
await picker.updateComplete
|
|
284
|
-
|
|
285
|
-
// Should still be able to add more currencies
|
|
286
|
-
picker.selected = ['USD', 'EUR']
|
|
287
|
-
await picker.updateComplete
|
|
288
|
-
|
|
289
|
-
assert.deepEqual(picker.selected, ['USD', 'EUR'])
|
|
290
|
-
})
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
describe('Event Coordination', () => {
|
|
294
|
-
async function coordinatedPickersFixture(): Promise<{
|
|
295
|
-
container: HTMLElement
|
|
296
|
-
picker1: CurrencyPicker
|
|
297
|
-
picker2: CurrencyPicker
|
|
298
|
-
}> {
|
|
299
|
-
const container = (await fixture(html`
|
|
300
|
-
<div class="coordinated-pickers">
|
|
301
|
-
<currency-picker id="picker1" label="Source Currency" .selected="${['USD']}"></currency-picker>
|
|
302
|
-
|
|
303
|
-
<currency-picker id="picker2" label="Target Currency" .selected="${['EUR']}"></currency-picker>
|
|
304
|
-
</div>
|
|
305
|
-
`)) as HTMLElement
|
|
306
|
-
|
|
307
|
-
const picker1 = container.querySelector('#picker1') as CurrencyPicker
|
|
308
|
-
const picker2 = container.querySelector('#picker2') as CurrencyPicker
|
|
309
|
-
|
|
310
|
-
return { container, picker1, picker2 }
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
it('should coordinate between multiple pickers', async () => {
|
|
314
|
-
const { picker1, picker2 } = await coordinatedPickersFixture()
|
|
315
|
-
|
|
316
|
-
// Set up coordination: when picker1 changes, update picker2's allowed currencies
|
|
317
|
-
picker1.addEventListener('change', () => {
|
|
318
|
-
const selected = picker1.selected[0]
|
|
319
|
-
if (selected) {
|
|
320
|
-
// Don't allow same currency in both pickers
|
|
321
|
-
const allCurrencies = ['USD', 'EUR', 'GBP', 'JPY', 'CAD']
|
|
322
|
-
picker2.allowedCurrencies = allCurrencies.filter((c) => c !== selected)
|
|
323
|
-
}
|
|
324
|
-
})
|
|
325
|
-
|
|
326
|
-
// Change picker1 selection
|
|
327
|
-
picker1.selected = ['GBP']
|
|
328
|
-
await picker1.updateComplete
|
|
329
|
-
|
|
330
|
-
// Verify picker2 is updated
|
|
331
|
-
assert.notInclude(picker2.allowedCurrencies, 'GBP')
|
|
332
|
-
})
|
|
333
|
-
|
|
334
|
-
it('should handle cascading updates without infinite loops', async () => {
|
|
335
|
-
const { picker1, picker2 } = await coordinatedPickersFixture()
|
|
336
|
-
|
|
337
|
-
let updateCount = 0
|
|
338
|
-
const maxUpdates = 10
|
|
339
|
-
|
|
340
|
-
const handleUpdate = () => {
|
|
341
|
-
updateCount++
|
|
342
|
-
if (updateCount < maxUpdates) {
|
|
343
|
-
// Simulate some coordination logic
|
|
344
|
-
if (picker1.selected[0] === picker2.selected[0]) {
|
|
345
|
-
// Avoid same selection
|
|
346
|
-
picker2.selected = picker2.selected[0] === 'USD' ? ['EUR'] : ['USD']
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
picker1.addEventListener('change', handleUpdate)
|
|
352
|
-
picker2.addEventListener('change', handleUpdate)
|
|
353
|
-
|
|
354
|
-
// Trigger initial change
|
|
355
|
-
picker1.selected = ['EUR'] // Same as picker2's initial selection
|
|
356
|
-
await picker1.updateComplete
|
|
357
|
-
|
|
358
|
-
// Should not cause infinite loop
|
|
359
|
-
assert.isBelow(updateCount, maxUpdates)
|
|
360
|
-
})
|
|
361
|
-
})
|
|
362
|
-
|
|
363
|
-
describe('Dynamic Behavior', () => {
|
|
364
|
-
async function dynamicFixture(): Promise<CurrencyPicker> {
|
|
365
|
-
return fixture(html`<currency-picker></currency-picker>`)
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
it('should handle dynamic property changes', async () => {
|
|
369
|
-
const picker = await dynamicFixture()
|
|
370
|
-
|
|
371
|
-
// Start with basic configuration
|
|
372
|
-
picker.label = 'Initial Label'
|
|
373
|
-
picker.selected = ['USD']
|
|
374
|
-
await picker.updateComplete
|
|
375
|
-
|
|
376
|
-
// Dynamically enable multi-select
|
|
377
|
-
picker.multi = true
|
|
378
|
-
picker.selected = ['USD', 'EUR']
|
|
379
|
-
await picker.updateComplete
|
|
380
|
-
|
|
381
|
-
// Verify multi-select is working
|
|
382
|
-
const chips = picker.shadowRoot?.querySelectorAll('ui-chip')
|
|
383
|
-
assert.equal(chips?.length, 2)
|
|
384
|
-
|
|
385
|
-
// Dynamically change to required
|
|
386
|
-
picker.required = true
|
|
387
|
-
picker.selected = []
|
|
388
|
-
await picker.updateComplete
|
|
389
|
-
|
|
390
|
-
// Should show error
|
|
391
|
-
assert.isTrue(!picker.validity.valid, 'Component should be in invalid state when required and empty')
|
|
392
|
-
})
|
|
393
|
-
|
|
394
|
-
it('should handle dynamic allowed currencies', async () => {
|
|
395
|
-
const picker = await dynamicFixture()
|
|
396
|
-
picker.multi = true // Enable multi-select for this test
|
|
397
|
-
|
|
398
|
-
// Start with limited currencies
|
|
399
|
-
picker.allowedCurrencies = ['USD', 'EUR']
|
|
400
|
-
picker.selected = ['USD']
|
|
401
|
-
await picker.updateComplete
|
|
402
|
-
|
|
403
|
-
// Expand allowed currencies
|
|
404
|
-
picker.allowedCurrencies = ['USD', 'EUR', 'GBP', 'JPY']
|
|
405
|
-
await picker.updateComplete
|
|
406
|
-
|
|
407
|
-
// Should now allow selection of new currencies
|
|
408
|
-
picker.selected = ['USD', 'GBP']
|
|
409
|
-
await picker.updateComplete
|
|
410
|
-
|
|
411
|
-
assert.include(picker.selected, 'GBP')
|
|
412
|
-
|
|
413
|
-
// Restrict currencies again
|
|
414
|
-
picker.allowedCurrencies = ['USD', 'EUR']
|
|
415
|
-
await picker.updateComplete
|
|
416
|
-
|
|
417
|
-
// Should filter out disallowed currencies
|
|
418
|
-
assert.notInclude(picker.selected, 'GBP')
|
|
419
|
-
})
|
|
420
|
-
})
|
|
421
|
-
|
|
422
|
-
describe('Accessibility Integration', () => {
|
|
423
|
-
async function accessibilityFixture(): Promise<{
|
|
424
|
-
form: HTMLFormElement
|
|
425
|
-
picker: CurrencyPicker
|
|
426
|
-
submitButton: HTMLButtonElement
|
|
427
|
-
}> {
|
|
428
|
-
const form = (await fixture(html`
|
|
429
|
-
<form>
|
|
430
|
-
<label for="currency-picker">Select your preferred currency:</label>
|
|
431
|
-
<currency-picker
|
|
432
|
-
id="currency-picker"
|
|
433
|
-
name="currency"
|
|
434
|
-
required
|
|
435
|
-
aria-describedby="currency-help"
|
|
436
|
-
></currency-picker>
|
|
437
|
-
<div id="currency-help">Choose the currency for your account.</div>
|
|
438
|
-
<button type="submit">Save Settings</button>
|
|
439
|
-
</form>
|
|
440
|
-
`)) as HTMLFormElement
|
|
441
|
-
|
|
442
|
-
const picker = form.querySelector('currency-picker') as CurrencyPicker
|
|
443
|
-
const submitButton = form.querySelector('button[type="submit"]') as HTMLButtonElement
|
|
444
|
-
|
|
445
|
-
return { form, picker, submitButton }
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
it('should integrate properly with form labels and descriptions', async () => {
|
|
449
|
-
const { picker } = await accessibilityFixture()
|
|
450
|
-
|
|
451
|
-
// Verify ARIA relationships
|
|
452
|
-
assert.equal(picker.id, 'currency-picker')
|
|
453
|
-
assert.equal(picker.getAttribute('aria-describedby'), 'currency-help')
|
|
454
|
-
})
|
|
455
|
-
|
|
456
|
-
it('should announce validation errors appropriately', async () => {
|
|
457
|
-
const { picker } = await accessibilityFixture()
|
|
458
|
-
|
|
459
|
-
picker.showErrors = true
|
|
460
|
-
picker.selected = [] // Trigger required validation
|
|
461
|
-
await picker.updateComplete
|
|
462
|
-
|
|
463
|
-
const errorElement = picker.shadowRoot?.querySelector('[role="alert"]')
|
|
464
|
-
assert.exists(errorElement)
|
|
465
|
-
assert.equal(errorElement?.getAttribute('aria-live'), 'polite')
|
|
466
|
-
})
|
|
467
|
-
|
|
468
|
-
it('should maintain focus appropriately during interactions', async () => {
|
|
469
|
-
const { picker } = await accessibilityFixture()
|
|
470
|
-
|
|
471
|
-
const select = picker.shadowRoot?.querySelector('ui-select') as HTMLElement
|
|
472
|
-
select.focus()
|
|
473
|
-
|
|
474
|
-
// Simulate selection
|
|
475
|
-
picker.selected = ['USD']
|
|
476
|
-
await picker.updateComplete
|
|
477
|
-
|
|
478
|
-
// Focus should still be manageable
|
|
479
|
-
assert.exists(select)
|
|
480
|
-
})
|
|
481
|
-
})
|
|
482
|
-
})
|