diff options
Diffstat (limited to 'testing/web-platform/tests/html/semantics/popovers/popover-top-layer-combinations.html')
-rw-r--r-- | testing/web-platform/tests/html/semantics/popovers/popover-top-layer-combinations.html | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/semantics/popovers/popover-top-layer-combinations.html b/testing/web-platform/tests/html/semantics/popovers/popover-top-layer-combinations.html new file mode 100644 index 0000000000..8db327d7d1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/popovers/popover-top-layer-combinations.html @@ -0,0 +1,149 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Popover combined with dialog/fullscreen behavior</title> +<link rel=author href="mailto:masonf@chromium.org"> +<link rel=help href="https://open-ui.org/components/popover.research.explainer"> +<link rel=help href="https://html.spec.whatwg.org/multipage/popover.html"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="resources/popover-utils.js"></script> + +<button id=visible>Visible button</button> +<div id=examples> + <dialog popover>Popover Dialog</dialog> + <dialog popover open style="top:50px;">Open Non-modal Popover Dialog</dialog> + <div popover class=fullscreen>Fullscreen Popover</div> + <dialog popover class=fullscreen>Fullscreen Popover Dialog</dialog> + <dialog popover open class=fullscreen style="top:200px;">Fullscreen Open Non-modal Popover Dialog</dialog> +</div> + +<style> + [popover] { + inset:auto; + top:0; + left:0; + } + [popover].fullscreen.visible { + display:block; + } +</style> + +<script> +const isDialog = (ex) => ex instanceof HTMLDialogElement; +const isFullscreen = (ex) => ex.classList.contains('fullscreen'); +function ensureIsOpenPopover(ex,message) { + // Because :popover-open will eventually support <dialog>, this does extra work to + // verify we're dealing with an :popover-open Popover. Note that this will also throw + // if this is an element with the `popover` attribute that has been made + // visible via an explicit `display:block` style rule. + message = message || 'Error'; + assert_true(ex.matches(':popover-open'),`${message}: Popover doesn\'t match :popover-open`); + ex.hidePopover(); // Shouldn't throw if this is a showing popover + ex.showPopover(); // Show it again to avoid state change + assert_true(ex.matches(':popover-open'),`${message}: Sanity`); +} +window.onload = () => requestAnimationFrame(() => requestAnimationFrame(() => { + const examples = Array.from(document.querySelectorAll('#examples>*')); + examples.forEach(ex => { + promise_test(async (t) => { + t.add_cleanup(() => ex.remove()); + // Test initial conditions + if (ex.hasAttribute('open')) { + assert_true(isDialog(ex)); + assert_true(isElementVisible(ex),'Open dialog should be visible by default'); + assert_throws_dom("InvalidStateError",() => ex.showPopover(),'Calling showPopover on an already-showing element should throw InvalidStateError'); + ex.removeAttribute('open'); + assert_false(isElementVisible(ex),'Removing the open attribute should hide the dialog'); + } else { + ex.showPopover(); // Should not throw + ensureIsOpenPopover(ex,'showPopover should work'); + ex.hidePopover(); // Should not throw + assert_false(ex.matches(':popover-open'),'hidePopover should work'); + } + assert_false(isElementVisible(ex)); + + // Start with popover, try the other API + ex.showPopover(); + ensureIsOpenPopover(ex); + let tested_something=false; + if (isDialog(ex)) { + tested_something=true; + assert_throws_dom("InvalidStateError",() => ex.showModal(),'Calling showModal() on an already-showing Popover should throw InvalidStateError'); + assert_throws_dom("InvalidStateError",() => ex.show(),'Calling show() on an already-showing Popover should throw InvalidStateError'); + } + if (isFullscreen(ex)) { + tested_something=true; + let requestSucceeded = false; + await blessTopLayer(ex); + await ex.requestFullscreen() + .then(() => {requestSucceeded = true;}) // We should not hit this. + .catch((exception) => { + // This exception is expected. + assert_equals(exception.name,'TypeError',`Invalid exception from requestFullscreen() (${exception.message})`); + }); + assert_false(requestSucceeded,'requestFullscreen() should not succeed when the element is an already-showing Popover'); + } + assert_true(tested_something); + ensureIsOpenPopover(ex); + ex.hidePopover(); + + // Start with the other API, then try popover + if (isDialog(ex)) { + ex.show(); + assert_true(ex.hasAttribute('open')); + assert_throws_dom("InvalidStateError",() => ex.showPopover(),'Calling showPopover() on an already-showing non-modal dialog should throw InvalidStateError'); + ex.close(); + assert_false(ex.hasAttribute('open')); + ex.showModal(); + assert_true(ex.hasAttribute('open')); + assert_throws_dom("InvalidStateError",() => ex.showPopover(),'Calling showPopover() on an already-showing modal dialog should throw InvalidStateError'); + ex.close(); + assert_false(ex.hasAttribute('open')); + } else if (isFullscreen(ex)) { + let requestSucceeded = false; + await blessTopLayer(visible); + await ex.requestFullscreen() + .then(() => { + assert_throws_dom("InvalidStateError",() => ex.showPopover(),'Calling showPopover() on an already-fullscreen element should throw InvalidStateError'); + }); + await document.exitFullscreen() + .then(() => assert_true(true)); + } + + // Finally, try invoking these combined popovers via a declarative invoker + const button = document.createElement('button'); + t.add_cleanup(() => button.remove()); + document.body.appendChild(button); + button.popoverTargetElement = ex; + button.popoverTargetAction = "toggle"; + assert_false(ex.matches(':popover-open')); + await clickOn(button); + ensureIsOpenPopover(ex,'Invoking element should be able to invoke all popovers'); + ex.hidePopover(); + if (isDialog(ex)) { + ex.showModal(); + assert_true(ex.hasAttribute('open')); + } else if (isFullscreen(ex)) { + // Popover fullscreen isn't visible by default, so explicitly add + // display:block, so that calls to "clickOn" can succeed. + ex.classList.add('visible'); + await blessTopLayer(visible); + await ex.requestFullscreen(); + } else { + assert_unreached('Not a dialog or fullscreen'); + } + ex.appendChild(button); // Add button to the element, so it's visible to click + await clickOn(button); + assert_false(ex.matches(':popover-open'),'The invoker click should have failed on the already-open dialog/fullscreen'); + if (isDialog(ex)) { + ex.close(); + } else { + await document.exitFullscreen() + } + }, `Popover combination: ${ex.textContent}`); + }); +})); +</script> |