1 // A ScrollBehaviorTest runs a set of ScrollBehaviorTestCases. The only
2 // ScrollBehaviorTest method that should be called by external code is run().
4 // Creates a ScrollBehaviorTest with arguments:
5 // scrollElement - Element being scrolled.
6 // scrollEventTarget - Target for scroll events for |scrollElement|.
7 // testsCases - Array of ScrollBehaviorTestCases.
8 // getEndPosition - Callback that takes a test case and start position, and
9 // returns the corresponding end position (where positions
10 // are dictionaries with x and y fields).
11 // jsScroll - Callback that takes a test case and executes the corresponding
12 // js-driven scroll (e.g. by setting scrollLeft/scrollTop or by
13 // calling scroll, scrollTo, or scrollBy). This should assume that
14 // scrollElement's scroll-behavior CSS property has already been
16 function ScrollBehaviorTest(scrollElement,
21 this.scrollElement = scrollElement;
22 this.scrollEventTarget = scrollEventTarget;
23 this.testCases = testCases;
24 this.currentTestCase = 0;
25 this.getEndPosition = getEndPosition;
26 this.jsScroll = jsScroll;
29 ScrollBehaviorTest.prototype.scrollListener = function(testCase) {
30 if (testCase.waitForEnd) {
31 if (this.scrollElement.scrollLeft == testCase.endX && this.scrollElement.scrollTop == testCase.endY)
32 this.testCaseComplete();
36 // Wait for an intermediate frame, then instant-scroll to the end state.
37 if ((this.scrollElement.scrollLeft != testCase.startX || this.scrollElement.scrollTop != testCase.startY) &&
38 (this.scrollElement.scrollLeft != testCase.endX || this.scrollElement.scrollTop != testCase.endY)) {
39 this.scrollElement.scrollLeft = {x: testCase.endX, behavior: "instant"};
40 this.scrollElement.scrollTop = {y: testCase.endY, behavior: "instant"};
41 this.testCaseComplete();
45 ScrollBehaviorTest.prototype.startNextTestCase = function() {
46 if (this.currentTestCase >= this.testCases.length) {
47 this.allTestCasesComplete();
50 var testCase = this.testCases[this.currentTestCase];
51 var isSmoothTest = (testCase.js == "smooth" || (testCase.css == "smooth" && testCase.js != "instant"));
53 this.asyncTest = async_test("Scroll x:" + testCase.x + ", y:" + testCase.y + ", smooth:" + isSmoothTest);
55 var currentPosition = {};
56 currentPosition.x = this.scrollElement.scrollLeft;
57 currentPosition.y = this.scrollElement.scrollTop;
58 var endPosition = this.getEndPosition(testCase, currentPosition);
59 testCase.setStartPosition(currentPosition);
60 testCase.setEndPosition(endPosition);
62 this.scrollElement.style.scrollBehavior = testCase.css;
63 this.jsScroll(testCase);
65 var scrollElement = this.scrollElement;
67 this.asyncTest.step(function() {
68 assert_equals(scrollElement.scrollLeft + ", " + scrollElement.scrollTop, testCase.startX + ", " + testCase.startY);
70 if (scrollElement.scrollLeft == testCase.endX && scrollElement.scrollTop == testCase.endY) {
71 // We've instant-scrolled. This means we've already failed the assert above, and will never
72 // reach an intermediate frame. End the test case now to avoid hanging while waiting for an
73 // intermediate frame.
74 this.testCaseComplete();
76 testCase.scrollListener = this.scrollListener.bind(this, testCase);
77 this.scrollEventTarget.addEventListener("scroll", testCase.scrollListener);
80 this.asyncTest.step(function() {
81 assert_equals(scrollElement.scrollLeft + ", " + scrollElement.scrollTop, testCase.endX + ", " + testCase.endY);
83 this.testCaseComplete();
87 ScrollBehaviorTest.prototype.testCaseComplete = function() {
88 var currentScrollListener = this.testCases[this.currentTestCase].scrollListener;
89 if (currentScrollListener) {
90 this.scrollEventTarget.removeEventListener("scroll", currentScrollListener);
92 this.asyncTest.done();
94 this.currentTestCase++;
95 this.startNextTestCase();
98 ScrollBehaviorTest.prototype.run = function() {
99 setup({explicit_done: true});
100 this.startNextTestCase();
103 ScrollBehaviorTest.prototype.allTestCasesComplete = function() {
108 // A ScrollBehaviorTestCase represents a single scroll.
110 // Creates a ScrollBehaviorTestCase. |testData| is a dictionary with fields:
111 // css - Value of scroll-behavior CSS property.
112 // js - (optional) Value of scroll behavior used in javascript.
113 // x, y - Coordinates to be used when carrying out the scroll.
114 // waitForEnd - (must be provided for smooth scrolls) Whether the test runner should
115 // wait until the scroll is complete, rather than only waiting until
116 // the scroll is underway.
117 function ScrollBehaviorTestCase(testData) {
118 this.js = testData.js;
119 this.css = testData.css;
120 this.waitForEnd = testData.waitForEnd;
125 ScrollBehaviorTestCase.prototype.setStartPosition = function(startPosition) {
126 this.startX = startPosition.x;
127 this.startY = startPosition.y;
130 ScrollBehaviorTestCase.prototype.setEndPosition = function(endPosition) {
131 this.endX = endPosition.x;
132 this.endY = endPosition.y;