tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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>