<!doctype html>
<html>
<head>
<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-vendor.js"></script>
<style>
#target {
border: 1px solid black;
height: 400px;
width: 400px;
overflow-y: scroll;
resize: both;
}
.spacer {
height: 2000px;
width: 100%;
}
</style>
</head>
<body onload=runTest()>
<div id="target">
<button id="targetButton">target</button>
<div class="spacer"></div>
</div>
<button id="docButton">doc</button>
<div class="spacer"></div>
<script>
let target_div = document.getElementById("target");
async function scrollDownElement(element, num_keydowns) {
const arrowDown = '\uE015';
for (let i = 0; i < num_keydowns; i++) {
await test_driver.send_keys(element, arrowDown);
}
}
async function scrollUpElement(element, num_keydowns) {
const arrowUp = '\uE013';
for (let i = 0; i < num_keydowns; i++) {
await test_driver.send_keys(element, arrowUp);
}
}
async function testSingleScrollendFired(test, scrolling_element, listening_element, button_element) {
await waitForCompositorCommit();
// This test ensures that only one scrollend fires when scrolling an element
// from scrollTop=|target_offset| to scrollTop=0.
// |target_offset| is calculated to be a scroll offset large enough to
// require multiple key downs.
await waitForScrollReset(scrolling_element);
assert_equals(scrolling_element.scrollTop, 0, "element should not be scrolled");
let target_scrollend_promise = waitForScrollendEvent(listening_element);
// Buttons are capable of grabbing input focus so they provide a
// consistent mechanism for targeting key events.
await scrollDownElement(button_element, 1);
await target_scrollend_promise;
let single_keydown_offset = scrolling_element.scrollTop;
assert_greater_than(single_keydown_offset, 0, "should have non-zero scroll offset");
let target_offset = 3 * single_keydown_offset;
target_scrollend_promise = waitForScrollendEvent(listening_element);
scrolling_element.scrollTop = target_offset;
await target_scrollend_promise;
assert_equals(scrolling_element.scrollTop, target_offset);
target_scrollend_promise = waitForScrollendEvent(listening_element);
await scrollUpElement(button_element, 5);
await target_scrollend_promise;
// If scrollend fired prematurely, we would see non-zero scrolltop.
assert_equals(scrolling_element.scrollTop, 0, "element should be scrolled all the way back up.");
}
function runTest() {
if (!window.internals)
return;
internals.settings.setScrollAnimatorEnabled(true);
promise_test(async (t) => {
await testSingleScrollendFired(t, target_div, target_div, targetButton);
}, "scrollend event fired for target element, only once.");
promise_test(async (t) => {
await testSingleScrollendFired(t, document.scrollingElement, document, docButton);
}, "scrollend event fired for root scroller, only once.");
}
</script>
</body>
</html>