Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(318)

Side by Side Diff: LayoutTests/transitions/resources/transition-test-helpers.js

Issue 15738009: Beat the transition tests with a sanity stick. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Pass presubmit. Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /* This is the helper function to run transition tests:
2
3 Test page requirements:
4 - The body must contain an empty div with id "result"
5 - Call this function directly from the <script> inside the test page
6
7 Function parameters:
8 expected [required]: an array of arrays defining a set of CSS properties tha t must have given values at specific times (see below)
9 callback [optional]: a function to be executed just before the test starts ( none by default)
10
11 Each sub-array must contain these items in this order:
12 - the time in seconds at which to snapshot the CSS property
13 - the id of the element on which to get the CSS property value
14 - the name of the CSS property to get [1]
15 - the expected value for the CSS property
16 - the tolerance to use when comparing the effective CSS property value with its expected value
17
18 [1] If the CSS property name is "-webkit-transform", expected value must be an array of 1 or more numbers corresponding to the matrix elements,
19 or a string which will be compared directly (useful if the expected value is "none")
20 If the CSS property name is "-webkit-transform.N", expected value must be a number corresponding to the Nth element of the matrix
21
22 */
23
24 const usePauseAPI = true;
25 const dontUsePauseAPI = false;
26
27 const shouldBeTransitioning = true;
28 const shouldNotBeTransitioning = false;
29
30 function roundNumber(num, decimalPlaces)
31 {
32 return Math.round(num * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPla ces);
33 }
34
35 function isCloseEnough(actual, desired, tolerance)
36 {
37 var diff = Math.abs(actual - desired);
38 return diff <= tolerance;
39 }
40
41 function isShadow(property)
42 {
43 return (property == '-webkit-box-shadow' || property == 'text-shadow');
44 }
45
46 function getShadowXY(cssValue)
47 {
48 var text = cssValue.cssText;
49 // Shadow cssText looks like "rgb(0, 0, 255) 0px -3px 10px 0px"
50 var shadowPositionRegExp = /\)\s*(-?\d+)px\s*(-?\d+)px/;
51 var result = shadowPositionRegExp.exec(text);
52 return [parseInt(result[1]), parseInt(result[2])];
53 }
54
55 function compareRGB(rgb, expected, tolerance)
56 {
57 return (isCloseEnough(parseInt(rgb[0]), expected[0], tolerance) &&
58 isCloseEnough(parseInt(rgb[1]), expected[1], tolerance) &&
59 isCloseEnough(parseInt(rgb[2]), expected[2], tolerance));
60 }
61
62 function parseCrossFade(s)
63 {
64 var matches = s.match("-webkit-cross-fade\\((.*)\\s*,\\s*(.*)\\s*,\\s*(.*)\\ )");
65
66 if (!matches)
67 return null;
68
69 return {"from": matches[1], "to": matches[2], "percent": parseFloat(matches[ 3])}
70 }
71
72 function checkExpectedValue(expected, index)
73 {
74 var time = expected[index][0];
75 var elementId = expected[index][1];
76 var property = expected[index][2];
77 var expectedValue = expected[index][3];
78 var tolerance = expected[index][4];
79 var postCompletionCallback = expected[index][5];
80
81 var computedValue;
82 var pass = false;
83 var transformRegExp = /^-webkit-transform(\.\d+)?$/;
84 if (transformRegExp.test(property)) {
85 computedValue = window.getComputedStyle(document.getElementById(elementI d)).webkitTransform;
86 if (typeof expectedValue == "string")
87 pass = (computedValue == expectedValue);
88 else if (typeof expectedValue == "number") {
89 var m = computedValue.split("(");
90 var m = m[1].split(",");
91 pass = isCloseEnough(parseFloat(m[parseInt(property.substring(18))]) , expectedValue, tolerance);
92 } else {
93 var m = computedValue.split("(");
94 var m = m[1].split(",");
95 for (i = 0; i < expectedValue.length; ++i) {
96 pass = isCloseEnough(parseFloat(m[i]), expectedValue[i], toleran ce);
97 if (!pass)
98 break;
99 }
100 }
101 } else if (property == "fill" || property == "stroke") {
102 computedValue = window.getComputedStyle(document.getElementById(elementI d)).getPropertyCSSValue(property).rgbColor;
103 if (compareRGB([computedValue.red.cssText, computedValue.green.cssText, computedValue.blue.cssText], expectedValue, tolerance))
104 pass = true;
105 else {
106 // We failed. Make sure computed value is something we can read in t he error message
107 computedValue = window.getComputedStyle(document.getElementById(elem entId)).getPropertyCSSValue(property).cssText;
108 }
109 } else if (property == "stop-color" || property == "flood-color" || property == "lighting-color") {
110 computedValue = window.getComputedStyle(document.getElementById(elementI d)).getPropertyCSSValue(property);
111 // The computedValue cssText is rgb(num, num, num)
112 var components = computedValue.cssText.split("(")[1].split(")")[0].split (",");
113 if (compareRGB(components, expectedValue, tolerance))
114 pass = true;
115 else {
116 // We failed. Make sure computed value is something we can read in t he error message
117 computedValue = computedValue.cssText;
118 }
119 } else if (property == "lineHeight") {
120 computedValue = parseInt(window.getComputedStyle(document.getElementById (elementId)).lineHeight);
121 pass = isCloseEnough(computedValue, expectedValue, tolerance);
122 } else if (property == "background-image"
123 || property == "border-image-source"
124 || property == "border-image"
125 || property == "list-style-image"
126 || property == "-webkit-mask-image"
127 || property == "-webkit-mask-box-image") {
128 if (property == "border-image" || property == "-webkit-mask-image" || pr operty == "-webkit-mask-box-image")
129 property += "-source";
130
131 computedValue = window.getComputedStyle(document.getElementById(elementI d)).getPropertyCSSValue(property).cssText;
132 computedCrossFade = parseCrossFade(computedValue);
133
134 if (!computedCrossFade) {
135 pass = false;
136 } else {
137 pass = isCloseEnough(computedCrossFade.percent, expectedValue, toler ance);
138 }
139 } else {
140 var computedStyle = window.getComputedStyle(document.getElementById(elem entId)).getPropertyCSSValue(property);
141 if (computedStyle.cssValueType == CSSValue.CSS_VALUE_LIST) {
142 var values = [];
143 for (var i = 0; i < computedStyle.length; ++i) {
144 switch (computedStyle[i].cssValueType) {
145 case CSSValue.CSS_PRIMITIVE_VALUE:
146 values.push(computedStyle[i].getFloatValue(CSSPrimitiveValue .CSS_NUMBER));
147 break;
148 case CSSValue.CSS_CUSTOM:
149 // arbitrarily pick shadow-x and shadow-y
150 if (isShadow) {
151 var shadowXY = getShadowXY(computedStyle[i]);
152 values.push(shadowXY[0]);
153 values.push(shadowXY[1]);
154 } else
155 values.push(computedStyle[i].cssText);
156 break;
157 }
158 }
159 computedValue = values.join(',');
160 pass = true;
161 for (var i = 0; i < values.length; ++i)
162 pass &= isCloseEnough(values[i], expectedValue[i], tolerance);
163 } else if (computedStyle.cssValueType == CSSValue.CSS_PRIMITIVE_VALUE) {
164 switch (computedStyle.primitiveType) {
165 case CSSPrimitiveValue.CSS_STRING:
166 case CSSPrimitiveValue.CSS_IDENT:
167 computedValue = computedStyle.getStringValue();
168 pass = computedValue == expectedValue;
169 break;
170 case CSSPrimitiveValue.CSS_RGBCOLOR:
171 var rgbColor = computedStyle.getRGBColorValue();
172 computedValue = [rgbColor.red.getFloatValue(CSSPrimitiveValu e.CSS_NUMBER),
173 rgbColor.green.getFloatValue(CSSPrimitiveVa lue.CSS_NUMBER),
174 rgbColor.blue.getFloatValue(CSSPrimitiveVal ue.CSS_NUMBER)]; // alpha is not exposed to JS
175 pass = true;
176 for (var i = 0; i < 3; ++i)
177 pass &= isCloseEnough(computedValue[i], expectedValue[i] , tolerance);
178 break;
179 case CSSPrimitiveValue.CSS_RECT:
180 computedValue = computedStyle.getRectValue();
181 computedValue = [computedValue.top.getFloatValue(CSSPrimitiv eValue.CSS_NUMBER),
182 computedValue.right.getFloatValue(CSSPrimit iveValue.CSS_NUMBER),
183 computedValue.bottom.getFloatValue(CSSPrimi tiveValue.CSS_NUMBER),
184 computedValue.left.getFloatValue(CSSPrimiti veValue.CSS_NUMBER)];
185 pass = true;
186 for (var i = 0; i < 4; ++i)
187 pass &= isCloseEnough(computedValue[i], expectedValue[i ], tolerance);
188 break;
189 case CSSPrimitiveValue.CSS_PERCENTAGE:
190 computedValue = parseFloat(computedStyle.cssText);
191 pass = isCloseEnough(computedValue, expectedValue, tolerance );
192 break;
193 default:
194 computedValue = computedStyle.getFloatValue(CSSPrimitiveValu e.CSS_NUMBER);
195 pass = isCloseEnough(computedValue, expectedValue, tolerance );
196 }
197 }
198 }
199
200 if (pass)
201 result += "PASS - \"" + property + "\" property for \"" + elementId + "\ " element at " + time + "s saw something close to: " + expectedValue + "<br>";
202 else
203 result += "FAIL - \"" + property + "\" property for \"" + elementId + "\ " element at " + time + "s expected: " + expectedValue + " but saw: " + computed Value + "<br>";
204
205 if (postCompletionCallback)
206 result += postCompletionCallback();
207 }
208
209 function endTest()
210 {
211 document.getElementById('result').innerHTML = result;
212
213 if (window.testRunner)
214 testRunner.notifyDone();
215 }
216
217 function checkExpectedValueCallback(expected, index)
218 {
219 return function() { checkExpectedValue(expected, index); };
220 }
221
222 function runTest(expected, usePauseAPI)
223 {
224 var maxTime = 0;
225 for (var i = 0; i < expected.length; ++i) {
226 var time = expected[i][0];
227 var elementId = expected[i][1];
228 var property = expected[i][2];
229 if (!property.indexOf("-webkit-transform."))
230 property = "-webkit-transform";
231
232 var tryToPauseTransition = expected[i][6];
233 if (tryToPauseTransition === undefined)
234 tryToPauseTransition = shouldBeTransitioning;
235
236 if (hasPauseTransitionAPI && usePauseAPI) {
237 if (tryToPauseTransition) {
238 var element = document.getElementById(elementId);
239 internals.pauseAnimations(time);
240 }
241 checkExpectedValue(expected, i);
242 } else {
243 if (time > maxTime)
244 maxTime = time;
245
246 window.setTimeout(checkExpectedValueCallback(expected, i), time * 10 00);
247 }
248 }
249
250 if (maxTime > 0)
251 window.setTimeout(endTest, maxTime * 1000 + 50);
252 else
253 endTest();
254 }
255
256 function waitForAnimationStart(callback, delay)
257 {
258 var delayTimeout = delay ? 1000 * delay + 10 : 0;
259 // Why the two setTimeouts? Well, for hardware animations we need to ensure that the hardware animation
260 // has started before we try to pause it, and timers fire before animations get committed in the runloop.
261 window.setTimeout(function() {
262 window.setTimeout(function() {
263 callback();
264 }, 0);
265 }, delayTimeout);
266 }
267
268 function startTest(expected, usePauseAPI, callback)
269 {
270 if (callback)
271 callback();
272
273 waitForAnimationStart(function() {
274 runTest(expected, usePauseAPI);
275 });
276 }
277
278 var result = "";
279 var hasPauseTransitionAPI;
280
281 function runTransitionTest(expected, callback, usePauseAPI, doPixelTest)
282 {
283 hasPauseTransitionAPI = 'internals' in window;
284
285 if (window.testRunner) {
286 if (!doPixelTest)
287 testRunner.dumpAsText();
288 testRunner.waitUntilDone();
289 }
290
291 if (!expected)
292 throw("Expected results are missing!");
293
294 window.addEventListener("load", function() { startTest(expected, usePauseAPI , callback); }, false);
295 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698