diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /testing/web-platform/tests/html/semantics/popovers/popover-target-action-hover.tentative.html | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/html/semantics/popovers/popover-target-action-hover.tentative.html')
-rw-r--r-- | testing/web-platform/tests/html/semantics/popovers/popover-target-action-hover.tentative.html | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/semantics/popovers/popover-target-action-hover.tentative.html b/testing/web-platform/tests/html/semantics/popovers/popover-target-action-hover.tentative.html new file mode 100644 index 0000000000..b03ec78ebf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/popovers/popover-target-action-hover.tentative.html @@ -0,0 +1,180 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<title>The popovertargetaction=hover behavior</title> +<link rel="author" href="mailto:masonf@chromium.org"> +<link rel=help href="https://open-ui.org/components/popover.research.explainer"> +<meta name="timeout" content="long"> +<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> + +<body> +<style> +.unrelated {top:0;} +.invoker {top:100px; width:fit-content; height:fit-content;} +[popover] {top: 200px;} +.offset-child {top:300px; left:300px;} +</style> + +<script> +const popoverShowDelay = 100; // The CSS delay setting. +const hoverWaitTime = 200; // How long to wait to cover the delay for sure. +async function makePopoverAndInvoker(test, popoverType, invokerType, delayMs) { + delayMs = delayMs || popoverShowDelay; + const popover = Object.assign(document.createElement('div'),{popover: popoverType}); + document.body.appendChild(popover); + popover.textContent = 'Popover'; + // Set popover-show-delay on the popover to 0 - it should be ignored. + popover.setAttribute('style',`popover-show-delay: 0; popover-hide-delay: 1000s;`); + let invoker = document.createElement('button'); + invoker.setAttribute('class','invoker'); + invoker.popoverTargetElement = popover; + invoker.popoverTargetAction = "hover"; + // Set popover-hide-delay on the invoker to 0 - it should be ignored. + invoker.setAttribute('style',`popover-show-delay: ${delayMs}ms; popover-hide-delay: 0;`); + document.body.appendChild(invoker); + const actualHoverDelay = Number(getComputedStyle(invoker)['popoverShowDelay'].slice(0,-1))*1000; + assert_equals(actualHoverDelay,delayMs,'popover-show-delay is incorrect'); + const originalInvoker = invoker; + const reassignPopoverFn = (p) => {originalInvoker.popoverTargetElement = p}; + switch (invokerType) { + case 'plain': + // Invoker is just a button. + invoker.textContent = 'Invoker'; + break; + case 'nested': + // Invoker is just a button containing a div. + const child1 = invoker.appendChild(document.createElement('div')); + child1.textContent = 'Invoker'; + break; + case 'nested-offset': + // Invoker is a child of the invoking button, and is not contained within + // the bounds of the popovertarget element. + invoker.textContent = 'Invoker'; + // Reassign invoker to the child: + invoker = invoker.appendChild(document.createElement('div')); + invoker.textContent = 'Invoker child'; + invoker.setAttribute('class','offset-child'); + break; + case 'none': + // No invoker. + invoker.remove(); + break; + default: + assert_unreached(`Invalid invokerType ${invokerType}`); + } + const unrelated = document.createElement('div'); + document.body.appendChild(unrelated); + unrelated.textContent = 'Unrelated'; + unrelated.setAttribute('class','unrelated'); + test.add_cleanup(async () => { + popover.remove(); + invoker.remove(); + originalInvoker.remove(); + unrelated.remove(); + await waitForRender(); + }); + await mouseOver(unrelated); // Start by mousing over the unrelated element + await waitForRender(); + return {popover,invoker,reassignPopoverFn}; +} + +// NOTE about testing methodology: +// This test checks whether popovers are triggered *after* the appropriate hover +// delay. The delay used for testing is kept low, to avoid this test taking too +// long, but that means that sometimes on a slow bot/client, the hover delay can +// elapse before we are able to check the popover status. And that can make this +// test flaky. To avoid that, the msSinceMouseOver() function is used to check +// that not-too-much time has passed, and if it has, the test is simply skipped. + +["auto","hint","manual"].forEach(type => { + ["plain","nested","nested-offset"].forEach(invokerType => { + promise_test(async (t) => { + const {popover,invoker} = await makePopoverAndInvoker(t,type,invokerType); + assert_false(popover.matches(':popover-open')); + await mouseOver(invoker); + let showing = popover.matches(':popover-open'); + // See NOTE above. + if (msSinceMouseOver() < popoverShowDelay) + assert_false(showing,'popover should not show immediately'); + await waitForHoverTime(hoverWaitTime); + assert_true(msSinceMouseOver() >= hoverWaitTime,'waitForHoverTime should wait the specified time'); + assert_true(popover.matches(':popover-open'),'popover should show after delay'); + assert_true(hoverWaitTime > popoverShowDelay,'popoverShowDelay is the CSS setting, hoverWaitTime should be longer than that'); + popover.hidePopover(); // Cleanup + },`popovertargetaction=hover shows a popover with popover=${type}, invokerType=${invokerType}`); + + promise_test(async (t) => { + const {popover,invoker} = await makePopoverAndInvoker(t,type,invokerType); + assert_false(popover.matches(':popover-open')); + invoker.click(); // Click the invoker + assert_true(popover.matches(':popover-open'),'Clicking the invoker should show the popover, even when popovertargetaction=hover'); + popover.hidePopover(); // Cleanup + },`popovertargetaction=hover should also allow click activation, for popover=${type}, invokerType=${invokerType}`); + + promise_test(async (t) => { + const longerHoverDelay = hoverWaitTime*2; + const {popover,invoker} = await makePopoverAndInvoker(t,type,invokerType,longerHoverDelay); + await mouseOver(invoker); + let showing = popover.matches(':popover-open'); + // See NOTE above. + if (msSinceMouseOver() >= longerHoverDelay) + return; // The WPT runner was too slow. + assert_false(showing,'popover should not show immediately'); + await waitForHoverTime(hoverWaitTime); + showing = popover.matches(':popover-open'); + if (msSinceMouseOver() >= longerHoverDelay) + return; // The WPT runner was too slow. + assert_false(showing,'popover should not show after not long enough of a delay'); + },`popovertargetaction=hover popover-show-delay is respected (popover=${type}, invokerType=${invokerType})`); + + promise_test(async (t) => { + const {popover,invoker} = await makePopoverAndInvoker(t,type,invokerType); + popover.showPopover(); + assert_true(popover.matches(':popover-open')); + await mouseOver(invoker); + assert_true(popover.matches(':popover-open'),'popover should stay showing on mouseover'); + await waitForHoverTime(hoverWaitTime); + assert_true(popover.matches(':popover-open'),'popover should stay showing after delay'); + popover.hidePopover(); // Cleanup + },`popovertargetaction=hover does nothing when popover is already showing (popover=${type}, invokerType=${invokerType})`); + + promise_test(async (t) => { + const {popover,invoker} = await makePopoverAndInvoker(t,type,invokerType); + await mouseOver(invoker); + let showing = popover.matches(':popover-open'); + popover.remove(); + // See NOTE above. + if (msSinceMouseOver() >= popoverShowDelay) + return; // The WPT runner was too slow. + assert_false(showing,'popover should not show immediately'); + await waitForHoverTime(hoverWaitTime); + assert_false(popover.matches(':popover-open'),'popover should not show even after a delay'); + // Now put it back in the document and make sure it doesn't trigger. + document.body.appendChild(popover); + await waitForHoverTime(hoverWaitTime); + assert_false(popover.matches(':popover-open'),'popover should not show even when returned to the document'); + },`popovertargetaction=hover does nothing when popover is moved out of the document (popover=${type}, invokerType=${invokerType})`); + + promise_test(async (t) => { + const {popover,invoker,reassignPopoverFn} = await makePopoverAndInvoker(t,type,invokerType); + const popover2 = Object.assign(document.createElement('div'),{popover: type}); + document.body.appendChild(popover2); + t.add_cleanup(() => popover2.remove()); + await mouseOver(invoker); + let eitherShowing = popover.matches(':popover-open') || popover2.matches(':popover-open'); + reassignPopoverFn(popover2); + // See NOTE above. + if (msSinceMouseOver() >= popoverShowDelay) + return; // The WPT runner was too slow. + assert_false(eitherShowing,'popover should not show immediately'); + await waitForHoverTime(hoverWaitTime); + assert_false(popover.matches(':popover-open'),'popover #1 should not show since popovertarget was reassigned'); + assert_false(popover2.matches(':popover-open'),'popover #2 should not show since popovertarget was reassigned'); + },`popovertargetaction=hover does nothing when target changes (popover=${type}, invokerType=${invokerType})`); + }); +}); +</script> |