@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.
- package/build/src/md/list/internals/ListItem.d.ts +24 -15
- package/build/src/md/list/internals/ListItem.d.ts.map +1 -1
- package/build/src/md/list/internals/ListItem.js +85 -59
- package/build/src/md/list/internals/ListItem.js.map +1 -1
- package/build/src/md/list/internals/ListItem.styles.js +11 -11
- package/build/src/md/list/internals/ListItem.styles.js.map +1 -1
- package/build/src/md/select/internals/Option.d.ts +4 -14
- package/build/src/md/select/internals/Option.d.ts.map +1 -1
- package/build/src/md/select/internals/Option.js +13 -28
- package/build/src/md/select/internals/Option.js.map +1 -1
- package/build/src/md/select/internals/Select.d.ts +1 -1
- package/build/src/md/select/internals/Select.d.ts.map +1 -1
- package/build/src/md/select/internals/Select.js +15 -5
- package/build/src/md/select/internals/Select.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -0
- package/package.json +1 -1
- package/src/md/list/internals/ListItem.styles.ts +11 -11
- package/src/md/list/internals/ListItem.ts +68 -43
- package/src/md/select/internals/Option.ts +14 -26
- package/src/md/select/internals/Select.ts +15 -5
- 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/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 -207
- 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,759 +0,0 @@
|
|
|
1
|
-
import { assert, fixture, html } from '@open-wc/testing'
|
|
2
|
-
import sinon from 'sinon'
|
|
3
|
-
import UiDialog, { UiDialogClosingReason } from '../../../src/md/dialog/internals/Dialog.js'
|
|
4
|
-
import { UiMock } from '../../helpers/UiMock.js'
|
|
5
|
-
import UiButton from '../../../src/md/button/internals/button.js'
|
|
6
|
-
|
|
7
|
-
import '../../../src/md/dialog/ui-dialog.js'
|
|
8
|
-
import '../../../src/md/icons/ui-icon.js'
|
|
9
|
-
import '../../../src/md/button/ui-button.js'
|
|
10
|
-
|
|
11
|
-
describe('md', () => {
|
|
12
|
-
describe('Dialog', () => {
|
|
13
|
-
async function basicFixture(): Promise<UiDialog> {
|
|
14
|
-
return fixture(html` <ui-dialog> Content </ui-dialog>`)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async function modalFixture(): Promise<UiDialog> {
|
|
18
|
-
return fixture(html` <ui-dialog modal> Content </ui-dialog>`)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async function iconFixture(): Promise<UiDialog> {
|
|
22
|
-
return fixture(
|
|
23
|
-
html` <ui-dialog>
|
|
24
|
-
<ui-icon slot="icon" icon="deleteOutline"></ui-icon>
|
|
25
|
-
Content
|
|
26
|
-
</ui-dialog>`
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async function titleFixture(): Promise<UiDialog> {
|
|
31
|
-
return fixture(
|
|
32
|
-
html` <ui-dialog>
|
|
33
|
-
<span slot="title">The title</span>
|
|
34
|
-
Content
|
|
35
|
-
</ui-dialog>`
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async function buttonFixture(): Promise<UiDialog> {
|
|
40
|
-
return fixture(
|
|
41
|
-
html` <ui-dialog>
|
|
42
|
-
Content
|
|
43
|
-
<ui-button color="text" slot="button">Learn more</ui-button>
|
|
44
|
-
<ui-button color="text" slot="button" value="dismiss">Cancel</ui-button>
|
|
45
|
-
<ui-button color="text" slot="button" value="confirm">Accept</ui-button>
|
|
46
|
-
</ui-dialog>`
|
|
47
|
-
)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
describe('open/close', () => {
|
|
51
|
-
it('opens the native dialog via the "open" attribute', async () => {
|
|
52
|
-
const element = await basicFixture()
|
|
53
|
-
assert.isFalse(element.dialog.open, 'native dialog is closed initially')
|
|
54
|
-
|
|
55
|
-
element.open = true
|
|
56
|
-
await element.updateComplete
|
|
57
|
-
assert.isTrue(element.dialog.open, 'native dialog is opened')
|
|
58
|
-
|
|
59
|
-
element.open = false
|
|
60
|
-
await element.updateComplete
|
|
61
|
-
assert.isFalse(element.dialog.open, 'native dialog is closed again')
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
it('closes the dialog via the Escape button', async () => {
|
|
65
|
-
const element = await buttonFixture()
|
|
66
|
-
// the dialog requires a focusable element
|
|
67
|
-
const button = element.querySelector('ui-button')!
|
|
68
|
-
button.focus()
|
|
69
|
-
await UiMock.keyPress(element, 'Escape', { key: 'Escape' })
|
|
70
|
-
assert.equal(element.open, false)
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
it('closes the dialog via the dismiss slotted button', async () => {
|
|
74
|
-
const element = await buttonFixture()
|
|
75
|
-
const button = element.querySelector('ui-button[value="dismiss"]') as UiButton
|
|
76
|
-
button.click()
|
|
77
|
-
assert.equal(element.open, false)
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
it('closes the dialog via the confirm slotted button', async () => {
|
|
81
|
-
const element = await buttonFixture()
|
|
82
|
-
const button = element.querySelector('ui-button[value="confirm"]') as UiButton
|
|
83
|
-
button.click()
|
|
84
|
-
assert.equal(element.open, false)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('closes the dialog via the dismissLabel button', async () => {
|
|
88
|
-
const element = await basicFixture()
|
|
89
|
-
element.dismissLabel = 'Close'
|
|
90
|
-
await element.updateComplete
|
|
91
|
-
const button = element.shadowRoot!.querySelector('.internal-button[value="dismiss"]') as UiButton
|
|
92
|
-
button.click()
|
|
93
|
-
assert.equal(element.open, false)
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
it('closes the dialog via the confirmLabel button', async () => {
|
|
97
|
-
const element = await basicFixture()
|
|
98
|
-
element.confirmLabel = 'Close'
|
|
99
|
-
await element.updateComplete
|
|
100
|
-
const button = element.shadowRoot!.querySelector('.internal-button[value="confirm"]') as UiButton
|
|
101
|
-
button.click()
|
|
102
|
-
assert.equal(element.open, false)
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
it('dispatches the close event with cancelled = true', async () => {
|
|
106
|
-
const element = await buttonFixture()
|
|
107
|
-
const spy = sinon.spy()
|
|
108
|
-
element.addEventListener('close', spy)
|
|
109
|
-
const button = element.querySelector('ui-button[value="dismiss"]') as UiButton
|
|
110
|
-
button.click()
|
|
111
|
-
assert.isTrue(spy.calledOnce, 'the event was dispatched')
|
|
112
|
-
const event = spy.args[0][0] as CustomEvent<UiDialogClosingReason>
|
|
113
|
-
assert.isTrue(event.detail.cancelled, 'the cancelled flag is set')
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
it('dispatches the close event with cancelled = true', async () => {
|
|
117
|
-
const element = await buttonFixture()
|
|
118
|
-
const spy = sinon.spy()
|
|
119
|
-
element.addEventListener('close', spy)
|
|
120
|
-
const button = element.querySelector('ui-button[value="confirm"]') as UiButton
|
|
121
|
-
button.click()
|
|
122
|
-
assert.isTrue(spy.calledOnce, 'the event was dispatched')
|
|
123
|
-
const event = spy.args[0][0] as CustomEvent<UiDialogClosingReason>
|
|
124
|
-
assert.isFalse(event.detail.cancelled, 'the cancelled flag is not set')
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
it('dispatches the dialogValue', async () => {
|
|
128
|
-
const element = await buttonFixture()
|
|
129
|
-
element.dialogValue = 'test'
|
|
130
|
-
const spy = sinon.spy()
|
|
131
|
-
element.addEventListener('close', spy)
|
|
132
|
-
const button = element.querySelector('ui-button[value="confirm"]') as UiButton
|
|
133
|
-
button.click()
|
|
134
|
-
assert.isTrue(spy.calledOnce, 'the event was dispatched')
|
|
135
|
-
const event = spy.args[0][0] as CustomEvent<UiDialogClosingReason>
|
|
136
|
-
assert.equal(event.detail.value, 'test', 'has the value')
|
|
137
|
-
})
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
describe('modal dialog', () => {
|
|
141
|
-
it('opens the dialog as modal', async () => {
|
|
142
|
-
const element = await modalFixture()
|
|
143
|
-
const spy = sinon.spy(element.dialog, 'showModal')
|
|
144
|
-
element.open = true
|
|
145
|
-
await element.updateComplete
|
|
146
|
-
assert.isTrue(spy.calledOnce)
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
it('applies modal class to dialog when modal is true', async () => {
|
|
150
|
-
const element = await basicFixture()
|
|
151
|
-
element.modal = true
|
|
152
|
-
await element.updateComplete
|
|
153
|
-
|
|
154
|
-
const dialog = element.shadowRoot!.querySelector('dialog') as HTMLDialogElement
|
|
155
|
-
assert.ok(dialog, 'has the dialog element')
|
|
156
|
-
assert.isTrue(dialog.classList.contains('modal'), 'has modal class')
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
it('applies non-modal class to dialog when modal is false', async () => {
|
|
160
|
-
const element = await basicFixture()
|
|
161
|
-
element.modal = false
|
|
162
|
-
await element.updateComplete
|
|
163
|
-
|
|
164
|
-
const dialog = element.shadowRoot!.querySelector('dialog') as HTMLDialogElement
|
|
165
|
-
assert.ok(dialog, 'has the dialog element')
|
|
166
|
-
assert.isTrue(dialog.classList.contains('non-modal'), 'has non-modal class')
|
|
167
|
-
})
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
describe('icon', () => {
|
|
171
|
-
it('renders the icon slot', async () => {
|
|
172
|
-
const element = await basicFixture()
|
|
173
|
-
const slot = element.shadowRoot!.querySelector('slot[name="icon"]') as HTMLSlotElement
|
|
174
|
-
assert.ok(slot, 'has the slot')
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
it('does not render padding around the icon slot', async () => {
|
|
178
|
-
const element = await basicFixture()
|
|
179
|
-
const container = element.shadowRoot!.querySelector('.icon') as HTMLElement
|
|
180
|
-
assert.isFalse(container.classList.contains('with-icon'), 'has no with-icon class')
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
it('renders padding around the icon slot with an icon', async () => {
|
|
184
|
-
const element = await iconFixture()
|
|
185
|
-
const container = element.shadowRoot!.querySelector('.icon') as HTMLElement
|
|
186
|
-
assert.isTrue(container.classList.contains('with-icon'), 'has the with-icon class')
|
|
187
|
-
})
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
describe('title', () => {
|
|
191
|
-
it('renders the title slot', async () => {
|
|
192
|
-
const element = await basicFixture()
|
|
193
|
-
const slot = element.shadowRoot!.querySelector('slot[name="title"]') as HTMLSlotElement
|
|
194
|
-
assert.ok(slot, 'has the slot')
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
it('does not render padding around the title slot', async () => {
|
|
198
|
-
const element = await basicFixture()
|
|
199
|
-
const container = element.shadowRoot!.querySelector('.title') as HTMLElement
|
|
200
|
-
assert.isFalse(container.classList.contains('with-title'), 'has no with-title class')
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
it('renders padding around the title slot with a title', async () => {
|
|
204
|
-
const element = await titleFixture()
|
|
205
|
-
const container = element.shadowRoot!.querySelector('.title') as HTMLElement
|
|
206
|
-
assert.isTrue(container.classList.contains('with-title'), 'has the with-title class')
|
|
207
|
-
})
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
describe('buttons', () => {
|
|
211
|
-
it('renders the button slot', async () => {
|
|
212
|
-
const element = await basicFixture()
|
|
213
|
-
const slot = element.shadowRoot!.querySelector('slot[name="button"]') as HTMLSlotElement
|
|
214
|
-
assert.ok(slot, 'has the slot')
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
it('does not render padding around the buttons slot', async () => {
|
|
218
|
-
const element = await basicFixture()
|
|
219
|
-
const container = element.shadowRoot!.querySelector('.buttons') as HTMLElement
|
|
220
|
-
assert.isFalse(container.classList.contains('with-buttons'), 'has no with-buttons class')
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
it('renders the confirm button', async () => {
|
|
224
|
-
const element = await basicFixture()
|
|
225
|
-
element.confirmLabel = 'OK label'
|
|
226
|
-
await element.updateComplete
|
|
227
|
-
const container = element.shadowRoot!.querySelector('.buttons') as HTMLElement
|
|
228
|
-
assert.isTrue(container.classList.contains('with-buttons'), 'has the with-buttons class')
|
|
229
|
-
const button = element.shadowRoot!.querySelector('.internal-button') as UiButton
|
|
230
|
-
assert.ok(button, 'has the button')
|
|
231
|
-
assert.equal(button.value, 'confirm')
|
|
232
|
-
assert.equal(button.textContent!.trim(), 'OK label')
|
|
233
|
-
})
|
|
234
|
-
|
|
235
|
-
it('renders the dismiss button', async () => {
|
|
236
|
-
const element = await basicFixture()
|
|
237
|
-
element.dismissLabel = 'Cancel label'
|
|
238
|
-
await element.updateComplete
|
|
239
|
-
const container = element.shadowRoot!.querySelector('.buttons') as HTMLElement
|
|
240
|
-
assert.isTrue(container.classList.contains('with-buttons'), 'has the with-buttons class')
|
|
241
|
-
const button = element.shadowRoot!.querySelector('.internal-button') as UiButton
|
|
242
|
-
assert.ok(button, 'has the button')
|
|
243
|
-
assert.equal(button.value, 'dismiss')
|
|
244
|
-
assert.equal(button.textContent!.trim(), 'Cancel label')
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
it('renders the slotted buttons', async () => {
|
|
248
|
-
const element = await buttonFixture()
|
|
249
|
-
const container = element.shadowRoot!.querySelector('.buttons') as HTMLElement
|
|
250
|
-
assert.isTrue(container.classList.contains('with-buttons'), 'has the with-buttons class')
|
|
251
|
-
})
|
|
252
|
-
|
|
253
|
-
it('applies destructive class to confirm button when destructive is true', async () => {
|
|
254
|
-
const element = await basicFixture()
|
|
255
|
-
element.confirmLabel = 'Delete'
|
|
256
|
-
element.destructive = true
|
|
257
|
-
await element.updateComplete
|
|
258
|
-
|
|
259
|
-
const button = element.shadowRoot!.querySelector('.internal-button[value="confirm"]') as UiButton
|
|
260
|
-
assert.ok(button, 'has the confirm button')
|
|
261
|
-
assert.isTrue(button.classList.contains('destructive'), 'has destructive class')
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
it('does not apply destructive class when destructive is false', async () => {
|
|
265
|
-
const element = await basicFixture()
|
|
266
|
-
element.confirmLabel = 'Confirm'
|
|
267
|
-
element.destructive = false
|
|
268
|
-
await element.updateComplete
|
|
269
|
-
|
|
270
|
-
const button = element.shadowRoot!.querySelector('.internal-button[value="confirm"]') as UiButton
|
|
271
|
-
assert.ok(button, 'has the confirm button')
|
|
272
|
-
assert.isFalse(button.classList.contains('destructive'), 'does not have destructive class')
|
|
273
|
-
})
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
describe('form handling', () => {
|
|
277
|
-
async function formWrappedDialogFixture(): Promise<{ form: HTMLFormElement; dialog: UiDialog }> {
|
|
278
|
-
const container = await fixture(html`
|
|
279
|
-
<form>
|
|
280
|
-
<ui-dialog submitClose>
|
|
281
|
-
<span slot="title">Form Dialog</span>
|
|
282
|
-
<input type="text" name="username" required />
|
|
283
|
-
<ui-button color="text" slot="button" value="dismiss">Cancel</ui-button>
|
|
284
|
-
<ui-button color="text" slot="button" value="confirm" type="submit">Submit</ui-button>
|
|
285
|
-
</ui-dialog>
|
|
286
|
-
</form>
|
|
287
|
-
`)
|
|
288
|
-
const form = container as HTMLFormElement
|
|
289
|
-
const dialog = form.querySelector('ui-dialog') as UiDialog
|
|
290
|
-
return { form, dialog }
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
async function formWithoutSubmitCloseFixture(): Promise<{ form: HTMLFormElement; dialog: UiDialog }> {
|
|
294
|
-
const container = await fixture(html`
|
|
295
|
-
<form>
|
|
296
|
-
<ui-dialog>
|
|
297
|
-
<span slot="title">Form Dialog</span>
|
|
298
|
-
<input type="text" name="username" required />
|
|
299
|
-
<ui-button color="text" slot="button" value="dismiss">Cancel</ui-button>
|
|
300
|
-
<ui-button color="text" slot="button" value="confirm" type="submit">Submit</ui-button>
|
|
301
|
-
</ui-dialog>
|
|
302
|
-
</form>
|
|
303
|
-
`)
|
|
304
|
-
const form = container as HTMLFormElement
|
|
305
|
-
const dialog = form.querySelector('ui-dialog') as UiDialog
|
|
306
|
-
return { form, dialog }
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
describe('dialog wrapped in form', () => {
|
|
310
|
-
it('should detect parent form when connected', async () => {
|
|
311
|
-
const { dialog } = await formWrappedDialogFixture()
|
|
312
|
-
await dialog.updateComplete
|
|
313
|
-
|
|
314
|
-
// The form should be detected during connectedCallback
|
|
315
|
-
// We can't directly access private fields, so we test the behavior instead
|
|
316
|
-
assert.ok(dialog.submitClose, 'dialog should be configured for form handling')
|
|
317
|
-
})
|
|
318
|
-
|
|
319
|
-
it('should close dialog when form is submitted and submitClose is true', async () => {
|
|
320
|
-
const { form, dialog } = await formWrappedDialogFixture()
|
|
321
|
-
dialog.open = true
|
|
322
|
-
await dialog.updateComplete
|
|
323
|
-
|
|
324
|
-
const spy = sinon.spy()
|
|
325
|
-
dialog.addEventListener('close', spy)
|
|
326
|
-
|
|
327
|
-
// Simulate form submission
|
|
328
|
-
const submitEvent = new SubmitEvent('submit', { bubbles: true, cancelable: true })
|
|
329
|
-
form.dispatchEvent(submitEvent)
|
|
330
|
-
|
|
331
|
-
assert.isFalse(dialog.open, 'dialog should be closed')
|
|
332
|
-
assert.isTrue(spy.calledOnce, 'close event should be dispatched')
|
|
333
|
-
const event = spy.args[0][0] as CustomEvent
|
|
334
|
-
assert.isFalse(event.detail.cancelled, 'dialog should be confirmed, not cancelled')
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
it('should not close dialog when form is submitted and submitClose is false', async () => {
|
|
338
|
-
const { form, dialog } = await formWithoutSubmitCloseFixture()
|
|
339
|
-
dialog.open = true
|
|
340
|
-
await dialog.updateComplete
|
|
341
|
-
|
|
342
|
-
const spy = sinon.spy()
|
|
343
|
-
dialog.addEventListener('close', spy)
|
|
344
|
-
|
|
345
|
-
// Simulate form submission
|
|
346
|
-
const submitEvent = new SubmitEvent('submit', { bubbles: true, cancelable: true })
|
|
347
|
-
form.dispatchEvent(submitEvent)
|
|
348
|
-
|
|
349
|
-
assert.isTrue(dialog.open, 'dialog should remain open')
|
|
350
|
-
assert.isFalse(spy.called, 'close event should not be dispatched')
|
|
351
|
-
})
|
|
352
|
-
|
|
353
|
-
it('should not handle form submit when submit button is clicked directly', async () => {
|
|
354
|
-
const { dialog } = await formWrappedDialogFixture()
|
|
355
|
-
dialog.open = true
|
|
356
|
-
await dialog.updateComplete
|
|
357
|
-
|
|
358
|
-
const submitButton = dialog.querySelector('ui-button[type="submit"]') as UiButton
|
|
359
|
-
const spy = sinon.spy()
|
|
360
|
-
dialog.addEventListener('close', spy)
|
|
361
|
-
|
|
362
|
-
// Click the submit button - this should not close the dialog immediately
|
|
363
|
-
// because we yield control to the form
|
|
364
|
-
submitButton.click()
|
|
365
|
-
|
|
366
|
-
// The dialog should still be open because the form hasn't been submitted yet
|
|
367
|
-
assert.isTrue(dialog.open, 'dialog should remain open when submit button is clicked')
|
|
368
|
-
})
|
|
369
|
-
|
|
370
|
-
it('should remove form event listener when disconnected', async () => {
|
|
371
|
-
const { form, dialog } = await formWrappedDialogFixture()
|
|
372
|
-
const removeEventListenerSpy = sinon.spy(form, 'removeEventListener')
|
|
373
|
-
|
|
374
|
-
dialog.remove()
|
|
375
|
-
|
|
376
|
-
// We can't test the private method directly, but we can verify the spy was called
|
|
377
|
-
// The actual method name is not accessible, so we test the behavior instead
|
|
378
|
-
assert.isTrue(removeEventListenerSpy.called, 'removeEventListener should be called on form')
|
|
379
|
-
})
|
|
380
|
-
})
|
|
381
|
-
|
|
382
|
-
describe('edge cases', () => {
|
|
383
|
-
it('should handle form submission when dialog is not open', async () => {
|
|
384
|
-
const { form, dialog } = await formWrappedDialogFixture()
|
|
385
|
-
// Dialog is closed by default
|
|
386
|
-
assert.isFalse(dialog.open, 'dialog should be closed initially')
|
|
387
|
-
|
|
388
|
-
const spy = sinon.spy()
|
|
389
|
-
dialog.addEventListener('close', spy)
|
|
390
|
-
|
|
391
|
-
// Submit form when dialog is closed
|
|
392
|
-
const submitEvent = new SubmitEvent('submit', { bubbles: true, cancelable: true })
|
|
393
|
-
form.dispatchEvent(submitEvent)
|
|
394
|
-
|
|
395
|
-
// Should still close the dialog (set open to false even though it's already false)
|
|
396
|
-
assert.isFalse(dialog.open, 'dialog should remain closed')
|
|
397
|
-
assert.isTrue(spy.calledOnce, 'close event should still be dispatched')
|
|
398
|
-
})
|
|
399
|
-
|
|
400
|
-
it('should handle multiple form submissions', async () => {
|
|
401
|
-
const { form, dialog } = await formWrappedDialogFixture()
|
|
402
|
-
dialog.open = true
|
|
403
|
-
await dialog.updateComplete
|
|
404
|
-
|
|
405
|
-
const spy = sinon.spy()
|
|
406
|
-
dialog.addEventListener('close', spy)
|
|
407
|
-
|
|
408
|
-
// Submit form multiple times
|
|
409
|
-
const submitEvent1 = new SubmitEvent('submit', { bubbles: true, cancelable: true })
|
|
410
|
-
const submitEvent2 = new SubmitEvent('submit', { bubbles: true, cancelable: true })
|
|
411
|
-
|
|
412
|
-
form.dispatchEvent(submitEvent1)
|
|
413
|
-
form.dispatchEvent(submitEvent2)
|
|
414
|
-
|
|
415
|
-
assert.equal(spy.callCount, 2, 'close event should be dispatched for each submission')
|
|
416
|
-
})
|
|
417
|
-
|
|
418
|
-
it('should maintain form reference across re-connections', async () => {
|
|
419
|
-
const { form, dialog } = await formWrappedDialogFixture()
|
|
420
|
-
|
|
421
|
-
// Remove and re-add dialog
|
|
422
|
-
const parent = form
|
|
423
|
-
dialog.remove()
|
|
424
|
-
await dialog.updateComplete
|
|
425
|
-
|
|
426
|
-
parent.appendChild(dialog)
|
|
427
|
-
await dialog.updateComplete
|
|
428
|
-
|
|
429
|
-
// Test the behavior instead of accessing private fields
|
|
430
|
-
// If form handling is working, submitClose should still work
|
|
431
|
-
dialog.open = true
|
|
432
|
-
await dialog.updateComplete
|
|
433
|
-
|
|
434
|
-
const spy = sinon.spy()
|
|
435
|
-
dialog.addEventListener('close', spy)
|
|
436
|
-
|
|
437
|
-
const submitEvent = new SubmitEvent('submit', { bubbles: true, cancelable: true })
|
|
438
|
-
form.dispatchEvent(submitEvent)
|
|
439
|
-
|
|
440
|
-
assert.isTrue(spy.called, 'form handling should work after reconnection')
|
|
441
|
-
})
|
|
442
|
-
})
|
|
443
|
-
})
|
|
444
|
-
|
|
445
|
-
describe('closing event', () => {
|
|
446
|
-
it('dispatches the closing event before close event when dismissing', async () => {
|
|
447
|
-
const element = await buttonFixture()
|
|
448
|
-
const closingSpy = sinon.spy()
|
|
449
|
-
const closeSpy = sinon.spy()
|
|
450
|
-
element.addEventListener('closing', closingSpy)
|
|
451
|
-
element.addEventListener('close', closeSpy)
|
|
452
|
-
|
|
453
|
-
const button = element.querySelector('ui-button[value="dismiss"]') as UiButton
|
|
454
|
-
button.click()
|
|
455
|
-
|
|
456
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched')
|
|
457
|
-
assert.isTrue(closeSpy.calledOnce, 'close event was dispatched')
|
|
458
|
-
assert.isTrue(closingSpy.calledBefore(closeSpy), 'closing event was dispatched before close event')
|
|
459
|
-
})
|
|
460
|
-
|
|
461
|
-
it('dispatches the closing event before close event when confirming', async () => {
|
|
462
|
-
const element = await buttonFixture()
|
|
463
|
-
const closingSpy = sinon.spy()
|
|
464
|
-
const closeSpy = sinon.spy()
|
|
465
|
-
element.addEventListener('closing', closingSpy)
|
|
466
|
-
element.addEventListener('close', closeSpy)
|
|
467
|
-
|
|
468
|
-
const button = element.querySelector('ui-button[value="confirm"]') as UiButton
|
|
469
|
-
button.click()
|
|
470
|
-
|
|
471
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched')
|
|
472
|
-
assert.isTrue(closeSpy.calledOnce, 'close event was dispatched')
|
|
473
|
-
assert.isTrue(closingSpy.calledBefore(closeSpy), 'closing event was dispatched before close event')
|
|
474
|
-
})
|
|
475
|
-
|
|
476
|
-
it('dispatches the closing event when pressing Escape', async () => {
|
|
477
|
-
const element = await buttonFixture()
|
|
478
|
-
const closingSpy = sinon.spy()
|
|
479
|
-
const closeSpy = sinon.spy()
|
|
480
|
-
element.addEventListener('closing', closingSpy)
|
|
481
|
-
element.addEventListener('close', closeSpy)
|
|
482
|
-
|
|
483
|
-
element.open = true
|
|
484
|
-
await element.updateComplete
|
|
485
|
-
const button = element.querySelector('ui-button')!
|
|
486
|
-
button.focus()
|
|
487
|
-
await UiMock.keyPress(element, 'Escape', { key: 'Escape' })
|
|
488
|
-
|
|
489
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched')
|
|
490
|
-
assert.isTrue(closeSpy.calledOnce, 'close event was dispatched')
|
|
491
|
-
assert.isTrue(closingSpy.calledBefore(closeSpy), 'closing event was dispatched before close event')
|
|
492
|
-
})
|
|
493
|
-
|
|
494
|
-
it('dispatches the closing event with correct detail for dismiss action', async () => {
|
|
495
|
-
const element = await buttonFixture()
|
|
496
|
-
const closingSpy = sinon.spy()
|
|
497
|
-
element.addEventListener('closing', closingSpy)
|
|
498
|
-
|
|
499
|
-
const button = element.querySelector('ui-button[value="dismiss"]') as UiButton
|
|
500
|
-
button.click()
|
|
501
|
-
|
|
502
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched')
|
|
503
|
-
const event = closingSpy.args[0][0] as CustomEvent<UiDialogClosingReason>
|
|
504
|
-
assert.isTrue(event.detail.cancelled, 'cancelled flag is true for dismiss action')
|
|
505
|
-
assert.isUndefined(event.detail.value, 'value is undefined when no dialogValue is set')
|
|
506
|
-
})
|
|
507
|
-
|
|
508
|
-
it('dispatches the closing event with correct detail for confirm action', async () => {
|
|
509
|
-
const element = await buttonFixture()
|
|
510
|
-
const closingSpy = sinon.spy()
|
|
511
|
-
element.addEventListener('closing', closingSpy)
|
|
512
|
-
|
|
513
|
-
const button = element.querySelector('ui-button[value="confirm"]') as UiButton
|
|
514
|
-
button.click()
|
|
515
|
-
|
|
516
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched')
|
|
517
|
-
const event = closingSpy.args[0][0] as CustomEvent<UiDialogClosingReason>
|
|
518
|
-
assert.isFalse(event.detail.cancelled, 'cancelled flag is false for confirm action')
|
|
519
|
-
assert.isUndefined(event.detail.value, 'value is undefined when no dialogValue is set')
|
|
520
|
-
})
|
|
521
|
-
|
|
522
|
-
it('includes dialogValue in closing event detail', async () => {
|
|
523
|
-
const element = await buttonFixture()
|
|
524
|
-
element.dialogValue = 'test-value'
|
|
525
|
-
const closingSpy = sinon.spy()
|
|
526
|
-
element.addEventListener('closing', closingSpy)
|
|
527
|
-
|
|
528
|
-
const button = element.querySelector('ui-button[value="confirm"]') as UiButton
|
|
529
|
-
button.click()
|
|
530
|
-
|
|
531
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched')
|
|
532
|
-
const event = closingSpy.args[0][0] as CustomEvent<UiDialogClosingReason>
|
|
533
|
-
assert.equal(event.detail.value, 'test-value', 'dialogValue is included in event detail')
|
|
534
|
-
})
|
|
535
|
-
|
|
536
|
-
it('prevents dialog closing when closing event is cancelled', async () => {
|
|
537
|
-
const element = await buttonFixture()
|
|
538
|
-
const closingSpy = sinon.spy()
|
|
539
|
-
const closeSpy = sinon.spy()
|
|
540
|
-
|
|
541
|
-
element.addEventListener('closing', (event) => {
|
|
542
|
-
closingSpy()
|
|
543
|
-
event.preventDefault() // Cancel the closing
|
|
544
|
-
})
|
|
545
|
-
element.addEventListener('close', closeSpy)
|
|
546
|
-
|
|
547
|
-
element.open = true
|
|
548
|
-
await element.updateComplete
|
|
549
|
-
assert.isTrue(element.open, 'dialog is initially open')
|
|
550
|
-
|
|
551
|
-
const button = element.querySelector('ui-button[value="dismiss"]') as UiButton
|
|
552
|
-
button.click()
|
|
553
|
-
|
|
554
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched')
|
|
555
|
-
assert.isFalse(closeSpy.called, 'close event was not dispatched')
|
|
556
|
-
assert.isTrue(element.open, 'dialog remains open when closing is prevented')
|
|
557
|
-
})
|
|
558
|
-
|
|
559
|
-
it('prevents dialog closing when confirming and closing event is cancelled', async () => {
|
|
560
|
-
const element = await buttonFixture()
|
|
561
|
-
const closingSpy = sinon.spy()
|
|
562
|
-
const closeSpy = sinon.spy()
|
|
563
|
-
|
|
564
|
-
element.addEventListener('closing', (event) => {
|
|
565
|
-
closingSpy()
|
|
566
|
-
event.preventDefault() // Cancel the closing
|
|
567
|
-
})
|
|
568
|
-
element.addEventListener('close', closeSpy)
|
|
569
|
-
|
|
570
|
-
element.open = true
|
|
571
|
-
await element.updateComplete
|
|
572
|
-
assert.isTrue(element.open, 'dialog is initially open')
|
|
573
|
-
|
|
574
|
-
const button = element.querySelector('ui-button[value="confirm"]') as UiButton
|
|
575
|
-
button.click()
|
|
576
|
-
|
|
577
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched')
|
|
578
|
-
assert.isFalse(closeSpy.called, 'close event was not dispatched')
|
|
579
|
-
assert.isTrue(element.open, 'dialog remains open when closing is prevented')
|
|
580
|
-
})
|
|
581
|
-
|
|
582
|
-
it('prevents dialog closing when pressing Escape and closing event is cancelled', async () => {
|
|
583
|
-
const element = await buttonFixture()
|
|
584
|
-
const closingSpy = sinon.spy()
|
|
585
|
-
const closeSpy = sinon.spy()
|
|
586
|
-
|
|
587
|
-
element.addEventListener('closing', (event) => {
|
|
588
|
-
closingSpy()
|
|
589
|
-
event.preventDefault() // Cancel the closing
|
|
590
|
-
})
|
|
591
|
-
element.addEventListener('close', closeSpy)
|
|
592
|
-
|
|
593
|
-
element.open = true
|
|
594
|
-
await element.updateComplete
|
|
595
|
-
assert.isTrue(element.open, 'dialog is initially open')
|
|
596
|
-
|
|
597
|
-
const button = element.querySelector('ui-button')!
|
|
598
|
-
button.focus()
|
|
599
|
-
await UiMock.keyPress(element, 'Escape', { key: 'Escape' })
|
|
600
|
-
|
|
601
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched')
|
|
602
|
-
assert.isFalse(closeSpy.called, 'close event was not dispatched')
|
|
603
|
-
assert.isTrue(element.open, 'dialog remains open when closing is prevented')
|
|
604
|
-
})
|
|
605
|
-
|
|
606
|
-
it('prevents native dialog close and reopens when closing event is cancelled', async () => {
|
|
607
|
-
const element = await modalFixture()
|
|
608
|
-
const closingSpy = sinon.spy()
|
|
609
|
-
const showModalSpy = sinon.spy(element.dialog, 'showModal')
|
|
610
|
-
|
|
611
|
-
element.addEventListener('closing', (event) => {
|
|
612
|
-
closingSpy()
|
|
613
|
-
event.preventDefault() // Cancel the closing
|
|
614
|
-
})
|
|
615
|
-
|
|
616
|
-
element.open = true
|
|
617
|
-
await element.updateComplete
|
|
618
|
-
assert.isTrue(element.open, 'dialog is initially open')
|
|
619
|
-
assert.isTrue(element.dialog.open, 'native dialog is open')
|
|
620
|
-
|
|
621
|
-
// Reset the spy count after initial open
|
|
622
|
-
showModalSpy.resetHistory()
|
|
623
|
-
|
|
624
|
-
// Simulate native dialog close event (e.g., clicking backdrop)
|
|
625
|
-
element.dialog.dispatchEvent(new Event('close'))
|
|
626
|
-
|
|
627
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched')
|
|
628
|
-
assert.isTrue(element.open, 'dialog remains open when closing is prevented')
|
|
629
|
-
assert.isTrue(showModalSpy.calledOnce, 'showModal was called to reopen the dialog')
|
|
630
|
-
})
|
|
631
|
-
|
|
632
|
-
it('verifies closing event properties', async () => {
|
|
633
|
-
const element = await buttonFixture()
|
|
634
|
-
let closingEvent: CustomEvent<UiDialogClosingReason>
|
|
635
|
-
|
|
636
|
-
element.addEventListener('closing', (event) => {
|
|
637
|
-
closingEvent = event as CustomEvent<UiDialogClosingReason>
|
|
638
|
-
})
|
|
639
|
-
|
|
640
|
-
const button = element.querySelector('ui-button[value="dismiss"]') as UiButton
|
|
641
|
-
button.click()
|
|
642
|
-
|
|
643
|
-
assert.isDefined(closingEvent!, 'closing event was dispatched')
|
|
644
|
-
assert.isTrue(closingEvent!.cancelable, 'closing event is cancelable')
|
|
645
|
-
assert.isFalse(closingEvent!.bubbles, 'closing event does not bubble')
|
|
646
|
-
assert.isFalse(closingEvent!.composed, 'closing event is not composed')
|
|
647
|
-
assert.equal(closingEvent!.type, 'closing', 'event type is "closing"')
|
|
648
|
-
})
|
|
649
|
-
|
|
650
|
-
it('works with imperative dismiss and confirm buttons', async () => {
|
|
651
|
-
const element = await basicFixture()
|
|
652
|
-
element.dismissLabel = 'Cancel'
|
|
653
|
-
element.confirmLabel = 'OK'
|
|
654
|
-
await element.updateComplete
|
|
655
|
-
|
|
656
|
-
const closingSpy = sinon.spy()
|
|
657
|
-
const closeSpy = sinon.spy()
|
|
658
|
-
element.addEventListener('closing', closingSpy)
|
|
659
|
-
element.addEventListener('close', closeSpy)
|
|
660
|
-
|
|
661
|
-
// Test dismiss button
|
|
662
|
-
const dismissButton = element.shadowRoot!.querySelector('.internal-button[value="dismiss"]') as UiButton
|
|
663
|
-
dismissButton.click()
|
|
664
|
-
|
|
665
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched for dismiss')
|
|
666
|
-
assert.isTrue(closeSpy.calledOnce, 'close event was dispatched for dismiss')
|
|
667
|
-
|
|
668
|
-
// Reset spies and test confirm button
|
|
669
|
-
closingSpy.resetHistory()
|
|
670
|
-
closeSpy.resetHistory()
|
|
671
|
-
element.open = true
|
|
672
|
-
await element.updateComplete
|
|
673
|
-
|
|
674
|
-
const confirmButton = element.shadowRoot!.querySelector('.internal-button[value="confirm"]') as UiButton
|
|
675
|
-
confirmButton.click()
|
|
676
|
-
|
|
677
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched for confirm')
|
|
678
|
-
assert.isTrue(closeSpy.calledOnce, 'close event was dispatched for confirm')
|
|
679
|
-
})
|
|
680
|
-
|
|
681
|
-
it('can prevent closing with imperative buttons', async () => {
|
|
682
|
-
const element = await basicFixture()
|
|
683
|
-
element.dismissLabel = 'Cancel'
|
|
684
|
-
await element.updateComplete
|
|
685
|
-
|
|
686
|
-
const closingSpy = sinon.spy()
|
|
687
|
-
const closeSpy = sinon.spy()
|
|
688
|
-
|
|
689
|
-
element.addEventListener('closing', (event) => {
|
|
690
|
-
closingSpy()
|
|
691
|
-
event.preventDefault()
|
|
692
|
-
})
|
|
693
|
-
element.addEventListener('close', closeSpy)
|
|
694
|
-
|
|
695
|
-
element.open = true
|
|
696
|
-
await element.updateComplete
|
|
697
|
-
|
|
698
|
-
const dismissButton = element.shadowRoot!.querySelector('.internal-button[value="dismiss"]') as UiButton
|
|
699
|
-
dismissButton.click()
|
|
700
|
-
|
|
701
|
-
assert.isTrue(closingSpy.calledOnce, 'closing event was dispatched')
|
|
702
|
-
assert.isFalse(closeSpy.called, 'close event was not dispatched')
|
|
703
|
-
assert.isTrue(element.open, 'dialog remains open')
|
|
704
|
-
})
|
|
705
|
-
})
|
|
706
|
-
|
|
707
|
-
describe('accessibility', () => {
|
|
708
|
-
it('meets accessibility standards in closed state', async () => {
|
|
709
|
-
const element = await basicFixture()
|
|
710
|
-
await assert.isAccessible(element)
|
|
711
|
-
})
|
|
712
|
-
|
|
713
|
-
it('meets accessibility standards when open', async () => {
|
|
714
|
-
const element = await basicFixture()
|
|
715
|
-
element.open = true
|
|
716
|
-
await element.updateComplete
|
|
717
|
-
await assert.isAccessible(element)
|
|
718
|
-
})
|
|
719
|
-
|
|
720
|
-
it('meets accessibility standards with modal dialog', async () => {
|
|
721
|
-
const element = await modalFixture()
|
|
722
|
-
element.open = true
|
|
723
|
-
await element.updateComplete
|
|
724
|
-
await assert.isAccessible(element)
|
|
725
|
-
})
|
|
726
|
-
|
|
727
|
-
it('meets accessibility standards with full content', async () => {
|
|
728
|
-
const element: UiDialog = await fixture(html`
|
|
729
|
-
<ui-dialog modal open>
|
|
730
|
-
<ui-icon slot="icon" icon="deleteOutline"></ui-icon>
|
|
731
|
-
<span slot="title">Delete confirmation</span>
|
|
732
|
-
<p>Are you sure you want to delete this item?</p>
|
|
733
|
-
<ui-button color="text" slot="button" value="dismiss">Cancel</ui-button>
|
|
734
|
-
<ui-button color="text" slot="button" value="confirm">Delete</ui-button>
|
|
735
|
-
</ui-dialog>
|
|
736
|
-
`)
|
|
737
|
-
await element.updateComplete
|
|
738
|
-
await assert.isAccessible(element)
|
|
739
|
-
})
|
|
740
|
-
|
|
741
|
-
it('maintains accessibility when closing is prevented', async () => {
|
|
742
|
-
const element = await buttonFixture()
|
|
743
|
-
element.addEventListener('closing', (event) => {
|
|
744
|
-
event.preventDefault()
|
|
745
|
-
})
|
|
746
|
-
|
|
747
|
-
element.open = true
|
|
748
|
-
await element.updateComplete
|
|
749
|
-
|
|
750
|
-
const button = element.querySelector('ui-button[value="dismiss"]') as UiButton
|
|
751
|
-
button.click()
|
|
752
|
-
|
|
753
|
-
// Dialog should remain open and accessible
|
|
754
|
-
assert.isTrue(element.open, 'dialog remains open')
|
|
755
|
-
await assert.isAccessible(element)
|
|
756
|
-
})
|
|
757
|
-
})
|
|
758
|
-
})
|
|
759
|
-
})
|