popover-shadow-dom.html (3945B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <link rel="author" href="mailto:masonf@chromium.org"> 4 <link rel=help href="https://open-ui.org/components/popover.research.explainer"> 5 <link rel=help href="https://html.spec.whatwg.org/multipage/popover.html"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="resources/popover-utils.js"></script> 9 10 <script> 11 function findPopovers(root) { 12 let popovers = []; 13 if (!root) 14 return popovers; 15 if (root instanceof Element && root.matches('[popover]')) 16 popovers.push(root); 17 popovers.push(...findPopovers(root.shadowRoot)); 18 root.childNodes.forEach(child => { 19 popovers.push(...findPopovers(child)); 20 }) 21 return popovers; 22 } 23 function getPopoverReferences(testId) { 24 const testRoot = document.querySelector(`#${testId}`); 25 assert_true(!!testRoot); 26 return findPopovers(testRoot); 27 } 28 </script> 29 30 <div id=test1> 31 <button>Test1 Popover</button> 32 <my-element> 33 <template shadowrootmode=open> 34 <div popover> 35 <p>This should show, even though it is inside shadow DOM.</p> 36 </div> 37 </template> 38 </my-element> 39 </div> 40 41 <script> 42 test(function() { 43 const popover = getPopoverReferences('test1')[0]; 44 popover.showPopover(); 45 assert_true(popover.matches(':popover-open')); 46 assert_true(isElementVisible(popover)); 47 popover.hidePopover(); // Cleanup 48 }, "Popovers located inside shadow DOM can still be shown"); 49 </script> 50 51 52 <div id=test4> 53 <button>Test 4 Popover 1</button> 54 <div popover> 55 <p>This should not get hidden when popover2 opens.</p> 56 <my-element> 57 <template shadowrootmode=open> 58 <button id=t4b2>Test 4 Popover 2</button> 59 <div popover> 60 <p>This should not hide popover1.</p> 61 </div> 62 </template> 63 </my-element> 64 </div> 65 </div> 66 67 <script> 68 promise_test(async function() { 69 const [popover1,popover2] = getPopoverReferences('test4'); 70 popover1.showPopover(); 71 popover2.showPopover(); 72 // Both 1 and 2 should be open at this point. 73 assert_true(popover1.matches(':popover-open'), 'popover1 not open'); 74 assert_true(isElementVisible(popover1)); 75 assert_true(popover2.matches(':popover-open'), 'popover2 not open'); 76 assert_true(isElementVisible(popover2)); 77 // This should hide both of them. 78 popover1.hidePopover(); 79 await waitForRender(); 80 assert_false(popover1.matches(':popover-open')); 81 assert_false(isElementVisible(popover1)); 82 assert_false(popover2.matches(':popover-open')); 83 assert_false(isElementVisible(popover2)); 84 }, "The popover stack is preserved across shadow-inclusive ancestors"); 85 </script> 86 87 88 <div id=test5> 89 <template shadowrootmode=open> 90 <button popovertarget=p1>Test 5 Popover 1</button> 91 <div popover id=p1>Popover 1 92 <p>This should not get hidden when popover2 opens.</p> 93 <button popovertarget=p2>Click</button> 94 </div> 95 <div popover id=p2>Popover 2 96 <p>This should not hide popover1.</p> 97 </div> 98 </template> 99 </div> 100 <script> 101 promise_test(async function() { 102 const [popover1,popover2] = getPopoverReferences('test5'); 103 popover1.showPopover(); 104 popover1.querySelector('button').click(); // Use invoker to keep 2 visible 105 // Both 1 and 2 should be open at this point. 106 assert_true(popover1.matches(':popover-open'), 'popover1 not open'); 107 assert_true(isElementVisible(popover1)); 108 assert_true(popover2.matches(':popover-open'), 'popover2 not open'); 109 assert_true(isElementVisible(popover2)); 110 // This should hide both of them. 111 popover1.hidePopover(); 112 await waitForRender(); 113 assert_false(popover1.matches(':popover-open')); 114 assert_false(isElementVisible(popover1)); 115 assert_false(popover2.matches(':popover-open')); 116 assert_false(isElementVisible(popover2)); 117 }, "Popover ancestor relationships are within a root, not within the document"); 118 </script>