Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / LayoutTests / fast / scroll-behavior / resources / scroll-interruption-test.js
blob26bc88f291fecd3c783d4331edffc92d5e80d894
1 // A SmoothScrollInterruptionTest verifies that in-progress smooth scrolls
2 // stop when interrupted by an instant scroll, another smooth scroll, a
3 // touch scroll, or a mouse wheel scroll.
4 //
5 // The only SmoothScrollInerruptionTest method that should be called by
6 // outside code is run().
7 //
8 // Creates a SmoothScrollInterruptionTest with arguments:
9 // scrollElement - Element being scrolled.
10 // innerPoint - Absolute position (expressed as a dictionary with x and y fields)
11 //              of a point inside |scrollElement|, that can be used as the location
12 //              of input events that trigger scrolls on |scrollElement|.
13 // targets - A dictionary whose members y_min, y_mid, and y_max should be
14 //           y co-ordinates that are far enough apart from each other that a
15 //           smooth scroll between any pair of them will be non-trivial (that
16 //           is, take multiple frames to finish), and should be such that
17 //           y_min < y_mid < y_max.
18 // jsScroll - Callback that takes a y co-ordinate and executes a js-driven
19 //            smooth scroll to that y co-ordinate.
20 function SmoothScrollInterruptionTest(scrollElement, innerPoint, targets, jsScroll) {
21     this.scrollElement = scrollElement;
22     this.innerPoint = innerPoint;
23     this.scrollStartPoint = targets.y_mid;
24     this.scrollEndPoint = targets.y_max;
25     this.scrollNewEndpoint = targets.y_min;
26     this.jsScroll = jsScroll;
28     this.testCases = [];
29     this.testCases.push(new SmoothScrollInterruptionTestCase(interruptWithInstantScroll, verifyScrollInterruptedByInstantScroll, "instant scroll"));
30     this.testCases.push(new SmoothScrollInterruptionTestCase(interruptWithSmoothScroll, verifyScrollInterruptedBySmoothScroll, "smooth scroll"));
31     this.testCases.push(new SmoothScrollInterruptionTestCase(interruptWithTouchScroll, verifyScrollInterruptedByInputDrivenScroll, "touch scroll"));
32     this.testCases.push(new SmoothScrollInterruptionTestCase(interruptWithWheelScroll, verifyScrollInterruptedByInputDrivenScroll, "wheel scroll"));
34     this.currentTestCase = 0;
37 SmoothScrollInterruptionTest.prototype.startNextTestCase = function() {
38     if (this.currentTestCase >= this.testCases.length) {
39         this.allTestCasesComplete();
40         return;
41     }
43     var testCase = this.testCases[this.currentTestCase];
44     this.asyncTest = async_test(testCase.description);
46     var scrollElement = this.scrollElement;
47     var scrollStartPoint = this.scrollStartPoint;
49     scrollElement.scrollTop = scrollStartPoint;
50     window.requestAnimationFrame(this.performSmoothScroll.bind(this));
53 SmoothScrollInterruptionTest.prototype.performSmoothScroll = function() {
54     var testCase = this.testCases[this.currentTestCase];
55     var scrollElement = this.scrollElement;
56     var scrollStartPoint = this.scrollStartPoint;
58     this.jsScroll(this.scrollEndPoint);
59     this.asyncTest.step(function() {
60         assert_equals(scrollElement.scrollTop, scrollStartPoint);
61     });
63     if (scrollElement.scrollTop == this.scrollEndPoint) {
64         // We've instant-scrolled, and failed the assert above.
65         this.testCaseComplete();
66         return;
67     }
69     window.requestAnimationFrame(this.waitForSmoothScrollStart.bind(this));
72 SmoothScrollInterruptionTest.prototype.waitForSmoothScrollStart = function() {
73     if (this.scrollElement.scrollTop == this.scrollStartPoint) {
74         window.requestAnimationFrame(this.waitForSmoothScrollStart.bind(this));
75         return;
76     }
78     var testCase = this.testCases[this.currentTestCase];
79     testCase.interruptSmoothScroll(this);
80     window.requestAnimationFrame(testCase.verifyScrollInterrupted.bind(testCase, this, this.testCaseComplete.bind(this)));
83 SmoothScrollInterruptionTest.prototype.testCaseComplete = function() {
84     this.asyncTest.done();
86     this.currentTestCase++;
87     this.startNextTestCase();
90 SmoothScrollInterruptionTest.prototype.run = function() {
91     setup({explicit_done: true, explicit_timeout: true});
92     this.startNextTestCase();
95 SmoothScrollInterruptionTest.prototype.allTestCasesComplete = function() {
96     done();
99 // A SmoothScrollInterruptionTestCase represents a single way of interrupting
100 // a smooth scroll and verifying that the smooth scroll gets canceled.
102 // Creates a SmoothScrollInterruptionTestCase with arguments:
103 // interruptSmoothScoll - Callback that takes a SmoothScrollInterruptionTest,
104 //                        and interrupts the on-going smooth scroll.
105 // verifyScrollInterrupted - Callback that takes a SmoothScrollInterruptionTest,
106 //                           a |verificationComplete| callback, and a timestamp,
107 //                           verifies (possibly asynchronously) that the smooth
108 //                           scroll has been superseded by the interruption, and
109 //                           then calls |verificationComplete|.
110 // description - String describing this test case.
111 function SmoothScrollInterruptionTestCase(interruptSmoothScroll, verifyScrollInterrupted, description) {
112     this.interruptSmoothScroll = interruptSmoothScroll;
113     this.verifyScrollInterrupted = verifyScrollInterrupted;
114     this.description = description;
118 function interruptWithInstantScroll(smoothScrollTest) {
119     smoothScrollTest.scrollElement.scrollTop = smoothScrollTest.scrollNewEndpoint;
120     smoothScrollTest.asyncTest.step(function() {
121         assert_equals(smoothScrollTest.scrollElement.scrollTop, smoothScrollTest.scrollNewEndpoint);
122     });
125 function verifyScrollInterruptedByInstantScroll(smoothScrollTest, verificationComplete) {
126     smoothScrollTest.asyncTest.step(function() {
127         assert_equals(smoothScrollTest.scrollElement.scrollTop, smoothScrollTest.scrollNewEndpoint);
128     });
129     verificationComplete();
132 function interruptWithSmoothScroll(smoothScrollTest) {
133     smoothScrollTest.jsScroll(smoothScrollTest.scrollNewEndpoint);
134     smoothScrollTest.asyncTest.step(function() {
135         assert_not_equals(smoothScrollTest.scrollElement.scrollTop, smoothScrollTest.scrollNewEndpoint);
136     });
138     this.scrollInterruptionPoint = smoothScrollTest.scrollElement.scrollTop;
141 function verifyScrollInterruptedBySmoothScroll(smoothScrollTest, verificationComplete) {
142     var currentPosition = smoothScrollTest.scrollElement.scrollTop;
144     if (currentPosition < this.scrollInterruptionPoint && currentPosition >= smoothScrollTest.scrollNewEndpoint) {
145         verificationComplete();
146     } else {
147         window.requestAnimationFrame(this.verifyScrollInterrupted.bind(this, smoothScrollTest, verificationComplete));
148     }
151 function interruptWithTouchScroll(smoothScrollTest) {
152     if (window.eventSender) {
153         window.eventSender.gestureScrollBegin(smoothScrollTest.innerPoint.x, smoothScrollTest.innerPoint.y);
154         window.eventSender.gestureScrollUpdate(0, -10);
155         window.eventSender.gestureScrollEnd(0, 0);
156     } else {
157         document.write("This test does not work in manual mode.");
158     }
161 function verifyScrollInterruptedByInputDrivenScroll(smoothScrollTest, verificationComplete, timestamp) {
162     var currentPosition = smoothScrollTest.scrollElement.scrollTop;
164     if (this.previousPosition && this.previousPosition == currentPosition) {
165         // Ensure that the animation has really stopped, not that we just have
166         // two frames that are so close together that the animation only seems to
167         // have stopped.
168         if (timestamp - this.previousTimestamp > 16) {
169             verificationComplete();
170         } else {
171             window.requestAnimationFrame(this.verifyScrollInterrupted.bind(this, smoothScrollTest, verificationComplete));
172         }
174         return;
175     }
177     this.previousPosition = currentPosition;
178     this.previousTimestamp = timestamp;
179     smoothScrollTest.asyncTest.step(function() {
180         assert_not_equals(currentPosition, smoothScrollTest.scrollEndPoint);
181     });
182     window.requestAnimationFrame(this.verifyScrollInterrupted.bind(this, smoothScrollTest, verificationComplete));
185 function interruptWithWheelScroll(smoothScrollTest) {
186     if (window.eventSender) {
187         window.eventSender.mouseMoveTo(smoothScrollTest.innerPoint.x, smoothScrollTest.innerPoint.y);
188         window.eventSender.mouseScrollBy(0, -10);
189     } else {
190         document.write("This test does not work in manual mode.");
191     }