chromium/third_party/blink/web_tests/virtual/threaded/fast/events/pinch/scroll-visual-viewport-send-boundary-events.html

<!DOCTYPE html>
<script src="../../../../../resources/testharness.js"></script>
<script src="../../../../../resources/testharnessreport.js"></script>
<script src="../../../../../resources/gesture-util.js"></script>
<style>
#target {
  margin: 0px;
  width: 100px;
  height: 100px;
  border: solid;
  position: absolute;
  left: 100px;
  top: 100px;
}
</style>
<div id='target' onmouseover="this.innerHTML='OVER';" onmouseout="this.innerHTML='OUT'">OUT</div>
<script>
// The pinch is done away from the edge of the viewport so the anchor doesn't
// snap to the edge.
const TEST_X = 150;
const TEST_Y = 150;
const TEST_SCALE = 2;
const EPSILON = 0.001;
const SCROLL_TOLERANCE = 10;
const MOUSE_INPUT = GestureSourceType.MOUSE_INPUT;

function waitForVisualViewportOffset(x, y) {
  return new Promise(function(resolve, reject) {
    function pollForOffset(frames) {
      if (Math.abs(window.visualViewport.offsetLeft - x) <= SCROLL_TOLERANCE &&
          Math.abs(window.visualViewport.offsetTop - y) <= SCROLL_TOLERANCE) {
        resolve();
      } else if (frames > 500) {
        reject("Scroll timeout. visualViewport.offsetLeft = " + visualViewport.offsetLeft +
               "visualViewport.offsetTop = " + visualViewport.offsetTop);
      } else {
        window.requestAnimationFrame(pollForOffset.bind(this, frames + 1));
      }
    }
    pollForOffset(0);
  });
}

promise_test(async () => {
  // Move mouse to hover the target
  await mouseMoveTo(TEST_X, TEST_Y);
  await waitForCompositorCommit();
  assert_equals(target.innerHTML, 'OVER', 'cursor over target after mouse move');

  // pinch to create an scrollable visual viewport
  await pinchBy(TEST_SCALE, TEST_X, TEST_Y, undefined, MOUSE_INPUT)
  assert_approx_equals(window.visualViewport.scale, TEST_SCALE, EPSILON);
  assert_approx_equals(window.visualViewport.offsetLeft, 75, EPSILON);
  assert_approx_equals(window.visualViewport.offsetTop, 75, EPSILON);
  await waitForCompositorCommit();
  assert_equals(target.innerHTML, 'OVER', 'cursor over target after pinch zoom');

  // scroll visual viewport
  await waitForCompositorCommit();
  await smoothScroll(200, TEST_X, TEST_Y, MOUSE_INPUT, 'down');

  await waitForVisualViewportOffset(75, 175);
  assert_equals(window.scrollX, 0);
  assert_equals(window.scrollY, 0);
  await waitForCompositorCommit();
  assert_equals(target.innerHTML, 'OUT', 'cursor over target after scroll');
}, 'Touchpad pinch and scroll sends boundary events');

</script>