Index: LayoutTests/fast/scroll-behavior/resources/scroll-interruption-test.js |
diff --git a/LayoutTests/fast/scroll-behavior/resources/scroll-interruption-test.js b/LayoutTests/fast/scroll-behavior/resources/scroll-interruption-test.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c27dc9b30318d13fae3e97e0643de29a26c65e31 |
--- /dev/null |
+++ b/LayoutTests/fast/scroll-behavior/resources/scroll-interruption-test.js |
@@ -0,0 +1,190 @@ |
+// 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."); |
+ } |
+} |