Commit 3af420d0 authored by David Bokan's avatar David Bokan Committed by Commit Bot

Fix pinch zoom tests on Mac

These tests:
virtual/threaded/fast/events/pinch/pinch-zoom-into-center.html
virtual/threaded/fast/events/pinch/pinch-zoom-pan-position-fixed.html
pinch-zoom-pan-within-zoomed-viewport.html

were breaking because Mac doesn't support touch events and the pinch
was being done using touch. I've changed to use a touchpad source as
this doesn't affect the meaning of the tests as well as some minor
cleanups.

While here, I also rewrote a number of tests to use gesture-util.js and
the async/await style which is more readable and easier to produce
non-flaky tests.

TBR=nasko@chromium.org

Bug: 854199,873435,877494,877361
Change-Id: I19f6e199fea694013d3dceaeb32c881059301f1d
Reviewed-on: https://chromium-review.googlesource.com/1185238
Commit-Queue: David Bokan <bokan@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Reviewed-by: default avatarNasko Oskov <nasko@chromium.org>
Reviewed-by: default avatarSahel Sharify <sahel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585871}
parent 2150cdb8
...@@ -1757,10 +1757,7 @@ crbug.com/613672 [ Mac ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoo ...@@ -1757,10 +1757,7 @@ crbug.com/613672 [ Mac ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoo
crbug.com/613672 [ Mac ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-out-slow-desktop.html [ Skip ] crbug.com/613672 [ Mac ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-out-slow-desktop.html [ Skip ]
crbug.com/613672 [ Mac ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-desktop.html [ Skip ] crbug.com/613672 [ Mac ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-desktop.html [ Skip ]
# These tests are currently flaky. # This test are currently flaky.
crbug.com/840017 virtual/threaded/fast/events/pinch/pinch-zoom-into-center.html [ Failure Pass ]
crbug.com/840017 virtual/threaded/fast/events/pinch/pinch-zoom-pan-position-fixed.html [ Failure Pass ]
crbug.com/840017 virtual/threaded/fast/events/pinch/pinch-zoom-pan-within-zoomed-viewport.html [ Failure Pass ]
crbug.com/877361 virtual/threaded/fast/events/pinch/gesture-pinch-zoom-scroll-bubble.html [ Timeout Pass ] crbug.com/877361 virtual/threaded/fast/events/pinch/gesture-pinch-zoom-scroll-bubble.html [ Timeout Pass ]
crbug.com/522648 fast/events/touch/compositor-touch-hit-rects-iframes.html [ Crash Failure Pass ] crbug.com/522648 fast/events/touch/compositor-touch-hit-rects-iframes.html [ Crash Failure Pass ]
......
<!DOCTYPE html> <!DOCTYPE html>
<script src="../../resources/testharness.js"></script> <script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script> <script src="../../resources/testharnessreport.js"></script>
<script src="../../resources/gesture-util.js"></script>
<style> <style>
.outer { .outer {
height: 400px; height: 400px;
...@@ -43,128 +44,114 @@ function setUpForContainer() { ...@@ -43,128 +44,114 @@ function setUpForContainer() {
assert_equals(container.scrollLeft, 100); assert_equals(container.scrollLeft, 100);
} }
function smoothScroll(pixels_to_scroll, start_x, start_y, gesture_source_type, direction, speed_in_pixels_s) { async function test_boundary_prevents_y(source_type) {
return new Promise((resolve, reject) => {
chrome.gpuBenchmarking.smoothScrollBy(pixels_to_scroll, resolve, start_x, start_y, gesture_source_type, direction, speed_in_pixels_s);
});
}
function waitForAnimationEnd() {
const MAX_FRAME = 500;
var last_changed_frame = 0;
var last_window_x = window.scrollX;
var last_window_y = window.scrollY;
var last_container_x = container.scrollLeft;
var last_container_y = container.scrollTop;
return new Promise((resolve, reject) => {
function tick(frames) {
// We requestAnimationFrame either for 500 frames or until 5 frames with
// no change have been observed.
if (frames >= MAX_FRAME || frames - last_changed_frame > 5) {
resolve();
} else {
if (window.scrollX != last_window_x ||
window.scrollY != last_window_y ||
container.scrollLeft != last_container_x ||
container.scrollTop != last_container_y) {
last_changed_frame = frames;
last_window_x = window.scrollX;
last_window_y = window.scrollY;
last_container_x = container.scrollLeft;
last_container_y = container.scrollTop;
}
requestAnimationFrame(tick.bind(this, frames + 1));
}
}
tick(0);
});
}
function test_boundary_prevents_y(source_type) {
container.style.overscrollBehaviorX = 'auto'; container.style.overscrollBehaviorX = 'auto';
container.style.overscrollBehaviorY = 'none'; container.style.overscrollBehaviorY = 'none';
setUpForWindow(); setUpForWindow();
return smoothScroll(200, 200, 500, source_type, "up", 4000) await waitForCompositorCommit();
.then(waitForAnimationEnd)
.then(() => { const x = 200;
assert_equals(window.scrollY, 100);}) const y = 500;
.then( const distance = 200;
smoothScroll.bind(this, 200, 200, 500, source_type, "left", 4000))
.then(waitForAnimationEnd) await smoothScroll(distance, x, y, source_type, 'up', SPEED_INSTANT);
.then(() => { await waitForAnimationEnd(() => { return window.scrollY; }, 500, 5);
assert_equals(window.scrollX, 0); assert_equals(window.scrollY, 100);
}); assert_equals(container.scrollTop, 0);
await smoothScroll(distance, x, y, source_type, 'left', SPEED_INSTANT);
// TODO(bokan): Wait for 10 frames without change. This is a bit long but
// otherwise we affect the next test because window.scrollX goes to 0 while
// the animation is still ticking. SPEED_INSTANT isn't as instant as it
// should be.
await waitForAnimationEnd(() => { return window.scrollX; }, 500, 10);
assert_equals(window.scrollX, 0);
assert_equals(container.scrollLeft, 0);
} }
function test_boundary_prevents_x(source_type) { async function test_boundary_prevents_x(source_type) {
container.style.overscrollBehaviorX = 'none'; container.style.overscrollBehaviorX = 'none';
container.style.overscrollBehaviorY = 'auto'; container.style.overscrollBehaviorY = 'auto';
setUpForWindow(); setUpForWindow();
return smoothScroll(200, 200, 500, source_type, 'left', 4000) await waitForCompositorCommit();
.then(waitForAnimationEnd)
.then(() => { const x = 200;
assert_equals(window.scrollX, 100);}) const y = 500;
.then( const distance = 200;
smoothScroll.bind(this, 200, 200, 500, source_type, 'up', 4000))
.then(waitForAnimationEnd) await smoothScroll(distance, x, y, source_type, 'left', SPEED_INSTANT);
.then(() => { await waitForAnimationEnd(() => { return window.scrollX; }, 500, 5);
assert_equals(window.scrollY, 0); assert_equals(window.scrollX, 100);
}); assert_equals(container.scrollTop, 0);
await smoothScroll(distance, x, y, source_type, 'up', SPEED_INSTANT);
await waitForAnimationEnd(() => { return window.scrollY; }, 500, 10);
assert_equals(window.scrollY, 0);
assert_equals(container.scrollLeft, 0);
} }
function test_boundary_allows_inner(source_type) { async function test_boundary_allows_inner(source_type) {
container.style.overscrollBehaviorX = 'none'; container.style.overscrollBehaviorX = 'none';
container.style.overscrollBehaviorY = 'none'; container.style.overscrollBehaviorY = 'none';
setUpForContainer(); setUpForContainer();
return smoothScroll(200, 200, 500, source_type, 'upleft', 4000) await waitForCompositorCommit();
.then(waitForAnimationEnd)
.then(() => { const x = 200;
assert_equals(container.scrollTop, 0); const y = 500;
assert_equals(container.scrollLeft, 0); const distance = 200;
});
await smoothScroll(distance, x, y, source_type, "upleft", SPEED_INSTANT);
await waitForAnimationEnd(() => { return container.scrollLeft; }, 500, 5);
await waitForAnimationEnd(() => { return container.scrollTop; }, 500, 10);
assert_equals(container.scrollTop, 0);
assert_equals(container.scrollLeft, 0);
} }
function test_boundary_on_nonscrollable_allows_propagation(source_type) { async function test_boundary_on_nonscrollable_allows_propagation(source_type) {
non_scrollable.style.overscrollBehaviorX = 'none'; non_scrollable.style.overscrollBehaviorX = 'none';
non_scrollable.style.overscrollBehaviorY = 'none'; non_scrollable.style.overscrollBehaviorY = 'none';
window.scrollTo(0, 0); window.scrollTo(0, 0);
return smoothScroll(200, 200, 300, source_type, 'right', 4000) await waitForCompositorCommit();
.then(waitForAnimationEnd)
.then(() => { const x = 200;
assert_greater_than(window.scrollX, 100);}) const y = 300;
.then( const distance = 200;
smoothScroll.bind(this, 200, 200, 300, source_type, 'down', 4000))
.then(waitForAnimationEnd) await smoothScroll(distance, x, y, source_type, "right", SPEED_INSTANT);
.then(() => { await waitForAnimationEnd(() => { return window.scrollX; }, 500, 5);
assert_greater_than(window.scrollY, 100); assert_greater_than(window.scrollX, 100);
});
await smoothScroll(distance, x, y, source_type, "down", SPEED_INSTANT);
await waitForAnimationEnd(() => { return window.scrollY; }, 500, 10);
assert_greater_than(window.scrollY, 100);
assert_equals(non_scrollable.scrollTop, 0);
assert_equals(non_scrollable.scrollLeft, 0);
} }
const TOUCH_SOURCE_TYPE = 1; // TOUCH_INPUT from synthetic_gesture_params.h
const WHEEL_SOURCE_TYPE = 2; // TOUCH_INPUT from synthetic_gesture_params.h
promise_test(t => { promise_test(t => {
return test_boundary_prevents_y(WHEEL_SOURCE_TYPE); return test_boundary_prevents_y(GestureSourceType.MOUSE_INPUT);
}, 'overscroll-behavior-y: none should only prevent scroll propagation on y axis with: wheel.'); }, 'overscroll-behavior-y: none should only prevent scroll propagation on y axis with: wheel.');
promise_test(t => { promise_test(t => {
return test_boundary_prevents_x(WHEEL_SOURCE_TYPE); return test_boundary_prevents_x(GestureSourceType.MOUSE_INPUT);
}, 'overscroll-behavior-x: none should only prevent scroll propagation on x axis with: wheel.'); }, 'overscroll-behavior-x: none should only prevent scroll propagation on x axis with: wheel.');
promise_test(t => { promise_test(t => {
return test_boundary_allows_inner(WHEEL_SOURCE_TYPE); return test_boundary_allows_inner(GestureSourceType.MOUSE_INPUT);
}, 'overscroll-behavior should not affect scrolling inside the applied container with: wheel.'); }, 'overscroll-behavior should not affect scrolling inside the applied container with: wheel.');
promise_test(t => { promise_test(t => {
return test_boundary_on_nonscrollable_allows_propagation(WHEEL_SOURCE_TYPE); return test_boundary_on_nonscrollable_allows_propagation(GestureSourceType.MOUSE_INPUT);
}, 'overscroll-behavior on non-scrollable area should not affect scroll propagation with: wheel.'); }, 'overscroll-behavior on non-scrollable area should not affect scroll propagation with: wheel.');
const IS_MAC = navigator.platform.indexOf('Mac') == 0; const IS_MAC = navigator.platform.indexOf('Mac') == 0;
if (!IS_MAC) { if (!IS_MAC) {
promise_test(t => { promise_test(t => {
return test_boundary_prevents_y(TOUCH_SOURCE_TYPE); return test_boundary_prevents_y(GestureSourceType.TOUCH_INPUT);
}, 'overscroll-behavior-y: none should only prevent scroll propagation on y axis with: touch.'); }, 'overscroll-behavior-y: none should only prevent scroll propagation on y axis with: touch.');
promise_test(t => { promise_test(t => {
return test_boundary_prevents_x(TOUCH_SOURCE_TYPE); return test_boundary_prevents_x(GestureSourceType.TOUCH_INPUT);
}, 'overscroll-behavior-x: none should only prevent scroll propagation on x axis with: touch.'); }, 'overscroll-behavior-x: none should only prevent scroll propagation on x axis with: touch.');
promise_test(t => { promise_test(t => {
return test_boundary_on_nonscrollable_allows_propagation(TOUCH_SOURCE_TYPE); return test_boundary_on_nonscrollable_allows_propagation(GestureSourceType.TOUCH_INPUT);
}, 'overscroll-behavior on non-scrollable area should not affect scroll propagation with: touch.'); }, 'overscroll-behavior on non-scrollable area should not affect scroll propagation with: touch.');
} }
</script> </script>
<!doctype html>
<style>
.scroll {
overflow: auto;
width: 100px;
height: 100px;
will-change: transform;
}
.scrolled-content {
width: 50px;
height: 1000px;
background-image: linear-gradient(green, red);
}
</style>
It should not be possible to scroll this content:<br>
<div class="scroll">
<div class="scrolled-content"></div>
</div>
<!doctype html> <!doctype html>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src='../../../resources/gesture-util.js'></script>
<style> <style>
.scroll { .scroll {
overflow: auto; overflow: auto;
...@@ -26,25 +29,15 @@ ...@@ -26,25 +29,15 @@
} }
</style> </style>
It should not be possible to scroll this content:<br> It should not be possible to scroll this content:<br>
<div class="scroll"> <div id="scroller" class="scroll">
<div class="scrolled-content"></div> <div class="scrolled-content"></div>
</div> </div>
<div id="animated-overlap"></div> <div id="animated-overlap"></div>
<script> <script>
testRunner.waitUntilDone(); promise_test(async t => {
// Wait for the animation to advance. await waitForCompositorCommit();
requestAnimationFrame(function() { await smoothScroll(20, 50, 50, GestureSourceType.MOUSE_INPUT, 'down', SPEED_INSTANT);
const GESTURE_SOURCE_TYPE = 2; // MOUSE_INPUT from synthetic_gesture_params.h await waitForCompositorCommit();
chrome.gpuBenchmarking.smoothScrollBy( assert_equals(document.getElementById('scroller').scrollTop, 0);
1000, }, 'Invisible composited animation prevents scroll');
function() {
testRunner.notifyDone();
},
50 /* start_x */,
50 /* start_y */,
GESTURE_SOURCE_TYPE,
'down',
20000 /* speed */,
false /* precise_scrolling_deltas */);
});
</script> </script>
...@@ -6,105 +6,48 @@ ...@@ -6,105 +6,48 @@
<script> <script>
var EPSILON = 0.001; var EPSILON = 0.001;
var MOUSE_INPUT = 2; // Gesture source type from synthetic_gesture_params.h
var t = async_test("Scrolling with a scaled visual viewport"); var t = async_test("Scrolling with a scaled visual viewport");
function waitForVisualViewportOffset(x, y) { // This test verifies scrolling of the page while pinch-zoomed in. We ensure
return new Promise(function(resolve, reject) { // that the scrolls target the correct (visual/layout) viewport and that
function pollForOffset(frames) { // bubbling between the two works correctly.
if (Math.abs(window.visualViewport.offsetLeft - x) <= EPSILON && window.onload = t.step_func(async function() {
Math.abs(window.visualViewport.offsetTop - y) <= EPSILON) { await waitForCompositorCommit();
resolve(); await pinchBy(2, 400, 599, SPEED_INSTANT, GestureSourceType.TOUCHPAD_INPUT);
} else if (frames > 500) { await waitForCompositorCommit();
reject(); assert_approx_equals(window.visualViewport.scale, 2.0, EPSILON);
} else { assert_approx_equals(window.visualViewport.offsetLeft, 200, EPSILON);
window.requestAnimationFrame(pollForOffset.bind(this, frames + 1)); assert_approx_equals(window.visualViewport.offsetTop, 300, EPSILON);
} // We're already within |EPSILON| of the desired offset, but we'll set it
} // here to avoid rounding issues later in the test.
pollForOffset(0); window.internals.setVisualViewportOffset(200, 300);
}); await waitForCompositorCommit();
}
// Scroll down, this will affect only the layout viewport.
await smoothScroll(2, 400, 300, GestureSourceType.TOUCHPAD_INPUT, "down", SPEED_INSTANT);
await waitForCompositorCommit();
assert_equals(window.scrollY, 1);
// Scroll right, this will affect only the visual viewport.
await smoothScroll(2, 400, 300, GestureSourceType.TOUCHPAD_INPUT, "right", SPEED_INSTANT);
await waitForCompositorCommit();
assert_equals(window.visualViewport.offsetLeft, 201);
// Move the visual viewport up by a pixel so that the next gesture will
// bubble.
window.internals.setVisualViewportOffset(201, 299);
await waitForCompositorCommit();
// Scroll back diagonally. This will affect both viewports by bubbling from
// the visual to the layout.
await smoothScroll(4, 400, 300, GestureSourceType.TOUCHPAD_INPUT, "downleft", SPEED_INSTANT);
await waitForCompositorCommit();
assert_equals(window.scrollY, 2);
assert_equals(window.visualViewport.offsetTop, 300);
assert_equals(window.visualViewport.offsetLeft, 199);
function testVerticalScroll() {
// Do a purely vertical scroll. This will scroll contents only.
chrome.gpuBenchmarking.smoothScrollBy(
2,
t.step_func(function () {
waitForVisualViewportOffset(200, 251).then(
t.step_func(testHorizontalScroll),
t.step_func_done(function() {
assert_unreached('Timeout waiting for vertical scroll');
}));
}),
undefined /* start_x */,
undefined /* start_y */,
MOUSE_INPUT,
'down',
undefined /* speed */);
}
function testHorizontalScroll() {
// Do a purely horizontal scroll. This will change the visual viewport offset
// only.
chrome.gpuBenchmarking.smoothScrollBy(
2,
t.step_func(function () {
waitForVisualViewportOffset(201, 251).then(
t.step_func(testDiagonalScroll),
t.step_func_done(function() {
assert_unreached('Timeout waiting for horizontal scroll');
}));
}),
undefined /* start_x */,
undefined /* start_y */,
MOUSE_INPUT,
'right',
undefined /* speed */);
}
function testDiagonalScroll() {
// Do a diagonal scroll. This will scroll the contents, and then bubble the
// result up to the visual viewport, where it will change the pinch
// virtual viewport offset.
chrome.gpuBenchmarking.smoothScrollBy(
4,
t.step_func(function () {
waitForVisualViewportOffset(199, 249).then(
t.done.bind(t),
t.step_func_done(function() {
assert_unreached('Timeout waiting for diagonal scroll');
}));
}),
undefined /* start_x */,
undefined /* start_y */,
MOUSE_INPUT,
'upleft',
undefined /* speed */);
}
// TODO: This test just verifies that scrollX and scrollY end up with the right
// values after a scroll. It does not verify whether these values are coming
// from content scroll or from viewport moving. This should be added.
if (window.chrome && chrome.gpuBenchmarking && window.internals) {
window.onload = t.step_func(function() {
chrome.gpuBenchmarking.pinchBy(2.0, 400, 500, t.step_func(function() {
assert_approx_equals(
window.visualViewport.scale, 2.0, EPSILON);
assert_approx_equals(window.visualViewport.offsetLeft, 200, EPSILON);
assert_approx_equals(window.visualViewport.offsetTop, 250, EPSILON);
// We're already within |EPSILON| of the desired offset, but we'll set it
// here to avoid rounding issues later in the test.
window.internals.setVisualViewportOffset(200, 250);
waitForCompositorCommit().then(testVerticalScroll);
}), undefined /* speed */, MOUSE_INPUT);
});
} else {
t.step(function() {
assert_unreached(
'This test requires chrome.gpuBenchmarking.pinchBy and internals');
});
t.done(); t.done();
} });
</script> </script>
...@@ -61,10 +61,9 @@ ...@@ -61,10 +61,9 @@
// position-fixed elements to move. Scroll down 1.5 screen heights so that // position-fixed elements to move. Scroll down 1.5 screen heights so that
// the visual viewport scrolls down for 0.5 and then the layout viewport // the visual viewport scrolls down for 0.5 and then the layout viewport
// for 1. // for 1.
// TODO(bokan): smoothScroll seems to have an off-by-one.
await waitForCompositorCommit(); await waitForCompositorCommit();
await smoothScroll(1801, 400, 300, GestureSourceType.TOUCH_INPUT, "down", SPEED_INSTANT); await smoothScroll(1800, 400, 300, GestureSourceType.TOUCHPAD_INPUT, "down", SPEED_INSTANT);
await waitFor(() => { return true; }); await waitForCompositorCommit();
testRunner.notifyDone(); testRunner.notifyDone();
} }
......
...@@ -34,10 +34,9 @@ ...@@ -34,10 +34,9 @@
internals.setPageScaleFactor(2); internals.setPageScaleFactor(2);
// Test that panning the visual viewport works when zoomed in. // Test that panning the visual viewport works when zoomed in.
// TODO(bokan): smoothScroll seems to have an off-by-one.
await waitForCompositorCommit(); await waitForCompositorCommit();
await smoothScroll(601, 400, 300, GestureSourceType.TOUCH_INPUT, "down", SPEED_INSTANT); await smoothScroll(600, 400, 300, GestureSourceType.TOUCHPAD_INPUT, "down", SPEED_INSTANT);
await waitFor(() => { return true; }); await waitForCompositorCommit();
testRunner.notifyDone(); testRunner.notifyDone();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment