| OLD | NEW |
| (Empty) |
| 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 locat
ion | |
| 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, jsScro
ll) { | |
| 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; | |
| 27 | |
| 28 this.testCases = []; | |
| 29 this.testCases.push(new SmoothScrollInterruptionTestCase(interruptWithInstan
tScroll, verifyScrollInterruptedByInstantScroll, "instant scroll")); | |
| 30 this.testCases.push(new SmoothScrollInterruptionTestCase(interruptWithSmooth
Scroll, verifyScrollInterruptedBySmoothScroll, "smooth scroll")); | |
| 31 this.testCases.push(new SmoothScrollInterruptionTestCase(interruptWithTouchS
croll, verifyScrollInterruptedByInputDrivenScroll, "touch scroll")); | |
| 32 this.testCases.push(new SmoothScrollInterruptionTestCase(interruptWithWheelS
croll, verifyScrollInterruptedByInputDrivenScroll, "wheel scroll")); | |
| 33 | |
| 34 this.currentTestCase = 0; | |
| 35 } | |
| 36 | |
| 37 SmoothScrollInterruptionTest.prototype.startNextTestCase = function() { | |
| 38 if (this.currentTestCase >= this.testCases.length) { | |
| 39 this.allTestCasesComplete(); | |
| 40 return; | |
| 41 } | |
| 42 | |
| 43 var testCase = this.testCases[this.currentTestCase]; | |
| 44 this.asyncTest = async_test(testCase.description); | |
| 45 | |
| 46 var scrollElement = this.scrollElement; | |
| 47 var scrollStartPoint = this.scrollStartPoint; | |
| 48 | |
| 49 scrollElement.scrollTop = scrollStartPoint; | |
| 50 this.jsScroll(this.scrollEndPoint); | |
| 51 this.asyncTest.step(function() { | |
| 52 assert_equals(scrollElement.scrollTop, scrollStartPoint); | |
| 53 }); | |
| 54 | |
| 55 if (scrollElement.scrollTop == this.scrollEndPoint) { | |
| 56 // We've instant-scrolled, and failed the assert above. | |
| 57 this.testCaseComplete(); | |
| 58 return; | |
| 59 } | |
| 60 | |
| 61 window.requestAnimationFrame(this.waitForSmoothScrollStart.bind(this)); | |
| 62 } | |
| 63 | |
| 64 SmoothScrollInterruptionTest.prototype.waitForSmoothScrollStart = function() { | |
| 65 if (this.scrollElement.scrollTop == this.scrollStartPoint) { | |
| 66 window.requestAnimationFrame(this.waitForSmoothScrollStart.bind(this)); | |
| 67 return; | |
| 68 } | |
| 69 | |
| 70 var scrollElement = this.scrollElement; | |
| 71 var scrollEndPoint = this.scrollEndPoint; | |
| 72 this.asyncTest.step(function() { | |
| 73 assert_not_equals(scrollElement.scrollTop, scrollEndPoint); | |
| 74 }); | |
| 75 | |
| 76 var testCase = this.testCases[this.currentTestCase]; | |
| 77 testCase.interruptSmoothScroll(this); | |
| 78 window.requestAnimationFrame(testCase.verifyScrollInterrupted.bind(testCase,
this, this.testCaseComplete.bind(this))); | |
| 79 } | |
| 80 | |
| 81 SmoothScrollInterruptionTest.prototype.testCaseComplete = function() { | |
| 82 this.asyncTest.done(); | |
| 83 | |
| 84 this.currentTestCase++; | |
| 85 this.startNextTestCase(); | |
| 86 } | |
| 87 | |
| 88 SmoothScrollInterruptionTest.prototype.run = function() { | |
| 89 setup({explicit_done: true}); | |
| 90 this.startNextTestCase(); | |
| 91 } | |
| 92 | |
| 93 SmoothScrollInterruptionTest.prototype.allTestCasesComplete = function() { | |
| 94 done(); | |
| 95 } | |
| 96 | |
| 97 // A SmoothScrollInterruptionTestCase represents a single way of interrupting | |
| 98 // a smooth scroll and verifying that the smooth scroll gets canceled. | |
| 99 // | |
| 100 // Creates a SmoothScrollInterruptionTestCase with arguments: | |
| 101 // interruptSmoothScoll - Callback that takes a SmoothScrollInterruptionTest, | |
| 102 // and interrupts the on-going smooth scroll. | |
| 103 // verifyScrollInterrupted - Callback that takes a SmoothScrollInterruptionTest, | |
| 104 // a |verificationComplete| callback, and a timestamp, | |
| 105 // verifies (possibly asynchronously) that the smooth | |
| 106 // scroll has been superseded by the interruption, and | |
| 107 // then calls |verificationComplete|. | |
| 108 // description - String describing this test case. | |
| 109 function SmoothScrollInterruptionTestCase(interruptSmoothScroll, verifyScrollInt
errupted, description) { | |
| 110 this.interruptSmoothScroll = interruptSmoothScroll; | |
| 111 this.verifyScrollInterrupted = verifyScrollInterrupted; | |
| 112 this.description = description; | |
| 113 } | |
| 114 | |
| 115 | |
| 116 function interruptWithInstantScroll(smoothScrollTest) { | |
| 117 smoothScrollTest.scrollElement.scrollTop = smoothScrollTest.scrollNewEndpoin
t; | |
| 118 smoothScrollTest.asyncTest.step(function() { | |
| 119 assert_equals(smoothScrollTest.scrollElement.scrollTop, smoothScrollTest
.scrollNewEndpoint); | |
| 120 }); | |
| 121 } | |
| 122 | |
| 123 function verifyScrollInterruptedByInstantScroll(smoothScrollTest, verificationCo
mplete) { | |
| 124 smoothScrollTest.asyncTest.step(function() { | |
| 125 assert_equals(smoothScrollTest.scrollElement.scrollTop, smoothScrollTest
.scrollNewEndpoint); | |
| 126 }); | |
| 127 verificationComplete(); | |
| 128 } | |
| 129 | |
| 130 function interruptWithSmoothScroll(smoothScrollTest) { | |
| 131 smoothScrollTest.jsScroll(smoothScrollTest.scrollNewEndpoint); | |
| 132 smoothScrollTest.asyncTest.step(function() { | |
| 133 assert_not_equals(smoothScrollTest.scrollElement.scrollTop, smoothScroll
Test.scrollNewEndpoint); | |
| 134 }); | |
| 135 | |
| 136 this.scrollInterruptionPoint = smoothScrollTest.scrollElement.scrollTop; | |
| 137 } | |
| 138 | |
| 139 function verifyScrollInterruptedBySmoothScroll(smoothScrollTest, verificationCom
plete) { | |
| 140 var currentPosition = smoothScrollTest.scrollElement.scrollTop; | |
| 141 | |
| 142 if (currentPosition < this.scrollInterruptionPoint && currentPosition > smoo
thScrollTest.scrollNewEndpoint) { | |
| 143 verificationComplete(); | |
| 144 } else { | |
| 145 window.requestAnimationFrame(this.verifyScrollInterrupted.bind(this, smo
othScrollTest, verificationComplete)); | |
| 146 } | |
| 147 } | |
| 148 | |
| 149 function interruptWithTouchScroll(smoothScrollTest) { | |
| 150 if (window.eventSender) { | |
| 151 window.eventSender.gestureScrollBegin(smoothScrollTest.innerPoint.x, smo
othScrollTest.innerPoint.y); | |
| 152 window.eventSender.gestureScrollUpdate(0, -10); | |
| 153 window.eventSender.gestureScrollEnd(0, 0); | |
| 154 } else { | |
| 155 document.write("This test does not work in manual mode."); | |
| 156 } | |
| 157 } | |
| 158 | |
| 159 function verifyScrollInterruptedByInputDrivenScroll(smoothScrollTest, verificati
onComplete, timestamp) { | |
| 160 var currentPosition = smoothScrollTest.scrollElement.scrollTop; | |
| 161 | |
| 162 if (this.previousPosition && this.previousPosition == currentPosition) { | |
| 163 // Ensure that the animation has really stopped, not that we just have | |
| 164 // two frames that are so close together that the animation only seems t
o | |
| 165 // have stopped. | |
| 166 if (timestamp - this.previousTimestamp > 16) { | |
| 167 verificationComplete(); | |
| 168 } else { | |
| 169 window.requestAnimationFrame(this.verifyScrollInterrupted.bind(this,
smoothScrollTest, verificationComplete)); | |
| 170 } | |
| 171 | |
| 172 return; | |
| 173 } | |
| 174 | |
| 175 this.previousPosition = currentPosition; | |
| 176 this.previousTimestamp = timestamp; | |
| 177 smoothScrollTest.asyncTest.step(function() { | |
| 178 assert_not_equals(currentPosition, smoothScrollTest.scrollEndPoint); | |
| 179 }); | |
| 180 window.requestAnimationFrame(this.verifyScrollInterrupted.bind(this, smoothS
crollTest, verificationComplete)); | |
| 181 } | |
| 182 | |
| 183 function interruptWithWheelScroll(smoothScrollTest) { | |
| 184 if (window.eventSender) { | |
| 185 window.eventSender.mouseMoveTo(smoothScrollTest.innerPoint.x, smoothScro
llTest.innerPoint.y); | |
| 186 window.eventSender.mouseScrollBy(0, -10); | |
| 187 } else { | |
| 188 document.write("This test does not work in manual mode."); | |
| 189 } | |
| 190 } | |
| OLD | NEW |