@operato/popup 10.11.0 → 10.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +206 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov.info +7675 -0
- package/dist/src/implementation.d.ts +13 -0
- package/dist/src/implementation.js +13 -0
- package/dist/src/implementation.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/open-popup.d.ts +37 -13
- package/dist/src/open-popup.js +79 -12
- package/dist/src/open-popup.js.map +1 -1
- package/dist/src/ox-floating-overlay.d.ts +4 -1
- package/dist/src/ox-floating-overlay.js +19 -2
- package/dist/src/ox-floating-overlay.js.map +1 -1
- package/dist/src/ox-popup-actions.d.ts +36 -0
- package/dist/src/ox-popup-actions.js +129 -0
- package/dist/src/ox-popup-actions.js.map +1 -0
- package/dist/src/ox-prompt.d.ts +9 -3
- package/dist/src/ox-prompt.js +50 -42
- package/dist/src/ox-prompt.js.map +1 -1
- package/dist/src/popup-result.d.ts +19 -0
- package/dist/src/popup-result.js +53 -0
- package/dist/src/popup-result.js.map +1 -0
- package/dist/test/office-control-height.test.d.ts +1 -0
- package/dist/test/office-control-height.test.js +48 -0
- package/dist/test/office-control-height.test.js.map +1 -0
- package/dist/test/ox-popup-actions.test.d.ts +3 -0
- package/dist/test/ox-popup-actions.test.js +104 -0
- package/dist/test/ox-popup-actions.test.js.map +1 -0
- package/dist/test/ox-prompt-actions.test.d.ts +1 -0
- package/dist/test/ox-prompt-actions.test.js +77 -0
- package/dist/test/ox-prompt-actions.test.js.map +1 -0
- package/dist/test/popup-result.test.d.ts +1 -0
- package/dist/test/popup-result.test.js +114 -0
- package/dist/test/popup-result.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -5
- package/test/office-control-height.test.ts +58 -0
- package/test/ox-popup-actions.test.ts +130 -0
- package/test/ox-prompt-actions.test.ts +99 -0
- package/test/popup-result.test.ts +150 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { expect } from '@open-wc/testing'
|
|
2
|
+
|
|
3
|
+
import { ACTION_HEIGHT_TOKENS, ButtonContainerStyles, CommonHeaderStyles, CommonPopupStyles } from '@operato/styles'
|
|
4
|
+
|
|
5
|
+
import { OxPopupActions } from '../src/ox-popup-actions.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Office button heights come from one token per use (ADR-0060 decision 6): 32px for action buttons,
|
|
9
|
+
* 26px in a grid cell, the same for mouse and finger (WCAG 2.2 AA, user decision 2026-09-17).
|
|
10
|
+
*
|
|
11
|
+
* The finger branch cannot be emulated in the test browser, so these read the stylesheets: every
|
|
12
|
+
* height is the token with the shared default, and no finger branch brings back a height of its own.
|
|
13
|
+
* Shop-floor popups raise the token themselves (operato-plant checks that on its side).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const text = (styles: unknown) =>
|
|
17
|
+
(Array.isArray(styles) ? styles : [styles]).map(s => String((s as { cssText?: string }).cssText ?? s)).join('\n')
|
|
18
|
+
|
|
19
|
+
const coarse = (css: string) => css.slice(css.indexOf('(pointer: coarse)'))
|
|
20
|
+
|
|
21
|
+
describe('office control height', () => {
|
|
22
|
+
it('the defaults are 32 for action buttons and 26 in a grid cell', () => {
|
|
23
|
+
expect(ACTION_HEIGHT_TOKENS).to.deep.equal({
|
|
24
|
+
'--context-action-height': 32,
|
|
25
|
+
'--popup-action-height': 32,
|
|
26
|
+
'--form-action-height': 32,
|
|
27
|
+
'--cell-action-height': 26
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('ox-popup-actions: the popup token, with no finger height of its own', () => {
|
|
32
|
+
const css = text(OxPopupActions.styles)
|
|
33
|
+
expect(css).to.contain('--_height: var(--popup-action-height, 32px)')
|
|
34
|
+
expect(coarse(css)).to.not.contain('--_height')
|
|
35
|
+
expect(css).to.not.match(/max\(\d+px/)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('CommonPopupStyles .buttons: the popup token for mouse and finger', () => {
|
|
39
|
+
const css = text(CommonPopupStyles)
|
|
40
|
+
expect(css).to.contain('--md-filled-button-container-height: var(--popup-action-height, 32px)')
|
|
41
|
+
expect(coarse(css)).to.contain('min-height: var(--popup-action-height, 32px)')
|
|
42
|
+
expect(css).to.not.match(/max\(\d+px/)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('CommonHeaderStyles .footer: the old popup footer reads the same popup token', () => {
|
|
46
|
+
const css = text(CommonHeaderStyles)
|
|
47
|
+
expect(css).to.contain('min-height: var(--popup-action-height, 32px)')
|
|
48
|
+
expect(css).to.not.contain('min-height: 30px')
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('ButtonContainerStyles: the page action token, and no finger branch', () => {
|
|
52
|
+
const css = text(ButtonContainerStyles)
|
|
53
|
+
expect(css).to.contain('height: var(--context-action-height, 32px)')
|
|
54
|
+
expect(css).to.contain('--md-filled-button-container-height: var(--context-action-height, 32px)')
|
|
55
|
+
expect(css).to.not.contain('--context-action-height-touch')
|
|
56
|
+
expect(css).to.not.contain('(pointer: coarse)')
|
|
57
|
+
})
|
|
58
|
+
})
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import '@material/web/button/filled-button.js'
|
|
2
|
+
import '@material/web/button/text-button.js'
|
|
3
|
+
|
|
4
|
+
import { expect, fixture } from '@open-wc/testing'
|
|
5
|
+
import { html } from 'lit'
|
|
6
|
+
|
|
7
|
+
import '../src/ox-popup-actions.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The action row owns order, height, shape and the destructive colour - so a popup cannot get them
|
|
11
|
+
* wrong by writing its markup differently. These run with a mouse pointer (the test browser); the
|
|
12
|
+
* finger bar is a media query of the same element.
|
|
13
|
+
*
|
|
14
|
+
* The expected numbers are written out (32, 68, 999em) rather than read from the stylesheet, so a
|
|
15
|
+
* change to the stylesheet shows up here as a decision, not as a silent follow.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const left = (el: Element) => el.getBoundingClientRect().left
|
|
19
|
+
const height = (el: Element) => Math.round(el.getBoundingClientRect().height)
|
|
20
|
+
|
|
21
|
+
async function row(template: ReturnType<typeof html>) {
|
|
22
|
+
const host = await fixture<HTMLElement>(html`<div style="width: 600px">${template}</div>`)
|
|
23
|
+
const actions = host.querySelector('ox-popup-actions') as HTMLElement & { updateComplete: Promise<unknown> }
|
|
24
|
+
await actions.updateComplete
|
|
25
|
+
await Promise.all(
|
|
26
|
+
Array.from(actions.querySelectorAll('md-filled-button, md-text-button')).map(
|
|
27
|
+
b => (b as HTMLElement & { updateComplete: Promise<unknown> }).updateComplete
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
return actions
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe('ox-popup-actions', () => {
|
|
34
|
+
it('renders start, cancel, confirm in that order whatever the markup order', async () => {
|
|
35
|
+
const actions = await row(html`
|
|
36
|
+
<ox-popup-actions>
|
|
37
|
+
<md-filled-button slot="confirm" id="confirm">save</md-filled-button>
|
|
38
|
+
<md-text-button slot="cancel" id="cancel">cancel</md-text-button>
|
|
39
|
+
<md-text-button slot="start" id="start">delete</md-text-button>
|
|
40
|
+
</ox-popup-actions>
|
|
41
|
+
`)
|
|
42
|
+
|
|
43
|
+
const start = actions.querySelector('#start')!
|
|
44
|
+
const cancel = actions.querySelector('#cancel')!
|
|
45
|
+
const confirm = actions.querySelector('#confirm')!
|
|
46
|
+
|
|
47
|
+
expect(left(start)).to.be.lessThan(left(cancel))
|
|
48
|
+
expect(left(cancel)).to.be.lessThan(left(confirm))
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('keeps the confirm button at the right edge', async () => {
|
|
52
|
+
const actions = await row(html`
|
|
53
|
+
<ox-popup-actions>
|
|
54
|
+
<md-filled-button slot="confirm" id="confirm">save</md-filled-button>
|
|
55
|
+
<md-text-button slot="cancel">cancel</md-text-button>
|
|
56
|
+
</ox-popup-actions>
|
|
57
|
+
`)
|
|
58
|
+
|
|
59
|
+
const confirm = actions.querySelector('#confirm')!
|
|
60
|
+
expect(Math.round(confirm.getBoundingClientRect().right)).to.equal(Math.round(actions.getBoundingClientRect().right))
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('gives Material buttons and plain buttons the same 32px height', async () => {
|
|
64
|
+
const actions = await row(html`
|
|
65
|
+
<ox-popup-actions>
|
|
66
|
+
<button slot="cancel" id="plain">cancel</button>
|
|
67
|
+
<md-filled-button slot="confirm" id="md">save</md-filled-button>
|
|
68
|
+
</ox-popup-actions>
|
|
69
|
+
`)
|
|
70
|
+
|
|
71
|
+
expect(height(actions.querySelector('#md')!)).to.equal(32)
|
|
72
|
+
expect(height(actions.querySelector('#plain')!)).to.equal(32)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('uses pill shapes inside the popup card', async () => {
|
|
76
|
+
const actions = await row(html`
|
|
77
|
+
<ox-popup-actions>
|
|
78
|
+
<button slot="cancel" id="plain">cancel</button>
|
|
79
|
+
<md-filled-button slot="confirm" id="md">save</md-filled-button>
|
|
80
|
+
</ox-popup-actions>
|
|
81
|
+
`)
|
|
82
|
+
|
|
83
|
+
const md = actions.querySelector('#md')!
|
|
84
|
+
expect(getComputedStyle(md).getPropertyValue('--md-filled-button-container-shape').trim()).to.equal('999em')
|
|
85
|
+
expect(getComputedStyle(actions.querySelector('#plain')!).borderTopLeftRadius).to.not.equal('0px')
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('lets a screen raise the height through --popup-action-height', async () => {
|
|
89
|
+
const actions = await row(html`
|
|
90
|
+
<ox-popup-actions style="--popup-action-height: 68px">
|
|
91
|
+
<button slot="cancel" id="plain">cancel</button>
|
|
92
|
+
<md-filled-button slot="confirm" id="md">save</md-filled-button>
|
|
93
|
+
</ox-popup-actions>
|
|
94
|
+
`)
|
|
95
|
+
|
|
96
|
+
expect(height(actions.querySelector('#md')!)).to.equal(68)
|
|
97
|
+
expect(height(actions.querySelector('#plain')!)).to.equal(68)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it('paints a destructive action with the error colour', async () => {
|
|
101
|
+
const actions = await row(html`
|
|
102
|
+
<ox-popup-actions style="--md-sys-color-error: rgb(190, 12, 20)">
|
|
103
|
+
<md-text-button slot="start" destructive id="side">delete</md-text-button>
|
|
104
|
+
<md-filled-button slot="confirm" destructive id="main">delete all</md-filled-button>
|
|
105
|
+
<button slot="cancel" id="plain" destructive>cancel</button>
|
|
106
|
+
</ox-popup-actions>
|
|
107
|
+
`)
|
|
108
|
+
|
|
109
|
+
const side = getComputedStyle(actions.querySelector('#side')!)
|
|
110
|
+
const main = getComputedStyle(actions.querySelector('#main')!)
|
|
111
|
+
|
|
112
|
+
expect(side.getPropertyValue('--md-text-button-label-text-color').trim()).to.equal('rgb(190, 12, 20)')
|
|
113
|
+
expect(main.getPropertyValue('--md-filled-button-container-color').trim()).to.equal('rgb(190, 12, 20)')
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('never paints cancel as destructive', async () => {
|
|
117
|
+
const actions = await row(html`
|
|
118
|
+
<ox-popup-actions style="--md-sys-color-error: rgb(190, 12, 20)">
|
|
119
|
+
<md-text-button slot="cancel" destructive id="cancel">cancel</md-text-button>
|
|
120
|
+
<button slot="cancel" destructive id="plain">cancel</button>
|
|
121
|
+
<md-filled-button slot="confirm">save</md-filled-button>
|
|
122
|
+
</ox-popup-actions>
|
|
123
|
+
`)
|
|
124
|
+
|
|
125
|
+
expect(getComputedStyle(actions.querySelector('#cancel')!).getPropertyValue('--md-text-button-label-text-color').trim()).to.not.equal(
|
|
126
|
+
'rgb(190, 12, 20)'
|
|
127
|
+
)
|
|
128
|
+
expect(getComputedStyle(actions.querySelector('#plain')!).color).to.not.equal('rgb(190, 12, 20)')
|
|
129
|
+
})
|
|
130
|
+
})
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { expect } from '@open-wc/testing'
|
|
2
|
+
|
|
3
|
+
import { OxPrompt } from '../src/ox-prompt.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* OxPrompt is the first real consumer of the shared action row. Before, its buttons were centred,
|
|
7
|
+
* confirm stood left of cancel, and both had the theme's 5px corner inside a floating card - a row of
|
|
8
|
+
* its own, unlike every popup that opened it.
|
|
9
|
+
*
|
|
10
|
+
* Checked here: the row is the shared one, confirm is on the right, heights match, a destructive
|
|
11
|
+
* confirmation is painted and focuses cancel, and the promise still answers true / false.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const settle = () => new Promise(resolve => setTimeout(resolve, 50))
|
|
15
|
+
|
|
16
|
+
const TIMEOUT = 'TIMEOUT'
|
|
17
|
+
function within<T>(promise: Promise<T>, ms = 1500): Promise<T | typeof TIMEOUT> {
|
|
18
|
+
return Promise.race([promise, new Promise<typeof TIMEOUT>(resolve => setTimeout(() => resolve(TIMEOUT), ms))])
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function openPrompt(destructive = false) {
|
|
22
|
+
const answer = OxPrompt.open({
|
|
23
|
+
title: 'remove?',
|
|
24
|
+
text: 'this cannot be undone',
|
|
25
|
+
confirmButton: { text: 'remove', destructive },
|
|
26
|
+
cancelButton: { text: 'cancel' },
|
|
27
|
+
preventCloseOnBlur: true
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
await settle()
|
|
31
|
+
|
|
32
|
+
const prompts = document.body.querySelectorAll('ox-prompt')
|
|
33
|
+
const prompt = prompts[prompts.length - 1] as OxPrompt
|
|
34
|
+
await prompt.updateComplete
|
|
35
|
+
|
|
36
|
+
const root = prompt.renderRoot as ShadowRoot
|
|
37
|
+
const actions = root.querySelector('ox-popup-actions') as HTMLElement & { updateComplete: Promise<unknown> }
|
|
38
|
+
await actions?.updateComplete
|
|
39
|
+
|
|
40
|
+
const confirm = root.querySelector('#confirm') as HTMLElement & { updateComplete: Promise<unknown> }
|
|
41
|
+
const cancel = root.querySelector('#cancel') as HTMLElement & { updateComplete: Promise<unknown> }
|
|
42
|
+
await Promise.all([confirm?.updateComplete, cancel?.updateComplete])
|
|
43
|
+
|
|
44
|
+
return { answer, prompt, root, actions, confirm, cancel }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
describe('OxPrompt uses the shared action row', () => {
|
|
48
|
+
before(() => {
|
|
49
|
+
/* No theme is loaded in the test page; an undefined var() would make every colour read empty. */
|
|
50
|
+
document.body.style.setProperty('--md-sys-color-error', 'rgb(190, 12, 20)')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
afterEach(() => {
|
|
54
|
+
/* A failed assertion before the click leaves its prompt open; do not let it leak into the next test. */
|
|
55
|
+
document.body.querySelectorAll('ox-prompt').forEach(p => (p as OxPrompt).close())
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('renders its buttons in ox-popup-actions, confirm right of cancel, same height', async () => {
|
|
59
|
+
const { answer, actions, confirm, cancel } = await openPrompt()
|
|
60
|
+
|
|
61
|
+
expect(actions, 'ox-popup-actions').to.exist
|
|
62
|
+
expect(confirm.getAttribute('slot')).to.equal('confirm')
|
|
63
|
+
expect(cancel.getAttribute('slot')).to.equal('cancel')
|
|
64
|
+
expect(cancel.getBoundingClientRect().left).to.be.lessThan(confirm.getBoundingClientRect().left)
|
|
65
|
+
expect(Math.round(confirm.getBoundingClientRect().height)).to.equal(32)
|
|
66
|
+
expect(Math.round(cancel.getBoundingClientRect().height)).to.equal(32)
|
|
67
|
+
|
|
68
|
+
cancel.click()
|
|
69
|
+
expect(await within(answer)).to.equal(false)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('answers true on confirm', async () => {
|
|
73
|
+
const { answer, confirm } = await openPrompt()
|
|
74
|
+
|
|
75
|
+
confirm.click()
|
|
76
|
+
expect(await within(answer)).to.equal(true)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('focuses confirm for an ordinary question', async () => {
|
|
80
|
+
const { answer, root, confirm, cancel } = await openPrompt()
|
|
81
|
+
|
|
82
|
+
/* Compare ids, not elements: a failing element comparison makes chai render the DOM and hang. */
|
|
83
|
+
expect((root.activeElement as HTMLElement | null)?.id).to.equal('confirm')
|
|
84
|
+
|
|
85
|
+
cancel.click()
|
|
86
|
+
await within(answer)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('paints a destructive confirmation and focuses cancel', async () => {
|
|
90
|
+
const { answer, root, confirm, cancel } = await openPrompt(true)
|
|
91
|
+
|
|
92
|
+
expect(confirm.hasAttribute('destructive')).to.equal(true)
|
|
93
|
+
expect(getComputedStyle(confirm).getPropertyValue('--md-filled-button-container-color').trim()).to.equal('rgb(190, 12, 20)')
|
|
94
|
+
expect((root.activeElement as HTMLElement | null)?.id).to.equal('cancel')
|
|
95
|
+
|
|
96
|
+
cancel.click()
|
|
97
|
+
expect(await within(answer)).to.equal(false)
|
|
98
|
+
})
|
|
99
|
+
})
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { expect } from '@open-wc/testing'
|
|
2
|
+
import { html } from 'lit'
|
|
3
|
+
|
|
4
|
+
import { closePopup, openPopup } from '../src/open-popup.js'
|
|
5
|
+
import { OxFloatingOverlay } from '../src/ox-floating-overlay.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The popup result settles exactly once, with the right value, whichever way the popup closes -
|
|
9
|
+
* for the default implementation (no @operato/layout loaded).
|
|
10
|
+
*
|
|
11
|
+
* The implementation's one promise is "call onclosed once when the popup is gone". Before this test
|
|
12
|
+
* the default implementation kept it only for handle.close(): ESC, the backdrop and X removed the
|
|
13
|
+
* overlay without telling the handle, so an awaited result would have hung forever.
|
|
14
|
+
*
|
|
15
|
+
* The same table runs for the layout implementation in @operato/layout/test. A new implementation
|
|
16
|
+
* adds its own row there.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const TIMEOUT = 'TIMEOUT'
|
|
20
|
+
|
|
21
|
+
/** Never await a result bare - a broken implementation must fail the test, not hang the runner. */
|
|
22
|
+
function within<T>(promise: Promise<T>, ms = 2000): Promise<T | typeof TIMEOUT> {
|
|
23
|
+
return Promise.race([promise, new Promise<typeof TIMEOUT>(resolve => setTimeout(() => resolve(TIMEOUT), ms))])
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function overlayOf(handle: { name: string }): OxFloatingOverlay {
|
|
27
|
+
return document.getElementById(handle.name) as OxFloatingOverlay
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function open(options = {}) {
|
|
31
|
+
const handle = openPopup<string>(html`<div class="content">content</div>`, { backdrop: true, ...options })
|
|
32
|
+
let onclosedCalls = 0
|
|
33
|
+
handle.onclosed = () => onclosedCalls++
|
|
34
|
+
|
|
35
|
+
const overlay = overlayOf(handle)
|
|
36
|
+
await overlay.updateComplete
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
handle,
|
|
40
|
+
overlay,
|
|
41
|
+
content: overlay.querySelector('.content') as HTMLElement,
|
|
42
|
+
onclosedCalls: () => onclosedCalls
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Lets any late second settle or second onclosed show up before counting. */
|
|
47
|
+
const settleTurn = () => new Promise(resolve => setTimeout(resolve, 50))
|
|
48
|
+
|
|
49
|
+
describe('openPopup result - default implementation', () => {
|
|
50
|
+
it('handle.close(value) settles with that value', async () => {
|
|
51
|
+
const { handle, onclosedCalls } = await open()
|
|
52
|
+
|
|
53
|
+
handle.close('saved')
|
|
54
|
+
|
|
55
|
+
expect(await within(handle.result)).to.equal('saved')
|
|
56
|
+
await settleTurn()
|
|
57
|
+
expect(handle.closed).to.equal(true)
|
|
58
|
+
expect(onclosedCalls()).to.equal(1)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('closePopup(element, value) from the content settles with that value', async () => {
|
|
62
|
+
const { handle, content, onclosedCalls } = await open()
|
|
63
|
+
|
|
64
|
+
closePopup(content, 'picked')
|
|
65
|
+
|
|
66
|
+
expect(await within(handle.result)).to.equal('picked')
|
|
67
|
+
await settleTurn()
|
|
68
|
+
expect(handle.closed).to.equal(true)
|
|
69
|
+
expect(onclosedCalls()).to.equal(1)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('closePopup(element) without a value settles undefined', async () => {
|
|
73
|
+
const { handle, content } = await open()
|
|
74
|
+
|
|
75
|
+
closePopup(content)
|
|
76
|
+
|
|
77
|
+
expect(await within(handle.result)).to.equal(undefined)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('ESC settles undefined and reports closed', async () => {
|
|
81
|
+
const { handle, onclosedCalls } = await open({ escapable: true })
|
|
82
|
+
|
|
83
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
|
|
84
|
+
|
|
85
|
+
expect(await within(handle.result)).to.equal(undefined)
|
|
86
|
+
await settleTurn()
|
|
87
|
+
expect(handle.closed).to.equal(true)
|
|
88
|
+
expect(onclosedCalls()).to.equal(1)
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('backdrop click settles undefined and reports closed', async () => {
|
|
92
|
+
const { handle, overlay, onclosedCalls } = await open()
|
|
93
|
+
|
|
94
|
+
const backdrop = overlay.renderRoot.querySelector('#backdrop') as HTMLElement
|
|
95
|
+
expect(backdrop, 'backdrop element').to.exist
|
|
96
|
+
backdrop.click()
|
|
97
|
+
|
|
98
|
+
expect(await within(handle.result)).to.equal(undefined)
|
|
99
|
+
await settleTurn()
|
|
100
|
+
expect(handle.closed).to.equal(true)
|
|
101
|
+
expect(onclosedCalls()).to.equal(1)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('the X button settles undefined and reports closed', async () => {
|
|
105
|
+
const { handle, overlay, onclosedCalls } = await open({ closable: true, title: 'x' })
|
|
106
|
+
|
|
107
|
+
const closer = overlay.renderRoot.querySelector('[closable][close]') as HTMLElement
|
|
108
|
+
expect(closer, 'close button').to.exist
|
|
109
|
+
closer.click()
|
|
110
|
+
|
|
111
|
+
expect(await within(handle.result)).to.equal(undefined)
|
|
112
|
+
await settleTurn()
|
|
113
|
+
expect(handle.closed).to.equal(true)
|
|
114
|
+
expect(onclosedCalls()).to.equal(1)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it('the first close request wins: closePopup then handle.close', async () => {
|
|
118
|
+
const { handle, content, onclosedCalls } = await open()
|
|
119
|
+
|
|
120
|
+
closePopup(content, 'first')
|
|
121
|
+
handle.close('second')
|
|
122
|
+
|
|
123
|
+
expect(await within(handle.result)).to.equal('first')
|
|
124
|
+
await settleTurn()
|
|
125
|
+
expect(onclosedCalls()).to.equal(1)
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('the first close request wins: handle.close twice', async () => {
|
|
129
|
+
const { handle, onclosedCalls } = await open()
|
|
130
|
+
|
|
131
|
+
handle.close('first')
|
|
132
|
+
handle.close('second')
|
|
133
|
+
|
|
134
|
+
expect(await within(handle.result)).to.equal('first')
|
|
135
|
+
await settleTurn()
|
|
136
|
+
expect(onclosedCalls()).to.equal(1)
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
it('an onclosed assigned before the change is still called once', async () => {
|
|
140
|
+
const handle = openPopup(html`<div>legacy</div>`)
|
|
141
|
+
let calls = 0
|
|
142
|
+
handle.onclosed = () => calls++
|
|
143
|
+
|
|
144
|
+
handle.close()
|
|
145
|
+
|
|
146
|
+
await within(handle.result)
|
|
147
|
+
await settleTurn()
|
|
148
|
+
expect(calls).to.equal(1)
|
|
149
|
+
})
|
|
150
|
+
})
|