tor-browser

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

browser_selectpopup_large.js (9035B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 const PAGECONTENT_SMALL = `
      5  <!doctype html>
      6  <html>
      7  <body><select id='one'>
      8    <option value='One'>One</option>
      9    <option value='Two'>Two</option>
     10  </select><select id='two'>
     11    <option value='Three'>Three</option>
     12    <option value='Four'>Four</option>
     13  </select><select id='three'>
     14    <option value='Five'>Five</option>
     15    <option value='Six'>Six</option>
     16  </select></body></html>
     17 `;
     18 
     19 async function performLargePopupTests(win) {
     20  let browser = win.gBrowser.selectedBrowser;
     21 
     22  await SpecialPowers.spawn(browser, [], async function () {
     23    let doc = content.document;
     24    let select = doc.getElementById("one");
     25    for (var i = 0; i < 180; i++) {
     26      select.add(new content.Option("Test" + i));
     27    }
     28 
     29    select.options[60].selected = true;
     30    select.focus();
     31  });
     32 
     33  // Check if a drag-select works and scrolls the list.
     34  const selectPopup = await openSelectPopup("mousedown", "select", win);
     35  const browserRect = browser.getBoundingClientRect();
     36 
     37  let getScrollPos = () => selectPopup.scrollBox.scrollbox.scrollTop;
     38  let scrollPos = getScrollPos();
     39  let popupRect = selectPopup.getBoundingClientRect();
     40 
     41  // First, check that scrolling does not occur when the mouse is moved over the
     42  // anchor button but not the popup yet.
     43  EventUtils.synthesizeMouseAtPoint(
     44    popupRect.left + 5,
     45    popupRect.top - 10,
     46    {
     47      type: "mousemove",
     48      buttons: 1,
     49    },
     50    win
     51  );
     52  is(
     53    getScrollPos(),
     54    scrollPos,
     55    "scroll position after mousemove over button should not change"
     56  );
     57 
     58  EventUtils.synthesizeMouseAtPoint(
     59    popupRect.left + 20,
     60    popupRect.top + 10,
     61    {
     62      type: "mousemove",
     63      buttons: 1,
     64    },
     65    win
     66  );
     67 
     68  // Dragging above the popup scrolls it up.
     69  let scrolledPromise = BrowserTestUtils.waitForEvent(
     70    selectPopup,
     71    "scroll",
     72    false,
     73    () => getScrollPos() < scrollPos - 5
     74  );
     75  EventUtils.synthesizeMouseAtPoint(
     76    popupRect.left + 20,
     77    popupRect.top - 20,
     78    {
     79      type: "mousemove",
     80      buttons: 1,
     81    },
     82    win
     83  );
     84  await scrolledPromise;
     85  ok(true, "scroll position at drag up");
     86 
     87  // Dragging below the popup scrolls it down.
     88  scrollPos = getScrollPos();
     89  scrolledPromise = BrowserTestUtils.waitForEvent(
     90    selectPopup,
     91    "scroll",
     92    false,
     93    () => getScrollPos() > scrollPos + 5
     94  );
     95  EventUtils.synthesizeMouseAtPoint(
     96    popupRect.left + 20,
     97    popupRect.bottom + 20,
     98    {
     99      type: "mousemove",
    100      buttons: 1,
    101    },
    102    win
    103  );
    104  await scrolledPromise;
    105  ok(true, "scroll position at drag down");
    106 
    107  // Releasing the mouse button and moving the mouse does not change the scroll position.
    108  scrollPos = getScrollPos();
    109  EventUtils.synthesizeMouseAtPoint(
    110    popupRect.left + 20,
    111    popupRect.bottom + 25,
    112    { type: "mouseup" },
    113    win
    114  );
    115  is(getScrollPos(), scrollPos, "scroll position at mouseup should not change");
    116 
    117  EventUtils.synthesizeMouseAtPoint(
    118    popupRect.left + 20,
    119    popupRect.bottom + 20,
    120    { type: "mousemove" },
    121    win
    122  );
    123  is(
    124    getScrollPos(),
    125    scrollPos,
    126    "scroll position at mousemove after mouseup should not change"
    127  );
    128 
    129  // Now check dragging with a mousedown on an item
    130  let menuRect = selectPopup.children[51].getBoundingClientRect();
    131  EventUtils.synthesizeMouseAtPoint(
    132    menuRect.left + 5,
    133    menuRect.top + 5,
    134    { type: "mousedown" },
    135    win
    136  );
    137 
    138  // Dragging below the popup scrolls it down.
    139  scrolledPromise = BrowserTestUtils.waitForEvent(
    140    selectPopup,
    141    "scroll",
    142    false,
    143    () => getScrollPos() > scrollPos + 5
    144  );
    145  EventUtils.synthesizeMouseAtPoint(
    146    popupRect.left + 20,
    147    popupRect.bottom + 20,
    148    {
    149      type: "mousemove",
    150      buttons: 1,
    151    },
    152    win
    153  );
    154  await scrolledPromise;
    155  ok(true, "scroll position at drag down from option");
    156 
    157  // Dragging above the popup scrolls it up.
    158  scrolledPromise = BrowserTestUtils.waitForEvent(
    159    selectPopup,
    160    "scroll",
    161    false,
    162    () => getScrollPos() < scrollPos - 5
    163  );
    164  EventUtils.synthesizeMouseAtPoint(
    165    popupRect.left + 20,
    166    popupRect.top - 20,
    167    {
    168      type: "mousemove",
    169      buttons: 1,
    170    },
    171    win
    172  );
    173  await scrolledPromise;
    174  ok(true, "scroll position at drag up from option");
    175 
    176  scrollPos = getScrollPos();
    177  // We intentionally turn off this a11y check, because the following click
    178  // is sent on an arbitrary web content that is not expected to be tested
    179  // by itself with the browser mochitests, therefore this rule check shall
    180  // be ignored by a11y-checks suite.
    181  AccessibilityUtils.setEnv({ labelRule: false });
    182  EventUtils.synthesizeMouseAtPoint(
    183    popupRect.left + 20,
    184    popupRect.bottom + 25,
    185    { type: "mouseup" },
    186    win
    187  );
    188  AccessibilityUtils.resetEnv();
    189  is(
    190    getScrollPos(),
    191    scrollPos,
    192    "scroll position at mouseup from option should not change"
    193  );
    194 
    195  EventUtils.synthesizeMouseAtPoint(
    196    popupRect.left + 20,
    197    popupRect.bottom + 20,
    198    { type: "mousemove" },
    199    win
    200  );
    201  is(
    202    getScrollPos(),
    203    scrollPos,
    204    "scroll position at mousemove after mouseup should not change"
    205  );
    206 
    207  await hideSelectPopup("escape", win);
    208 
    209  let positions = [
    210    "margin-top: 300px;",
    211    "position: fixed; bottom: 200px;",
    212    "width: 100%; height: 9999px;",
    213  ];
    214 
    215  let position;
    216  while (positions.length) {
    217    await openSelectPopup("key", "select", win);
    218 
    219    let rect = selectPopup.getBoundingClientRect();
    220    let marginBottom = parseFloat(getComputedStyle(selectPopup).marginBottom);
    221    let marginTop = parseFloat(getComputedStyle(selectPopup).marginTop);
    222    Assert.greaterOrEqual(
    223      rect.top - marginTop,
    224      browserRect.top,
    225      "Popup top position in within browser area"
    226    );
    227    Assert.lessOrEqual(
    228      rect.bottom + marginBottom,
    229      browserRect.bottom,
    230      "Popup bottom position in within browser area"
    231    );
    232 
    233    let cs = win.getComputedStyle(selectPopup);
    234    let csArrow = win.getComputedStyle(selectPopup.scrollBox);
    235    let bpBottom =
    236      parseFloat(cs.paddingBottom) +
    237      parseFloat(cs.borderBottomWidth) +
    238      parseFloat(csArrow.paddingBottom) +
    239      parseFloat(csArrow.borderBottomWidth);
    240    let selectedOption = 60;
    241 
    242    if (Services.prefs.getBoolPref("dom.forms.selectSearch")) {
    243      // Use option 61 instead of 60, as the 60th option element is actually the
    244      // 61st child, since the first child is now the search input field.
    245      selectedOption = 61;
    246    }
    247    // Some of the styles applied to the menuitems are percentages, meaning
    248    // that the final layout calculations returned by getBoundingClientRect()
    249    // might return floating point values. We don't care about sub-pixel
    250    // accuracy, and only care about the final pixel value, so we add a
    251    // fuzz-factor of 1.
    252    const fuzzFactor = 1;
    253    SimpleTest.isfuzzy(
    254      selectPopup.children[selectedOption].getBoundingClientRect().bottom,
    255      selectPopup.getBoundingClientRect().bottom - bpBottom + marginBottom,
    256      fuzzFactor,
    257      "Popup scroll at correct position " + bpBottom
    258    );
    259 
    260    await hideSelectPopup("enter", win);
    261 
    262    position = positions.shift();
    263 
    264    let contentPainted = BrowserTestUtils.waitForContentEvent(
    265      browser,
    266      "MozAfterPaint"
    267    );
    268    await SpecialPowers.spawn(
    269      browser,
    270      [position],
    271      async function (contentPosition) {
    272        let select = content.document.getElementById("one");
    273        select.setAttribute("style", contentPosition || "");
    274        select.getBoundingClientRect();
    275      }
    276    );
    277    await contentPainted;
    278  }
    279 }
    280 
    281 add_setup(async function () {
    282  await SpecialPowers.pushPrefEnv({
    283    set: [["test.wait300msAfterTabSwitch", true]],
    284  });
    285 });
    286 
    287 // This test checks select elements with a large number of options to ensure that
    288 // the popup appears within the browser area.
    289 add_task(async function test_large_popup() {
    290  const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
    291  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
    292 
    293  await performLargePopupTests(window);
    294 
    295  BrowserTestUtils.removeTab(tab);
    296 });
    297 
    298 // This test checks the same as the previous test but in a new, vertically smaller window.
    299 add_task(async function test_large_popup_in_small_window() {
    300  let newWin = await BrowserTestUtils.openNewBrowserWindow();
    301 
    302  let resizePromise = BrowserTestUtils.waitForEvent(
    303    newWin,
    304    "resize",
    305    false,
    306    () => {
    307      info(`Got resize event (innerHeight: ${newWin.innerHeight})`);
    308      return newWin.innerHeight <= 450;
    309    }
    310  );
    311  newWin.resizeTo(600, 450);
    312  await resizePromise;
    313 
    314  const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
    315  let browserLoadedPromise = BrowserTestUtils.browserLoaded(
    316    newWin.gBrowser.selectedBrowser
    317  );
    318  BrowserTestUtils.startLoadingURIString(
    319    newWin.gBrowser.selectedBrowser,
    320    pageUrl
    321  );
    322  await browserLoadedPromise;
    323 
    324  newWin.gBrowser.selectedBrowser.focus();
    325 
    326  await performLargePopupTests(newWin);
    327 
    328  await BrowserTestUtils.closeWindow(newWin);
    329 });