Commit 37ba4241 authored by Lan Wei's avatar Lan Wei Committed by Commit Bot

Reland "Rewrite scroll interruption tests into browser tests"

After we finish the scroll unification, the scrolls happens mainly on
the compositor thread, and the scroll code in the main thread will be
removed. eventSender sends the scroll events to main thread, so it
would not work after the scroll unification. We rewrite below tests
fast/scroll-behavior/main-frame-interrupted-scroll.html,
fast/scroll-behavior/overflow-interrupted-scroll.html and
fast/scroll-behavior/subframe-interrupted-scroll.html into browser tests
because we cannot guarantee that the scroll arrives before the animation
completes.

I disable the test when disable_threaded_scrolling_ is false, because we
do not know what is the final scrollTop value.

TBR=bokan@chromium.org

Change-Id: Ia9b68cd2e0c4f198968aa56482698c0c02edf452
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2441205Reviewed-by: default avatarLan Wei <lanwei@chromium.org>
Commit-Queue: Lan Wei <lanwei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812517}
parent 1864e6e3
...@@ -1049,6 +1049,7 @@ test("content_browsertests") { ...@@ -1049,6 +1049,7 @@ test("content_browsertests") {
"../browser/renderer_host/input/interaction_mq_dynamic_browsertest.cc", "../browser/renderer_host/input/interaction_mq_dynamic_browsertest.cc",
"../browser/renderer_host/input/main_thread_event_queue_browsertest.cc", "../browser/renderer_host/input/main_thread_event_queue_browsertest.cc",
"../browser/renderer_host/input/mouse_latency_browsertest.cc", "../browser/renderer_host/input/mouse_latency_browsertest.cc",
"../browser/renderer_host/input/scroll_behavior_browsertest.cc",
"../browser/renderer_host/input/scroll_latency_browsertest.cc", "../browser/renderer_host/input/scroll_latency_browsertest.cc",
"../browser/renderer_host/input/synthetic_input_browsertest.cc", "../browser/renderer_host/input/synthetic_input_browsertest.cc",
"../browser/renderer_host/input/touch_action_browsertest.cc", "../browser/renderer_host/input/touch_action_browsertest.cc",
......
<!DOCTYPE html>
<html>
<head>
<style>
#content {
width: 1000px;
height: 10000px;
background-color: blue;
}
</style>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="resources/scroll-interruption-test.js"></script>
<script type="text/javascript">
function jsScroll(y) {
window.scrollTo({top: y, behavior: 'smooth'});
}
function doTest() {
const targets = {y_min: 40, y_mid: 3500, y_max: 7000};
const innerPoint = {x: 100, y: 100};
var scrollInterruptionTest = new SmoothScrollInterruptionTest(document.scrollingElement,
innerPoint,
targets,
jsScroll);
scrollInterruptionTest.run();
}
window.addEventListener('load', doTest, false);
</script>
</head>
<body>
<p>Test that interrupting a smooth scroll on the main frame works with both scroll behaviors and with input</p>
<div id="content"></div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style>
#container {
width: 200px;
height: 200px;
overflow: scroll;
}
#content {
width: 7500px;
height: 7500px;
background-color: blue;
}
</style>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="resources/scroll-interruption-test.js"></script>
<script type="text/javascript">
function jsScroll(y) {
document.getElementById('container').scrollTo({top: y, behavior: 'smooth'});
}
function doTest() {
const targets = {y_min: 40, y_mid: 3500, y_max: 7000};
const innerPoint = {x: 100, y: 100};
var element = document.getElementById('container');
var scrollInterruptionTest = new SmoothScrollInterruptionTest(element,
innerPoint,
targets,
jsScroll);
scrollInterruptionTest.run();
}
window.addEventListener('load', doTest, false);
</script>
</head>
<body>
<p>Test that interrupting a smooth scroll on an overflow:scroll element works with both scroll behaviors and with input</p>
<div id="container">
<div id="content"></div>
</div>
</body>
</html>
// A SmoothScrollInterruptionTest verifies that in-progress smooth scrolls
// stop when interrupted by an instant scroll, another smooth scroll, a
// touch scroll, or a mouse wheel scroll.
//
// The only SmoothScrollInerruptionTest method that should be called by
// outside code is run().
//
// Creates a SmoothScrollInterruptionTest with arguments:
// scrollElement - Element being scrolled.
// innerPoint - Absolute position (expressed as a dictionary with x and y fields)
// of a point inside |scrollElement|, that can be used as the location
// of input events that trigger scrolls on |scrollElement|.
// targets - A dictionary whose members y_min, y_mid, and y_max should be
// y co-ordinates that are far enough apart from each other that a
// smooth scroll between any pair of them will be non-trivial (that
// is, take multiple frames to finish), and should be such that
// y_min < y_mid < y_max.
// jsScroll - Callback that takes a y co-ordinate and executes a js-driven
// smooth scroll to that y co-ordinate.
function SmoothScrollInterruptionTest(scrollElement, innerPoint, targets, jsScroll) {
this.scrollElement = scrollElement;
this.innerPoint = innerPoint;
this.scrollStartPoint = targets.y_mid;
this.scrollEndPoint = targets.y_max;
this.scrollNewEndpoint = targets.y_min;
this.jsScroll = jsScroll;
this.testCases = [];
this.testCases.push(new SmoothScrollInterruptionTestCase(interruptWithInstantScroll, verifyScrollInterruptedByInstantScroll, "instant scroll"));
this.testCases.push(new SmoothScrollInterruptionTestCase(interruptWithSmoothScroll, verifyScrollInterruptedBySmoothScroll, "smooth scroll"));
this.testCases.push(new SmoothScrollInterruptionTestCase(interruptWithTouchScroll, verifyScrollInterruptedByInputDrivenScroll, "touch scroll"));
this.testCases.push(new SmoothScrollInterruptionTestCase(interruptWithWheelScroll, verifyScrollInterruptedByInputDrivenScroll, "wheel scroll"));
this.currentTestCase = 0;
}
SmoothScrollInterruptionTest.prototype.startNextTestCase = function() {
if (this.currentTestCase >= this.testCases.length) {
this.allTestCasesComplete();
return;
}
var testCase = this.testCases[this.currentTestCase];
this.asyncTest = async_test(testCase.description);
var scrollElement = this.scrollElement;
var scrollStartPoint = this.scrollStartPoint;
scrollElement.scrollTop = scrollStartPoint;
window.requestAnimationFrame(this.waitForSyncScroll.bind(this));
}
SmoothScrollInterruptionTest.prototype.waitForSyncScroll = function() {
// Wait until cc has received the commit from main with the scrollStartPoint.
if (this.scrollElement.scrollTop != this.scrollStartPoint) {
// TODO(flackr): There seems to be a bug in that we shouldn't have to
// reapply the scroll position when cancelling a smooth scroll.
// https://crbug.com/667477
this.scrollElement.scrollTop = this.scrollStartPoint;
window.requestAnimationFrame(this.waitForSyncScroll.bind(this));
return;
}
this.performSmoothScroll();
}
SmoothScrollInterruptionTest.prototype.performSmoothScroll = function() {
var testCase = this.testCases[this.currentTestCase];
var scrollElement = this.scrollElement;
var scrollStartPoint = this.scrollStartPoint;
this.jsScroll(this.scrollEndPoint);
this.asyncTest.step(function() {
assert_equals(scrollElement.scrollTop, scrollStartPoint);
});
if (scrollElement.scrollTop == this.scrollEndPoint) {
// We've instant-scrolled, and failed the assert above.
this.testCaseComplete();
return;
}
window.requestAnimationFrame(this.waitForSmoothScrollStart.bind(this));
}
SmoothScrollInterruptionTest.prototype.waitForSmoothScrollStart = function() {
if (this.scrollElement.scrollTop == this.scrollStartPoint) {
window.requestAnimationFrame(this.waitForSmoothScrollStart.bind(this));
return;
}
var testCase = this.testCases[this.currentTestCase];
testCase.interruptSmoothScroll(this);
window.requestAnimationFrame(testCase.verifyScrollInterrupted.bind(testCase, this, this.testCaseComplete.bind(this)));
}
SmoothScrollInterruptionTest.prototype.testCaseComplete = function() {
this.asyncTest.done();
this.currentTestCase++;
this.startNextTestCase();
}
SmoothScrollInterruptionTest.prototype.run = function() {
setup({explicit_done: true, explicit_timeout: true});
this.startNextTestCase();
}
SmoothScrollInterruptionTest.prototype.allTestCasesComplete = function() {
done();
}
// A SmoothScrollInterruptionTestCase represents a single way of interrupting
// a smooth scroll and verifying that the smooth scroll gets canceled.
//
// Creates a SmoothScrollInterruptionTestCase with arguments:
// interruptSmoothScoll - Callback that takes a SmoothScrollInterruptionTest,
// and interrupts the on-going smooth scroll.
// verifyScrollInterrupted - Callback that takes a SmoothScrollInterruptionTest,
// a |verificationComplete| callback, and a timestamp,
// verifies (possibly asynchronously) that the smooth
// scroll has been superseded by the interruption, and
// then calls |verificationComplete|.
// description - String describing this test case.
function SmoothScrollInterruptionTestCase(interruptSmoothScroll, verifyScrollInterrupted, description) {
this.interruptSmoothScroll = interruptSmoothScroll;
this.verifyScrollInterrupted = verifyScrollInterrupted;
this.description = description;
}
function interruptWithInstantScroll(smoothScrollTest) {
smoothScrollTest.scrollElement.scrollTop = smoothScrollTest.scrollNewEndpoint;
smoothScrollTest.asyncTest.step(function() {
assert_equals(smoothScrollTest.scrollElement.scrollTop, smoothScrollTest.scrollNewEndpoint);
});
}
function verifyScrollInterruptedByInstantScroll(smoothScrollTest, verificationComplete) {
smoothScrollTest.asyncTest.step(function() {
assert_equals(smoothScrollTest.scrollElement.scrollTop, smoothScrollTest.scrollNewEndpoint);
});
verificationComplete();
}
function interruptWithSmoothScroll(smoothScrollTest) {
smoothScrollTest.jsScroll(smoothScrollTest.scrollNewEndpoint);
smoothScrollTest.asyncTest.step(function() {
assert_not_equals(smoothScrollTest.scrollElement.scrollTop, smoothScrollTest.scrollNewEndpoint);
});
this.scrollInterruptionPoint = smoothScrollTest.scrollElement.scrollTop;
}
function verifyScrollInterruptedBySmoothScroll(smoothScrollTest, verificationComplete) {
var currentPosition = smoothScrollTest.scrollElement.scrollTop;
if (currentPosition < this.scrollInterruptionPoint && currentPosition >= smoothScrollTest.scrollNewEndpoint) {
verificationComplete();
} else {
window.requestAnimationFrame(this.verifyScrollInterrupted.bind(this, smoothScrollTest, verificationComplete));
}
}
function interruptWithTouchScroll(smoothScrollTest) {
if (window.eventSender) {
eventSender.gestureScrollBegin(smoothScrollTest.innerPoint.x, smoothScrollTest.innerPoint.y);
eventSender.gestureScrollUpdate(0, -10);
eventSender.gestureScrollEnd(0, 0);
} else {
document.write("This test does not work in manual mode.");
}
}
function verifyScrollInterruptedByInputDrivenScroll(smoothScrollTest, verificationComplete, timestamp) {
var currentPosition = smoothScrollTest.scrollElement.scrollTop;
if (this.previousPosition && this.previousPosition == currentPosition) {
// Ensure that the animation has really stopped, not that we just have
// two frames that are so close together that the animation only seems to
// have stopped.
if (timestamp - this.previousTimestamp > 16) {
verificationComplete();
} else {
window.requestAnimationFrame(this.verifyScrollInterrupted.bind(this, smoothScrollTest, verificationComplete));
}
return;
}
this.previousPosition = currentPosition;
this.previousTimestamp = timestamp;
smoothScrollTest.asyncTest.step(function() {
assert_not_equals(currentPosition, smoothScrollTest.scrollEndPoint);
});
window.requestAnimationFrame(this.verifyScrollInterrupted.bind(this, smoothScrollTest, verificationComplete));
}
function interruptWithWheelScroll(smoothScrollTest) {
if (window.eventSender) {
eventSender.mouseMoveTo(smoothScrollTest.innerPoint.x, smoothScrollTest.innerPoint.y);
eventSender.mouseScrollBy(0, -10);
} else {
document.write("This test does not work in manual mode.");
}
}
<!DOCTYPE html>
<html>
<head>
<style>
#subframe {
width: 200px;
height: 200px;
}
</style>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="resources/scroll-interruption-test.js"></script>
<script type="text/javascript">
function jsScroll(y) {
var subframe = document.getElementById('subframe');
subframe.contentWindow.scrollTo({top: y, behavior: 'smooth'});
}
function doTest()
{
const targets = {y_min: 40, y_mid: 3500, y_max: 7000};
const innerPoint = {x: 100, y: 100}
var subframeScrollingElement = document.getElementById('subframe').contentDocument.scrollingElement;
var scrollInterruptionTest = new SmoothScrollInterruptionTest(subframeScrollingElement,
innerPoint,
targets,
jsScroll);
scrollInterruptionTest.run();
}
window.addEventListener('load', doTest, false);
</script>
</head>
<body>
<p>Test that interrupting a smooth scroll on a subframe works with both scroll behaviors and with input</p>
<iframe id="subframe" src="resources/large-subframe.html"></iframe>
</body>
</html>
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