blob: 83d653ab1d6bd535235b946f68aa089306872810 [file] [log] [blame]
<!DOCTYPE html>
<title>Tests mouse autoscroll interactions on a non-custom composited div scrollbar.</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../../resources/gesture-util.js"></script>
<script src="../../../resources/scrollbar-util.js"></script>
<style>
.appearance {
width: 100px;
height: 100px;
overflow: scroll;
border: 1px solid black;
}
.location {
position: absolute;
top: 100px;
left: 100px;
}
.space {
height: 2000px;
width: 2000px;
}
</style>
<!-- Composited non-custom scroller -->
<div id="scroller" class="appearance location">
<div id="divContent" class="space"></div>
</div>
<script>
// Turn off animated scrolling. The "conditionHolds" API expects the scrollTop to
// *not* change for 10 frames. This will fail since the last GSU would still be
// animating if animated scrolling were on.
if (window.internals)
internals.settings.setScrollAnimatorEnabled(false);
const scroller = document.getElementById("scroller");
const scrollerRect = scroller.getBoundingClientRect();
const onMacPlatform = navigator.userAgent.search(/\bMac OS X\b/) != -1;
const TRACK_WIDTH = calculateScrollbarThickness();
const BUTTON_WIDTH = TRACK_WIDTH;
const SCROLL_CORNER = TRACK_WIDTH;
const SCROLL_DELTA = (internals.runtimeFlags.percentBasedScrollingEnabled) ?
Math.floor(scroller.clientHeight * SCROLLBAR_SCROLL_PERCENTAGE) * 10 :
SCROLLBAR_SCROLL_PIXELS * 10;
const MAX_SCROLLER_OFFSET = 1915;
promise_test (async () => {
if(onMacPlatform)
return;
await waitForCompositorCommit();
scroller.scrollTop = 0;
const down_arrow_x = scrollerRect.right - BUTTON_WIDTH / 2;
const down_arrow_y = scrollerRect.bottom - SCROLL_CORNER - BUTTON_WIDTH / 2;
await mouseMoveTo(down_arrow_x, down_arrow_y);
await mouseDownAt(down_arrow_x, down_arrow_y);
await waitUntil(() => { return scroller.scrollTop > SCROLL_DELTA; },
`scroller.scrollTop = ${scroller.scrollTop} never went beyond ${SCROLL_DELTA}`);
await mouseUpAt(down_arrow_x, down_arrow_y);
// Since autoscroll for arrows happens at 800 px per second, verify that the
// scrollTop has not reached the end.
assert_less_than(scroller.scrollTop, MAX_SCROLLER_OFFSET, "Reached scroller end.");
await waitForCompositorCommit();
const current_offset = scroller.scrollTop;
await conditionHolds(() => { return scroller.scrollTop == current_offset; },
`scroller.scrollTop = ${scroller.scrollTop} current_offset = ${current_offset}`);
},"Test arrow autoscroll down and autoscroll stop.");
promise_test (async () => {
await waitForCompositorCommit();
scroller.scrollTop = 0;
const trackscroll_x = scrollerRect.right - BUTTON_WIDTH / 2;
const trackscroll_y = scrollerRect.bottom - SCROLL_CORNER - BUTTON_WIDTH;
await mouseMoveTo(trackscroll_x, trackscroll_y);
await mouseDownAt(trackscroll_x, trackscroll_y);
await waitUntil(() => { return scroller.scrollTop > SCROLL_DELTA; },
`scroller.scrollTop = ${scroller.scrollTop} never went beyond ${SCROLL_DELTA}`);
await mouseUpAt(trackscroll_x, trackscroll_y);
// Verify that the track autoscroll actually stops as expected. Autoscroll velocity
// in this particular case is 1480 px/sec (i.e 74 * 20). There is currently a bug in
// the main thread autoscrolling code that causes autoscrolling to happen at a
// much lower velocity (crbug.com/1053398)
assert_less_than(scroller.scrollTop, 800, "Track autosroll did not end.");
const current_offset = scroller.scrollTop;
await conditionHolds(() => { return scroller.scrollTop == current_offset; },
`scroller.scrollTop = ${scroller.scrollTop} current_offset = ${current_offset}`);
},"Test track autoscroll down and autoscroll stop.");
promise_test (async () => {
// Scrollbars on Mac don't have arrows. This test is irrelevant. Infinite auto
// scroll can't be tested for track scrolls since autoscrolling aborts the as
// soon as the thumb reaches the pointer. Regular autoscrolling still has coverage
// on all platforms.
if(onMacPlatform)
return;
await waitForCompositorCommit();
scroller.scrollTop = MAX_SCROLLER_OFFSET;
const content = document.getElementById("divContent");
const originalDivHeight = content.clientHeight;
const extendedDivHeight = originalDivHeight + 500;
setTimeout(function() {
content.setAttribute("style","height:" + extendedDivHeight + "px");
}, 500);
const down_arrow_x = scrollerRect.right - BUTTON_WIDTH / 2;
const down_arrow_y = scrollerRect.bottom - SCROLL_CORNER - BUTTON_WIDTH / 2;
// Keep the mouse pressed. The previously scheduled scroller height increment kicks in
// and at this point, the autoscrolling is expected to take place. This should prove
// that scrolling occured *after* the scroller length was extended.
await mouseMoveTo(down_arrow_x, down_arrow_y);
await mouseDownAt(down_arrow_x, down_arrow_y);
// Verify that autoscroll took place beyond the old bounds. If there is a regression here,
// the scroller.scrollTop would've stayed at MAX_SCROLLER_OFFSET.
await waitUntil(() => { return scroller.scrollTop > MAX_SCROLLER_OFFSET; },
`Infinite autoscroll down failed (scroller.scrollTop = ${scroller.scrollTop})`);
await mouseUpAt(down_arrow_x, down_arrow_y);
// Reset the scroller dimensions.
content.setAttribute("style","height:" + originalDivHeight + "px");
},"Test infinite scrolling when content is extended dynamically.");
promise_test (async () => {
// Scrollbars on Mac don't have arrows. This test is irrelevant.
if(onMacPlatform)
return;
scroller.scrollTop = 0;
const SCROLL_TOP = 100;
const down_arrow_x = scrollerRect.right - BUTTON_WIDTH / 2;
const down_arrow_y = scrollerRect.bottom - SCROLL_CORNER - BUTTON_WIDTH / 2;
// Keep the mouse pressed on the down arrow.
await mouseMoveTo(down_arrow_x, down_arrow_y);
await mouseDownAt(down_arrow_x, down_arrow_y);
// Wait for a bit for the autoscroll to start. In the call below, the first 250ms
// is spent waiting for the autoscroll to start. After 250ms, autoscroll initiates
// with a velocity of 800px/sec. So, in the remaining time (of 250ms), the duration
// should be enough to take the scroller beyond the expected threshold (SCROLL_TOP).
// Note that the expected SCROLL_TOP here is 100px. If scrolling crosses this value,
// it should suffice as proof that autoscrolling works as expected.
await waitForMs(500);
await waitFor(() => { return scroller.scrollTop >= SCROLL_TOP; },
`scroller.scrollTop = ${scroller.scrollTop} never reached ${SCROLL_TOP}`);
// Without releasing the mouse, move away from the arrow.
await mouseMoveTo(down_arrow_x, down_arrow_y - 20);
// Now that the mouse is away, record the scrolltop and ensure that no scrolling happens.
const current_scrolltop = scroller.scrollTop;
await conditionHolds(() => { return current_scrolltop == scroller.scrollTop; },
`Condition did not hold [scroller.scrollTop = ${scroller.scrollTop}]`);
// Now move back on the arrow and verify that auto-scrolling starts immediately. There
// should not be the 250ms pause before starting autoscroll since the mouse was never released.
await mouseMoveTo(down_arrow_x, down_arrow_y);
// Allow some time for queued GSU's to fire.
await waitFor(() => { return scroller.scrollTop >= current_scrolltop; },
`Animation did not restart [scroller.scrollTop = ${scroller.scrollTop}]`);
await mouseUpAt(down_arrow_x, down_arrow_y);
},"Test autoscroll play/pause when pointer moves in and out of arrow bounds.");
</script>