menuitem-activate.html (8596B)
1 <!DOCTYPE html> 2 <meta name="timeout" content="long"> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <script src="/resources/testdriver.js"></script> 6 <script src="/resources/testdriver-actions.js"></script> 7 <script src="/resources/testdriver-vendor.js"></script> 8 <script src="../../popovers/resources/popover-utils.js"></script> 9 <link rel=author href=mailto:dom@chromium.org> 10 <link rel=help href=https://open-ui.org/components/menu.explainer> 11 12 <menubar> 13 <menuitem id=menubarmenuitem commandfor=mainmenu command=toggle-menu>Open first menu</menuitem> 14 </menubar> 15 16 <menulist id=mainmenu> 17 <menuitem id=mainmenuitem command=toggle-menu commandfor=submenu>Toggle menu</menuitem> 18 <menuitem id=mainmenuitem2 command=toggle-popover commandfor=popover>Show popover</menuitem> 19 <menuitem id=normalmenuitem>Normal item</menuitem> 20 </menulist> 21 22 <menulist id=submenu> 23 <menuitem>First item!</menuitem> 24 </menulist> 25 26 <div popover id=popover></div> 27 28 <button popovertarget=popoverwithmenu>Open popover with menu</button> 29 <div popover id=popoverwithmenu> 30 <button popovertarget=menuinpopover>Open menu in the popover</button> 31 <menulist id=menuinpopover> 32 <menuitem id=menuinpopoveritem1>First item</menuitem> 33 <menuitem id=menuinpopoveritem2 command=toggle-menu commandfor=menuinpopover2>Toggle menu 2</menuitem> 34 </menulist> 35 <menulist id=menuinpopover2> 36 <menuitem>Submenu item</menuitem> 37 </menulist> 38 </div> 39 40 <style> 41 [popover] { 42 width: 400px; 43 height: 400px; 44 } 45 </style> 46 47 <script> 48 promise_test(async () => { 49 assert_false(mainmenu.matches(":popover-open"), "mainmenu popover starts closed"); 50 await test_driver.click(menubarmenuitem); 51 assert_true(mainmenu.matches(":popover-open"), "mainmenu opens"); 52 53 assert_false(submenu.matches(":popover-open"), "submenu popover starts closed"); 54 await test_driver.click(mainmenuitem); 55 assert_true(submenu.matches(":popover-open"), "submenu opens"); 56 57 // Close the submenu. 58 await test_driver.click(mainmenuitem); 59 assert_false(submenu.matches(":popover-open"), "submenu popover gets closed"); 60 assert_true(mainmenu.matches(":popover-open"), "mainmenu still open"); 61 62 // Close the mainmenu. 63 await test_driver.click(menubarmenuitem); 64 assert_false(mainmenu.matches(":popover-open"), "mainmenu gets closed"); 65 }, 'User menuitem activation works with the toggle-menu command'); 66 67 promise_test(async () => { 68 assert_false(mainmenu.matches(":popover-open"), "mainmenu popover starts closed"); 69 await test_driver.click(menubarmenuitem); 70 assert_true(mainmenu.matches(":popover-open"), "mainmenu popover opens"); 71 72 assert_false(popover.matches(":popover-open"), "div popover starts closed"); 73 await test_driver.click(mainmenuitem2); 74 assert_true(popover.matches(":popover-open"), "div popover opens"); 75 assert_false(mainmenu.matches(":popover-open"), "mainmenu popover closes"); 76 77 // Close the popover. 78 await test_driver.click(menubarmenuitem); 79 assert_false(popover.matches(":popover-open"), "div popover gets closed"); 80 assert_true(mainmenu.matches(":popover-open"), "mainmenu gets opened"); 81 await test_driver.click(menubarmenuitem); 82 assert_false(mainmenu.matches(":popover-open"), "mainmenu gets closed"); 83 }, 'User menuitem activation works with show-popover command'); 84 85 promise_test(async (t) => { 86 assert_false(popoverwithmenu.matches(":popover-open"), 87 "popover with menu starts closed"); 88 89 // Open the popover that hosts two menulists. 90 await test_driver.click( 91 document.querySelector("button[popovertarget=popoverwithmenu]")); 92 assert_true(popoverwithmenu.matches(":popover-open"), 93 "popover with menu opens"); 94 assert_false(menuinpopover.matches(":popover-open"), 95 "menu in popover starts closed"); 96 97 // Open the first menu in the popover. 98 await test_driver.click( 99 document.querySelector('button[popovertarget=menuinpopover]')); 100 assert_true(menuinpopover.matches(":popover-open"), "menu in popover opens"); 101 assert_true(popoverwithmenu.matches(":popover-open"), 102 "outer popover remains open"); 103 assert_false(menuinpopover2.matches(":popover-open"), 104 "menu 2 in popover starts closed"); 105 106 // Open the second menu in the popover. 107 await test_driver.click(menuinpopoveritem2); 108 assert_true(menuinpopover2.matches(":popover-open"), 109 "menu 2 in popover opens"); 110 assert_true(popoverwithmenu.matches(":popover-open"), 111 "outer popover remains open after opening menu 2"); 112 assert_true(menuinpopover.matches(":popover-open"), 113 "menu in popover remains open"); 114 115 // Close the second, "sub", menu within the popover by just clicking off of 116 // it. 117 await test_driver.click(menuinpopoveritem2); 118 assert_false(menuinpopover2.matches(":popover-open"), 119 "menu 2 in popover closes"); 120 assert_true(popoverwithmenu.matches(":popover-open"), 121 "outer popover remains open after closing menu 2"); 122 assert_true(menuinpopover.matches(":popover-open"), 123 "menu in popover remains open"); 124 }, 'Menulist inside a popover works correctly; does not get accidentally ' + 125 'dismissed by opening submenus'); 126 127 async function getCoords(invoker, invokee) { 128 // test_driver isn't suited to mousedown-drag-mouseup interactions when the 129 // mousedown triggers visibility of one of the elements. 130 await clickOn(invoker); 131 const menulist = invokee.parentElement; 132 assert_true(menulist.matches(":popover-open"), "menulist popover opens when clicked"); 133 let rect = invokee.getBoundingClientRect(); 134 let coords = {x: Math.round(rect.x + rect.width / 2), 135 y: Math.round(rect.y + rect.height / 2)}; 136 await test_driver.click(invoker); 137 assert_false(menulist.matches(":popover-open"), "menulist popover closes when clicked"); 138 return coords; 139 } 140 141 promise_test(async (t) => { 142 assert_false(mainmenu.matches(":popover-open"), "mainmenu popover starts closed"); 143 const normal_menu_coords = await getCoords(menubarmenuitem, normalmenuitem); 144 let invokerClicks = 0; 145 let itemClicks = 0; 146 menubarmenuitem.addEventListener('click',() => (++invokerClicks)); 147 normalmenuitem.addEventListener('click',() => (++itemClicks)); 148 let openStateAfterPointerdown = "none"; 149 menubarmenuitem.addEventListener('pointermove',() => { 150 // There will be two move events, one before the pointerdown and one after. 151 // Just capture the one after. 152 if (openStateAfterPointerdown === "none") { 153 openStateAfterPointerdown = "first-move"; 154 } else if (openStateAfterPointerdown === "first-move") { 155 openStateAfterPointerdown = mainmenu.matches(":popover-open") ? "open" : "closed"; 156 } 157 },{signal: t.get_signal()}); 158 await new test_driver.Actions() 159 .addPointer('mouse', 'mouse') 160 .pointerMove(0, 0, {origin: menubarmenuitem}) 161 .pointerDown() 162 // Extra move to trigger event on menubarmenuitem: 163 .pointerMove(2, 2, {origin: menubarmenuitem}) 164 // This is the center of normalmenuitem: 165 .pointerMove(normal_menu_coords.x, normal_menu_coords.y, {}) 166 .pointerUp() 167 .send(); 168 await waitForRender(); 169 assert_equals(openStateAfterPointerdown,"open", "mainmenu popover should open after pointer down"); 170 assert_false(mainmenu.matches(":popover-open"), "mainmenu popover should be closed after interaction"); 171 assert_equals(invokerClicks,0, "the invoking menu didn't get a click"); 172 // TODO: Menu items should fire a click event when they are selected. 173 // assert_equals(itemClicks,1, "the invoked menu did get a click"); 174 }, 'A mousedown-drag-mouseup gesture on a normal menuitem picks the item'); 175 176 promise_test(async (t) => { 177 assert_false(mainmenu.matches(":popover-open"), "mainmenu popover starts closed"); 178 assert_false(submenu.matches(":popover-open"), "submenu popover starts closed"); 179 const main_menu_coords = await getCoords(menubarmenuitem, mainmenuitem); 180 await new test_driver.Actions() 181 .addPointer('mouse', 'mouse') 182 .pointerMove(0, 0, {origin: menubarmenuitem}) 183 .pointerDown() 184 // This is the center of mainmenuitem: 185 .pointerMove(main_menu_coords.x, main_menu_coords.y, {}) 186 .pointerUp() 187 .send(); 188 await waitForRender(); 189 assert_true(mainmenu.matches(":popover-open"), "mainmenu popover should remain open, because submenu chosen"); 190 assert_true(submenu.matches(":popover-open"), "submenu popover should be open"); 191 await clickOn(menubarmenuitem); // Cleanup. 192 assert_false(mainmenu.matches(":popover-open"), "mainmenu popover should be closed"); 193 assert_false(submenu.matches(":popover-open"), "submenu popover should be closed"); 194 }, 'A mousedown-drag-mouseup gesture on a submenu item leaves both menus open'); 195 </script>