summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html')
-rw-r--r--testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html202
1 files changed, 202 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html b/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html
new file mode 100644
index 0000000000..62aa135b56
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html
@@ -0,0 +1,202 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<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/popover-utils.js"></script>
+
+<script>
+ function ensureShadowDom(host) {
+ host.querySelectorAll('my-element').forEach(host => {
+ if (host.shadowRoot)
+ return; // Declarative Shadow DOM is enabled
+ const template = host.firstElementChild;
+ assert_true(template instanceof HTMLTemplateElement);
+ const shadow = host.attachShadow({mode: 'open'});
+ shadow.appendChild(template.content);
+ template.remove();
+ })
+ }
+ function findPopovers(root) {
+ let popovers = [];
+ if (!root)
+ return popovers;
+ if (root instanceof Element && root.matches('[popover]'))
+ popovers.push(root);
+ popovers.push(...findPopovers(root.shadowRoot));
+ root.childNodes.forEach(child => {
+ popovers.push(...findPopovers(child));
+ })
+ return popovers;
+ }
+ function getPopoverReferences(testId) {
+ const testRoot = document.querySelector(`#${testId}`);
+ assert_true(!!testRoot);
+ ensureShadowDom(testRoot);
+ return findPopovers(testRoot);
+ }
+ function showTestPopover(testId,popoverNum) {
+ getPopoverReferences(testId)[popoverNum].showPopover();
+ }
+</script>
+
+<div id=test1>
+ <button onclick='showTestPopover("test1",0)'>Test1 Popover</button>
+ <my-element>
+ <template shadowrootmode=open>
+ <div popover>
+ <p>This should show, even though it is inside shadow DOM.</p>
+ </div>
+ </template>
+ </my-element>
+</div>
+
+<script>
+ test(function() {
+ const popover = getPopoverReferences('test1')[0];
+ popover.showPopover();
+ assert_true(popover.matches(':popover-open'));
+ assert_true(isElementVisible(popover));
+ popover.hidePopover(); // Cleanup
+ }, "Popovers located inside shadow DOM can still be shown");
+</script>
+
+
+<div id=test2>
+ <button id=t2b1 onclick='showTestPopover("test2",0)'>Test 2 Popover 1</button>
+ <div popover anchor=t2b1 style="top: 200px;">
+ <p>Popover 1</p>
+ <button id=t2b2 onclick='showTestPopover("test2",1)'>Test 2 Popover 2</button>
+ </div>
+ <my-element>
+ <template shadowrootmode=open>
+ <div popover anchor=t2b2 style="top: 400px;">
+ <p>Hiding this popover will hide *all* open popovers,</p>
+ <p>because t2b2 doesn't exist in this context.</p>
+ </div>
+ </template>
+ </my-element>
+</div>
+
+<script>
+ test(function() {
+ const [popover1,popover2] = getPopoverReferences('test2');
+ popover1.showPopover();
+ assert_true(popover1.matches(':popover-open'));
+ assert_true(isElementVisible(popover1));
+ popover2.showPopover();
+ assert_false(popover1.matches(':popover-open'), 'popover1 open'); // P1 was closed by P2
+ assert_false(isElementVisible(popover1), 'popover1 visible');
+ assert_true(popover2.matches(':popover-open'), 'popover2 open'); // P2 is open
+ assert_true(isElementVisible(popover2), 'popover2 visible');
+ popover2.hidePopover(); // Cleanup
+ }, "anchor references do not cross shadow boundaries");
+</script>
+
+
+<div id=test3>
+ <my-element>
+ <template shadowrootmode=open>
+ <button id=t3b1 onclick='showTestPopover("test3",0)'>Test 3 Popover 1</button>
+ <div popover anchor=t3b1>
+ <p>This popover will stay open when popover2 shows.</p>
+ <slot></slot>
+ </div>
+ </template>
+ <button id=t3b2 onclick='showTestPopover("test3",1)'>Test 3 Popover 2</button>
+ </my-element>
+ <div popover anchor=t3b2>Popover 2</div>
+</div>
+
+<script>
+ promise_test(async function() {
+ const [popover1,popover2] = getPopoverReferences('test3');
+ popover1.showPopover();
+ assert_true(popover1.matches(':popover-open'));
+ assert_true(isElementVisible(popover1));
+ // Showing popover2 should not close popover1, since it is a flat
+ // tree ancestor of popover2's anchor button.
+ popover2.showPopover();
+ assert_true(popover2.matches(':popover-open'));
+ assert_true(isElementVisible(popover2));
+ assert_true(popover1.matches(':popover-open'));
+ assert_true(isElementVisible(popover1));
+ popover1.hidePopover();
+ await waitForRender();
+ assert_false(popover1.matches(':popover-open'));
+ assert_false(isElementVisible(popover1));
+ assert_false(popover2.matches(':popover-open'));
+ assert_false(isElementVisible(popover2));
+ }, "anchor references use the flat tree not the DOM tree");
+</script>
+
+
+<div id=test4>
+ <button id=t4b1 onclick='showTestPopover("test4",0)'>Test 4 Popover 1</button>
+ <div popover anchor=t4b1>
+ <p>This should not get hidden when popover2 opens.</p>
+ <my-element>
+ <template shadowrootmode=open>
+ <button id=t4b2 onclick='showTestPopover("test4",1)'>Test 4 Popover 2</button>
+ <div popover anchor=t4b2>
+ <p>This should not hide popover1.</p>
+ </div>
+ </template>
+ </my-element>
+ </div>
+</div>
+
+<script>
+ promise_test(async function() {
+ const [popover1,popover2] = getPopoverReferences('test4');
+ popover1.showPopover();
+ popover2.showPopover();
+ // Both 1 and 2 should be open at this point.
+ assert_true(popover1.matches(':popover-open'), 'popover1 not open');
+ assert_true(isElementVisible(popover1));
+ assert_true(popover2.matches(':popover-open'), 'popover2 not open');
+ assert_true(isElementVisible(popover2));
+ // This should hide both of them.
+ popover1.hidePopover();
+ await waitForRender();
+ assert_false(popover1.matches(':popover-open'));
+ assert_false(isElementVisible(popover1));
+ assert_false(popover2.matches(':popover-open'));
+ assert_false(isElementVisible(popover2));
+ }, "The popover stack is preserved across shadow-inclusive ancestors");
+</script>
+
+
+<div id=test5>
+ <template shadowrootmode=open>
+ <button popovertarget=p1>Test 5 Popover 1</button>
+ <div popover id=p1>Popover 1
+ <p>This should not get hidden when popover2 opens.</p>
+ <button popovertarget=p2>Click</button>
+ </div>
+ <div popover id=p2>Popover 2
+ <p>This should not hide popover1.</p>
+ </div>
+ </template>
+</div>
+<script>
+ promise_test(async function() {
+ const [popover1,popover2] = getPopoverReferences('test5');
+ popover1.showPopover();
+ popover1.querySelector('button').click(); // Use invoker to keep 2 visible
+ // Both 1 and 2 should be open at this point.
+ assert_true(popover1.matches(':popover-open'), 'popover1 not open');
+ assert_true(isElementVisible(popover1));
+ assert_true(popover2.matches(':popover-open'), 'popover2 not open');
+ assert_true(isElementVisible(popover2));
+ // This should hide both of them.
+ popover1.hidePopover();
+ await waitForRender();
+ assert_false(popover1.matches(':popover-open'));
+ assert_false(isElementVisible(popover1));
+ assert_false(popover2.matches(':popover-open'));
+ assert_false(isElementVisible(popover2));
+ }, "Popover ancestor relationships are within a root, not within the document");
+</script>