chromium/third_party/blink/web_tests/fast/scrolling/scrollend-on-viewport-only-scroll.html

<!DOCTYPE html>

<body onload="runTest()">
  <script src="../../resources/gesture-util.js"></script>
  <script src="../../resources/testdriver.js"></script>
  <script src="../../resources/testdriver-vendor.js"></script>
  <script src="../../resources/testharness.js"></script>
  <script src="../../resources/testharnessreport.js"></script>
  <style>
    body, html {
    width: 100%;
    height: 100%;
    margin: 0;
    background-color: red;
    overflow: scroll;
  }
    #box {
      top: 25vh;
      left: 25vh;
      width: 50vh;
      height: 50vh;
      background-color: green;
      border: 5px solid black;
      box-sizing: border-box;
    }
  </style>
  <div id="box">
  </div>
  <script>
    async function resetScroller() {
      await waitForScrollReset(document.scrollingElement);
    }

    async function sendArrowDownToElement(element, num_keydowns) {
      const arrowDown = '\uE015';
      for (let i = 0; i < num_keydowns; i++) {
        await test_driver.send_keys(element, arrowDown);
      }
    }

    function runTest() {
      if (!internals)
        return;

      // Per kPixelsPerLineStep.
      const scroll_by_line_amount = 40;
      let scale = 2;
      internals.setPageScaleFactor(scale);

      promise_test(async () => {
        await resetScroller();
        await waitForCompositorCommit();

        assert_equals(visualViewport.offsetTop, 0);

        let y = box.getBoundingClientRect().top + box.clientHeight / 2;
        let x = box.getBoundingClientRect().left + box.clientWidth / 2;
        let scrollend_count = 0;
        let scroll_amount = 50;

        let scrollend_promise = waitForScrollendEvent(document);
        let top_before = visualViewport.offsetTop;
        await smoothScroll(scroll_amount, x, y,
                          GestureSourceType.TOUCHPAD_INPUT,
                          "down", SPEED_INSTANT);

        let scaled_offset = scroll_amount / scale;
        await waitFor(() => {
          return Math.abs(visualViewport.offsetTop - (top_before + scaled_offset)) < 1;
        });

        await scrollend_promise.then(
          (/* resolve */) => { assert_true(false, "scrollend should not fire!"); },
          (/* reject */) => { /* Didin't get scrollend which is okay. */}
        );
        assert_true(Math.abs(visualViewport.offsetTop - (top_before + scaled_offset)) < 1);

        // Restore VisualViewport to top.
        await smoothScroll(scroll_amount, x, y,
                          GestureSourceType.TOUCHPAD_INPUT,
                          "up", SPEED_INSTANT);
        await waitFor(() => { return visualViewport.offsetTop == 0; });
      }, "viewport pan should not trigger scrollend");

      promise_test(async () => {
        await resetScroller();
        await waitForCompositorCommit();

        assert_equals(visualViewport.offsetTop, 0);

        let num_keydowns = 3;
        let scroll_amount = scroll_by_line_amount * num_keydowns;

        let scrollend_promise = waitForScrollendEvent(document);
        let top_before = visualViewport.offsetTop;
        await sendArrowDownToElement(document.documentElement, num_keydowns);

        await waitFor(() => {
          // Keyboard scrolls don't appear to take scale into account so use
          // scroll_amount directly.
          // TODO(awogbemila): Find out if this should be a tighter bound.
          // Currently, in some VirtualTestSuites, offsetTop consistently
          // only hits a max value which is off by 3.375 pixels per keydown.
          return Math.abs(visualViewport.offsetTop - scroll_amount) < 4 * num_keydowns;
        });

        await scrollend_promise.then(
          (/* resolve */) => { assert_true(false, "scrollend should not fire!"); },
          (/* reject */) => { /* Didin't get scrollend which is okay. */}
        );
        assert_true(Math.abs(visualViewport.offsetTop - scroll_amount) < 4 * num_keydowns);
      }, "viewport pan via key should not trigger scrollend");
    }
  </script>
</body>