<!DOCTYPE html>
<style>
body, html {
width: 100%;
height: 100%;
margin: 0px;
}
#root-scroller::-webkit-scrollbar {
width: 0px;
height: 0px;
}
#root-scroller {
width: 100%;
height: 100%;
overflow: scroll;
position: absolute;
left: 0;
top: 0;
background-color: red;
scroll-snap-type: y mandatory;
}
.spacer {
width: 100%;
height: 100%;
}
#initial-snap-area {
width: 200px;
height: 50%;
background-color: blue;
scroll-snap-align: start;
}
#snap-area {
width: 200px;
height: 50%;
background-color: blue;
scroll-snap-align: start;
}
</style>
<script src="../../../resources/gesture-util.js"></script>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<div id="root-scroller">
<div class="spacer" style="background-color: PaleGreen"></div>
<div class="spacer" style="background-color: PaleGreen"></div>
<div id="initial-snap-area"></div>
<!--
Needed because otherwise the other snap-area's snap offset would get
clipped to the same offset as the initial snap area, which would make either
snap area a valid choice.
-->
<div style="height:10px;"></div>
<div id="snap-area"></div>
</div>
<script>
if (window.internals) {
internals.runtimeFlags.implicitRootScrollerEnabled = true;
}
const root_scroller = document.getElementById("root-scroller");
const snap_area = document.getElementById("snap-area");
const initial_area = document.getElementById("initial-snap-area");
// Tests that the visual viewport is affected when scrolling the global root
// scroller by gesture. The snap area is located at the bottom of the layout
// viewport, so the layout viewport cannot align with the snap area.
// However, when it becomes the global root scroller we should be scrolling the
// visual viewport too to align with the snap area.
//
// TODO: There is no test for programmatic scrolling because the expected
// behaviour of the visual viewport while scrolling the root scroller is not
// clear [1]. The current behaviour is that the visual viewport offset does not
// change, and only the layout viewport scrolls to the target.
// [1] https://github.com/w3c/csswg-drafts/issues/4393
promise_test(async function () {
const scale_factor = 2;
internals.setPageScaleFactor(scale_factor);
internals.setVisualViewportOffset(0, 0);
assert_equals(visualViewport.scale, 2);
assert_equals(visualViewport.offsetTop, 0);
await waitForCompositorCommit();
assert_equals(window.internals.effectiveRootScroller(document),
root_scroller,
"#root-scroller must be the effective root scroller");
// Should be snapped to the closer snap area on the initial layout.
assert_equals(visualViewport.offsetTop + root_scroller.scrollTop,
initial_area.offsetTop);
// Scroll halfway to the snap area. This will trigger the snapping.
const delta = snap_area.offsetTop / 2;
// Start scroll from the middle of the viewport.
const initial_scroll_position = {
x: visualViewport.width / 2,
y: visualViewport.height / 2
}
await smoothScroll(
delta,
initial_scroll_position.x,
initial_scroll_position.y,
GestureSourceType.TOUCH_INPUT,
'down',
SPEED_INSTANT);
await waitForAnimationEndTimeBased(() => {
return root_scroller.scrollTop;
});
// The offset of the visual viewport and the layout viewport combined should
// be at the snap point.
assert_equals(visualViewport.offsetTop + root_scroller.scrollTop,
snap_area.offsetTop, "Visual viewport offset combined with the scroller's \
scroll offset should add to the snap area's position.");
}, "Snapping the root scroller after smooth scrolling should affect the\
visual viewport offset.");
</script>