Commit b00300ae authored by ajuma@chromium.org's avatar ajuma@chromium.org

Scroll interruption tests for CSSOM View smooth scroll

This adds a SmoothScrollInterruptionTest class and tests using
this class.

BUG=243871

Review URL: https://codereview.chromium.org/398043005

git-svn-id: svn://svn.chromium.org/blink/trunk@178387 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 8770c5ff
......@@ -684,6 +684,8 @@ crbug.com/374643 [ Mac ] fast/text-autosizing/tables/table-with-inline-block.htm
crbug.com/335710 virtual/gpu/canvas/philip/tests/2d.text.draw.fontface.notinpage.html [ Pass Failure ]
crbug.com/335710 canvas/philip/tests/2d.text.draw.fontface.notinpage.html [ Pass Failure ]
crbug.com/243871 [ Mac Win ] fast/scroll-behavior/listbox-interrupted-scroll.html [ NeedsRebaseline ]
# Started failing after r162705.
crbug.com/324369 compositing/video/video-reflection.html [ Failure ]
crbug.com/324369 virtual/softwarecompositing/video/video-reflection.html [ Failure ]
......
Test that interrupting a smooth scroll on a listbox works with both scroll behaviors and with input
This is a testharness.js-based test.
FAIL instant scroll assert_equals: expected 3400 but got 6800
FAIL smooth scroll assert_equals: expected 3400 but got 6800
FAIL touch scroll assert_equals: expected 3400 but got 6800
FAIL wheel scroll assert_equals: expected 3400 but got 6800
Harness: the test ran to completion.
<!DOCTYPE html>
<html>
<head>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="resources/scroll-interruption-test.js"></script>
<script type="text/javascript">
const numItems = 500;
function jsScroll(y) {
document.getElementById('listbox').scrollTop = {y: y, behavior: 'smooth'};
}
function initializeContents(listbox) {
for (var i = 0; i < numItems; i++) {
var option = document.createElement('option');
option.appendChild(document.createTextNode(i));
listbox.appendChild(option);
}
}
function initializeTest(indexTargets, targets, innerPoint, listbox) {
var itemHeight = (listbox.scrollHeight - listbox.clientHeight) / (numItems - listbox.size);
// Convert from listbox item index to scroll offset.
targets.y_min = indexTargets.index_min * itemHeight;
targets.y_mid = indexTargets.index_mid * itemHeight;
targets.y_max = indexTargets.index_max * itemHeight;
var boundingRect = listbox.getBoundingClientRect();
innerPoint.x = (boundingRect.left + boundingRect.right)/2;
innerPoint.y = (boundingRect.top + boundingRect.bottom)/2;
}
function doTest() {
var indexTargets = {index_min: 3, index_mid: 200, index_max: 400};
var targets = {};
var innerPoint = {};
var element = document.getElementById('listbox');
initializeContents(element);
initializeTest(indexTargets, targets, innerPoint, element);
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 a listbox works with both scroll behaviors and with input</p>
<select size="4" id="listbox"></select>
</body>
</html>
Test that interrupting a smooth scroll on the main frame works with both scroll behaviors and with input
This is a testharness.js-based test.
FAIL instant scroll assert_equals: expected 3500 but got 7000
FAIL smooth scroll assert_equals: expected 3500 but got 7000
FAIL touch scroll assert_equals: expected 3500 but got 7000
FAIL wheel scroll assert_equals: expected 3500 but got 7000
Harness: the test ran to completion.
<!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) {
var currentX = document.documentElement.scrollTop;
window.scrollTo(currentX, 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.documentElement,
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>
Test that interrupting a smooth scroll on an overflow:scroll element works with both scroll behaviors and with input
This is a testharness.js-based test.
FAIL instant scroll assert_equals: expected 3500 but got 7000
FAIL smooth scroll assert_equals: expected 3500 but got 7000
FAIL touch scroll assert_equals: expected 3500 but got 7000
FAIL wheel scroll assert_equals: expected 3500 but got 7000
Harness: the test ran to completion.
<!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').scrollTop = {y: 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;
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 scrollElement = this.scrollElement;
var scrollEndPoint = this.scrollEndPoint;
this.asyncTest.step(function() {
assert_not_equals(scrollElement.scrollTop, scrollEndPoint);
});
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});
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) {
window.eventSender.gestureScrollBegin(smoothScrollTest.innerPoint.x, smoothScrollTest.innerPoint.y);
window.eventSender.gestureScrollUpdate(0, -10);
window.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) {
window.eventSender.mouseMoveTo(smoothScrollTest.innerPoint.x, smoothScrollTest.innerPoint.y);
window.eventSender.mouseScrollBy(0, -10);
} else {
document.write("This test does not work in manual mode.");
}
}
Test that interrupting a smooth scroll on a subframe works with both scroll behaviors and with input
This is a testharness.js-based test.
FAIL instant scroll assert_equals: expected 3500 but got 7000
FAIL smooth scroll assert_equals: expected 3500 but got 7000
FAIL touch scroll assert_equals: expected 3500 but got 7000
FAIL wheel scroll assert_equals: expected 3500 but got 7000
Harness: the test ran to completion.
<!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');
var currentX = subframe.contentDocument.documentElement.scrollTop;
subframe.contentWindow.scrollTo(currentX, y, {behavior: 'smooth'});
}
function doTest()
{
const targets = {y_min: 40, y_mid: 3500, y_max: 7000};
const innerPoint = {x: 100, y: 100}
var subframeDocumentElement = document.getElementById('subframe').contentDocument.documentElement;
var scrollInterruptionTest = new SmoothScrollInterruptionTest(subframeDocumentElement,
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