on-popover-behavior.html (5535B)
1 <!doctype html> 2 <meta charset="utf-8" /> 3 <meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" /> 4 <meta name="timeout" content="long" /> 5 <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="resources/invoker-utils.js"></script> 9 10 <div id="invokee" popover> 11 <button id="containedinvoker" commandfor="invokee" command="hide-popover"></button> 12 </div> 13 <button id="invokerbutton" commandfor="invokee" command="toggle-popover"></button> 14 15 <style> 16 #invokee { 17 margin: 0; 18 position-area: block-end span-all; 19 } 20 </style> 21 22 <script> 23 function resetState() { 24 invokerbutton.setAttribute("commandfor", "invokee"); 25 invokerbutton.setAttribute("command", "toggle-popover"); 26 containedinvoker.setAttribute("commandfor", "invokee"); 27 containedinvoker.setAttribute("command", "hide-popover"); 28 try { 29 invokee.hidePopover(); 30 } catch {} 31 invokee.setAttribute("popover", ""); 32 } 33 34 promise_test(async function (t) { 35 assert_false(invokee.matches(":popover-open")); 36 invokee.addEventListener("command", (e) => { invokerbutton.setAttribute('command', 'hide-popover'); }, { 37 once: true, 38 }); 39 invokerbutton.click(); 40 t.add_cleanup(resetState); 41 assert_true(invokee.matches(":popover-open")); 42 }, "changing command attribute inside invokeevent doesn't impact the invocation"); 43 44 // Open actions 45 [ 46 "toggle-popover", 47 "show-popover", 48 /* test case sensitivity */ 49 "tOgGlE-pOpOvEr", 50 "sHoW-pOpOvEr", 51 ].forEach((command) => { 52 test( 53 function (t) { 54 t.add_cleanup(resetState); 55 invokerbutton.command = command; 56 assert_false(invokee.matches(":popover-open")); 57 invokerbutton.click(); 58 assert_true(invokee.matches(":popover-open")); 59 }, 60 `invoking (as ${command}) closed popover opens`, 61 ); 62 63 test( 64 function (t) { 65 t.add_cleanup(resetState); 66 invokerbutton.command = command; 67 assert_false(invokee.matches(":popover-open")); 68 invokee.addEventListener("command", (e) => e.preventDefault(), { 69 once: true, 70 }); 71 invokerbutton.click(); 72 assert_false(invokee.matches(":popover-open")); 73 }, 74 `invoking (as ${command}) closed popover with preventDefault does not open`, 75 ); 76 }); 77 78 // Close actions 79 [ 80 "toggle-popover", 81 "hide-popover", 82 /* test case sensitivity */ 83 "tOgGlE-pOpOvEr", 84 "hIdE-pOpOvEr", 85 ].forEach((command) => { 86 test( 87 function (t) { 88 t.add_cleanup(resetState); 89 invokerbutton.command = command; 90 invokee.showPopover(); 91 assert_true(invokee.matches(":popover-open")); 92 invokerbutton.click(); 93 assert_false(invokee.matches(":popover-open")); 94 }, 95 `invoking (as ${command}) open popover closes`, 96 ); 97 98 test( 99 function (t) { 100 t.add_cleanup(resetState); 101 invokerbutton.command = command; 102 invokee.showPopover(); 103 assert_true(invokee.matches(":popover-open")); 104 invokee.addEventListener("command", (e) => e.preventDefault(), { 105 once: true, 106 }); 107 invokerbutton.click(); 108 assert_true(invokee.matches(":popover-open")); 109 }, 110 `invoking (as ${command}) open popover with preventDefault does not close`, 111 ); 112 113 test( 114 function (t) { 115 t.add_cleanup(resetState); 116 containedinvoker.command = command; 117 invokee.showPopover(); 118 assert_true(invokee.matches(":popover-open")); 119 containedinvoker.click(); 120 assert_false(invokee.matches(":popover-open")); 121 }, 122 `invoking (as ${command}) from within open popover closes`, 123 ); 124 125 test( 126 function (t) { 127 t.add_cleanup(resetState); 128 containedinvoker.command = command; 129 invokee.showPopover(); 130 invokee.addEventListener("command", (e) => e.preventDefault(), { 131 once: true, 132 }); 133 assert_true(invokee.matches(":popover-open")); 134 containedinvoker.click(); 135 assert_true(invokee.matches(":popover-open")); 136 }, 137 `invoking (as ${command}) from within open popover with preventDefault does not close`, 138 ); 139 }); 140 141 // show-popover specific 142 test(function (t) { 143 t.add_cleanup(resetState); 144 invokerbutton.setAttribute("command", "show-popover"); 145 invokee.showPopover(); 146 assert_true(invokee.matches(":popover-open")); 147 invokerbutton.click(); 148 assert_true(invokee.matches(":popover-open")); 149 }, "invoking (as show-popover) open popover is noop"); 150 151 // hide-popover specific 152 test(function (t) { 153 t.add_cleanup(resetState); 154 invokerbutton.setAttribute("command", "hide-popover"); 155 assert_false(invokee.matches(":popover-open")); 156 invokerbutton.click(); 157 assert_false(invokee.matches(":popover-open")); 158 }, "invoking (as hide-popover) closed popover is noop"); 159 160 161 test(function (t) { 162 t.add_cleanup(resetState); 163 invokerbutton.setAttribute("command", "show-popover"); 164 invokerbutton.click(); 165 assert_true(invokee.matches(":popover-open"), 166 ":popover-open should match after calling invokerbutton.click()"); 167 const rect = invokee.getBoundingClientRect(); 168 assert_not_equals(rect.y, 0, 169 "popover should not be at the top of the window because it is anchor positioned."); 170 }, "invoking (as show-popover) should create an implicit anchor reference for anchor positioning."); 171 </script>