chromium/third_party/blink/web_tests/fast/events/touch/gesture/touch-gesture-scroll-multiply-nested-div-past-extent.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/testdriver.js"></script>
<script src="../../../../resources/testdriver-actions.js"></script>
<script src="../../../../resources/testdriver-vendor.js"></script>
<style>
body {
  margin: 0;
}

.greenbox {
  width: 100px;
  height: 100px;
  background: green;
  padding: 0px;
  margin: 0px;
}

.redbox {
  width: 100px;
  height: 100px;
  background: red;
  padding: 0px;
  margin: 0px;
}

.bluebox {
  width: 100px;
  height: 100px;
  background: blue;
  padding: 0px;
  margin: 0px;
}

.yellowbox {
  width: 100px;
  height: 100px;
  background: yellow;
  padding: 0px;
  margin: 0px;
}

#innerdiv {
  width: 200px;
  height: 200px;
  overflow-y: scroll;
  overflow-x: scroll;
}

#outerdiv {
  width: 250px;
  height: 250px;
  overflow-y: scroll;
  overflow-x: scroll;
}

#outermostdiv {
  width: 300px;
  height: 300px;
  overflow-y: scroll;
  overflow-x: scroll;
}
</style>
<body>
<div id="outermostdiv">
  <div id="outerdiv">
    <div id="innerdiv">
      <div class="greenbox"></div>
      <div class="redbox"></div>
      <div class="greenbox"></div>
    </div>
    <div class="bluebox"></div>
  </div>
  <div class="yellowbox"></div>
</div>
</body>

<script>
promise_test (async () => {
  assert_equals(outerdiv.scrollTop, 0);
  assert_equals(innerdiv.scrollTop, 0);
  assert_equals(outermostdiv.scrollTop, 0);

  const target = document.getElementById("innerdiv");
  const insets = {x: 20, y: 20};
  const position = elementPosition(target,
                                   ElementAlignment.CENTER,
                                   ElementAlignment.BOTTOM,
                                   insets);
  const innerScrollRange = target.scrollHeight - target.clientHeight;
  const outerScrollRange = outerdiv.scrollHeight - outerdiv.clientHeight;
  const outermostScrollRange =
      outermostdiv.scrollHeight - outermostdiv.clientHeight;

  const dx = 0;
  const dy = -position.y;
  // Amount we expect to drag before scrolling starts.
  // Ensure that the drag amount is enough to position any of the scroll
  // containers at their respective boundary.
  const touchSlop = 15;
  const requiredDrag =
     Math.max(innerScrollRange, outerScrollRange, outermostScrollRange) +
         touchSlop;
  assert_greater_than(Math.abs(dy), requiredDrag);

  // First scroll positions target at scroll boundary, and remainder does not
  // propagate.
  await touchScroll(position.x, position.y, dx, dy, target);
  assert_equals(target.scrollTop, innerScrollRange);
  assert_equals(outerdiv.scrollTop, 0);
  assert_equals(outermostdiv.scrollTop, 0);

  // Second scroll propagates to outerdiv, positioning it at the scrollboundary.
  // Remaining scroll delta does not propagate to outermost.
  await touchScroll(position.x, position.y, dx, dy, outerdiv);
  assert_equals(target.scrollTop, innerScrollRange);
  assert_equals(outerdiv.scrollTop, outerScrollRange);
  assert_equals(outermostdiv.scrollTop, 0);

  // Third scroll propagates to outermostdiv, positioning it at the
  // scrollboundary.
  await touchScroll(position.x, position.y, dx, dy, outermostdiv);
  assert_equals(target.scrollTop, innerScrollRange);
  assert_equals(outerdiv.scrollTop, outerScrollRange);
  assert_equals(outermostdiv.scrollTop, outermostScrollRange);
}, 'This tests gesture scroll propagation with multiply nesting of ' +
   'scroll containers');
</script>