tor-browser

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

helper_no_synth_mousemove_after_pan.html (5192B)


      1 <!doctype html>
      2 <html>
      3 <head>
      4 <meta charset="utf-8">
      5 <meta name="viewport" content="width=device-width; initial-scale=1.0,minimum-scale=1.0">
      6 <title>Test for no synthetic eMouseMove after swipe to scroll</title>
      7 <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
      8 <script type="application/javascript" src="apz_test_utils.js"></script>
      9 <script src="/tests/SimpleTest/paint_listener.js"></script>
     10 <script src="/tests/SimpleTest/EventUtils.js"></script>
     11 <style>
     12 body {
     13  margin: 0;
     14 }
     15 div {
     16  margin: 0;
     17  height: 2lh;
     18 }
     19 div:hover {
     20  background-color: limegreen;
     21 }
     22 </style>
     23 <script>
     24 "use strict";
     25 
     26 addEventListener("DOMContentLoaded", () => {
     27  document.body.innerHTML = "";
     28  for (let i = 0; i < 100; i++) {
     29    const div = document.createElement("div");
     30    div.id = `div${i}`;
     31    document.body.appendChild(div);
     32  }
     33  document.documentElement.getBoundingClientRect();
     34  waitUntilApzStable()
     35    .then(test)
     36    .then(subtestDone, subtestFailed);
     37 }, {once: true});
     38 
     39 async function test() {
     40  while (document.documentElement.scrollY == 0) {
     41    // the scrollframe is not yet marked as APZ-scrollable. Mark it so
     42    // before continuing.
     43    document.documentElement.scrollTo(0, 1);
     44    await promiseApzFlushedRepaints();
     45  }
     46  const height = window.innerHeight;
     47  const divToBeSwiped = document.body.querySelector(`div:nth-child(${
     48    Math.floor(height / document.body.firstElementChild.getBoundingClientRect().height)
     49  })`);
     50  const divToBeSwipedRect = divToBeSwiped.getBoundingClientRect();
     51  ok(
     52    height > divToBeSwipedRect.height * 5,
     53    `The viewport should be able to show at least 5 <div> elements, expected taller than ${
     54      divToBeSwipedRect.height * 5
     55    }, but ${height}`
     56  );
     57  // Wait for synthesized mousemove is flushed in the next animation frame
     58  // before doing some since it'll fix the `:hover` state and mouse/pointer
     59  // boundary event state with the latest layout.
     60  function flushPendingSynthesizedMouseMove(aCallback) {
     61    requestAnimationFrame(
     62      () => requestAnimationFrame(aCallback)
     63    );
     64  }
     65  function promiseFlushPendingSynthesizedMouseMove() {
     66    return new Promise(resolve => {
     67      flushPendingSynthesizedMouseMove(resolve);
     68    });
     69  }
     70 
     71  // First, make PresShell forgets the last mouse location which may be set accidentally.
     72  synthesizeMouseAtCenter(divToBeSwiped, {type: "mousecancel"}, {once: true});
     73  // Hopefully, synthesize a tap first.  That may cause PresShell storing the
     74  // tap point as the last mouse location since that should cause a set of
     75  // compatibility mouse events.
     76  info("Synthesizing a tap...");
     77  const waitForClick = new Promise(resolve => {
     78    addEventListener("click", event => {
     79      is(
     80        event.target,
     81        divToBeSwiped,
     82        "`click` should be fired on the bottom <div>"
     83      );
     84      const clickPosition = { x: event.clientX, y: event.clientY };
     85      flushPendingSynthesizedMouseMove(() => resolve(clickPosition));
     86    }, {once: true});
     87  });
     88  await promiseNativePointerTap(
     89    divToBeSwiped,
     90    "touch",
     91    divToBeSwipedRect.width / 2,
     92    divToBeSwipedRect.height / 2
     93  );
     94  info("Waiting for the click...");
     95  const clickPosition = await waitForClick;
     96  // Then, swipe from the bottom <div> to above to scroll down.
     97  info("Synthesizing a swipe...");
     98  const scrollTopBefore = document.documentElement.scrollTop;
     99  const waitForPointerCancel = new Promise(resolve => {
    100    addEventListener("pointercancel", resolve, {once: true});
    101  });
    102  const transformEndPromise = promiseTransformEnd();
    103  await promiseNativePointerDrag(
    104    divToBeSwiped,
    105    "touch",
    106    divToBeSwipedRect.width / 2,
    107    divToBeSwipedRect.height / 2,
    108    0, // deltaX
    109    divToBeSwipedRect.height * -3 // deltaY
    110  );
    111  info("Waiting for pointercancel which should be caused by the swipe...");
    112  await waitForPointerCancel;
    113  info("Waiting for transformEndPromise...");
    114  await transformEndPromise;
    115  info("Waiting for promiseApzFlushedRepaints()...");
    116  await promiseApzFlushedRepaints();
    117  await promiseFlushPendingSynthesizedMouseMove();
    118  const scrollTopAfter = document.documentElement.scrollTop;
    119  ok(
    120    scrollTopBefore + divToBeSwipedRect.height < scrollTopAfter,
    121    `The swipe should cause scrolling down, expected greater than ${
    122      scrollTopBefore + divToBeSwipedRect.height
    123    } (scrollTopBefore: ${scrollTopBefore}), but got ${scrollTopAfter}`
    124  );
    125  // Finally, the scroll down causes the element underneath the start position
    126  // of the swipe is a following <div> of the original <div> element.  However,
    127  // user must not want the <div> to have the :hover state since they have not
    128  // touched the <div>.
    129  const hoveredDiv = document.querySelector("div:hover");
    130  const elementAtClickedPosition = document.elementFromPoint(clickPosition.x, clickPosition.y);
    131  ok(
    132    !hoveredDiv || hoveredDiv != elementAtClickedPosition,
    133    `The div element at the previously clicked position should not have :hover state, got ${
    134      hoveredDiv ? hoveredDiv.outerHTML : "null"
    135    }${
    136      elementAtClickedPosition
    137        ? ` which should never be ${elementAtClickedPosition.outerHTML}`
    138        : ""
    139    }`
    140  );
    141 }
    142 </script>
    143 </head>
    144 <body></body>
    145 </html>