chromium/third_party/blink/web_tests/fast/scrolling/scrollbars/scrollbar-mousedown-move-mouseup.html

<!DOCTYPE html>
<script src='../../../resources/testharness.js'></script>
<script src='../../../resources/testharnessreport.js'></script>
<script src='../../../resources/gesture-util.js'></script>
<script src="../../../resources/blink-coordinates-util.js"></script>
<script src='../../../resources/scrollbar-util.js'></script>

<style>
  #scrollme,
  #notscrollme {
    width: 100px;
    height: 100px;
    overflow: auto;
  }

  #scrollme p {
    height: 1000px;
  }
</style>

<div id='scrollme'>
  <p>This is a scrollable div.</p>
</div>
<div id='notscrollme'></div>

<script>

  function readyPromise(scroller, other) {
    return new Promise(resolve => {
      const events = {
        'scrollme': [],
        'notscrollme': []
      };
      const initEventHandlers = (element) => {
        element.addEventListener('mousedown', (e) => {
                                   events[e.target.id].push(e);
                                 }, { once: true });
        element.addEventListener('mouseup', (e) => {
                                   events[e.target.id].push(e);
                                   requestAnimationFrame(() => {
                                     requestAnimationFrame(() => {
                                       resolve(events);
                                     });
                                   });
                                 }, { once: true });
      }
      initEventHandlers(scroller);
      initEventHandlers(other);
    });
  }

  window.onload = async () => {
    const d1 = document.getElementById('scrollme');
    const d2 = document.getElementById('notscrollme');
    const scroll_start = trackTop(d1);
    // scroll_start.y + delta_y intentionally exceeds bounds of the scroll
    // container.
    const delta_y = d1.getBoundingClientRect().height;

    if (scrollbarThickness() == 0) {
      // Test is not relevant on platforms that don't display scrollbars.
      return;
    }

    internals.settings.setScrollAnimatorEnabled(false);

    async function runMouseDragTest(button) {
      await waitForCompositorReady();
      await waitForScrollReset(d1);
      const ready = readyPromise(d1, d2);
      // TOOD(kevers): Switch to a method that uses test-driver. At present,
      // the test driver version does not include separate pauses before and
      // after the move, which turned out to result in test flakes.
      await mouseDragAndDrop(
        scroll_start.x,
        scroll_start.y,
        scroll_start.x,
        scroll_start.y + delta_y,
        pointerActionButtonId(button));
      const events = await ready;
      assert_greater_than(d1.scrollTop, 0);
      assert_equals(d2.scrollTop, 0);
      const which = button == Buttons.LEFT ? 1 : 2;
      assert_equals(events['notscrollme'].length, 0);
      assert_equals(events['scrollme'].length, 2);
      assert_equals(events['scrollme'][0].type, 'mousedown');
      assert_equals(events['scrollme'][0].which, which);
      assert_equals(events['scrollme'][1].type, 'mouseup');
      assert_equals(events['scrollme'][1].which, which);
    }

    promise_test(async () => {
      return runMouseDragTest(Buttons.LEFT);
    }, 'Drag a scrollbar with the left button and release it on another DIV, ' +
       'only the DIV that owns the dragging scrollbar receive mouse events');

    promise_test(async () => {
      return runMouseDragTest(Buttons.MIDDLE);
    }, 'Drag a scrollbar with the middle button and release it on another ' +
       'DIV, only the DIV that owns the dragging scrollbar receive mouse ' +
       'events');
}
</script>