OLD | NEW |
1 /* This is the helper function to run animation tests: | 1 /* This is the helper script for animation tests: |
2 | 2 |
3 Test page requirements: | 3 Test page requirements: |
4 - The body must contain an empty div with id "result" | 4 - The body must contain an empty div with id "result" |
5 - Call this function directly from the <script> inside the test page | 5 - Call this function directly from the <script> inside the test page |
6 | 6 |
7 Function parameters: | 7 runAnimationTest and runTransitionTest 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) | 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 callbacks [optional]: a function to be executed immediately after animation
starts; | 9 callbacks [optional]: a function to be executed immediately after animation
starts; |
10 or, an object in the form {time: function} containing
functions to be | 10 or, an object in the form {time: function} containing
functions to be |
11 called at the specified times (in seconds) during anim
ation. | 11 called at the specified times (in seconds) during anim
ation. |
12 trigger [optional]: a function to trigger transitions at the start of the te
st | 12 trigger [optional]: a function to be executed just before the test starts (n
one by default) |
| 13 doPixelTest [optional]: whether to dump pixels during the test (false by def
ault) |
| 14 disablePauseAnimationAPI [optional]: whether to disable the pause API and ru
n a RAF-based test (false by default) |
13 | 15 |
14 Each sub-array must contain these items in this order: | 16 Each sub-array must contain these items in this order: |
15 - the time in seconds at which to snapshot the CSS property | 17 - the time in seconds at which to snapshot the CSS property |
16 - the id of the element on which to get the CSS property value [1] | 18 - the id of the element on which to get the CSS property value [1] |
17 - the name of the CSS property to get [2] | 19 - the name of the CSS property to get [2] |
18 - the expected value for the CSS property | 20 - the expected value for the CSS property [3] |
19 - the tolerance to use when comparing the effective CSS property value with
its expected value | 21 - the tolerance to use when comparing the effective CSS property value with
its expected value |
20 | 22 |
21 [1] If a single string is passed, it is the id of the element to test. If an
array with 2 elements is passed they | 23 [1] If a single string is passed, it is the id of the element to test. If an
array with 2 elements is passed they |
22 are the ids of 2 elements, whose values are compared for equality. In this c
ase the expected value is ignored | 24 are the ids of 2 elements, whose values are compared for equality. In this c
ase the expected value is ignored |
23 but the tolerance is used in the comparison. | 25 but the tolerance is used in the comparison. |
24 | 26 |
25 If a string with a '.' is passed, this is an element in an iframe. The strin
g before the dot is the iframe id | 27 If a string with a '.' is passed, this is an element in an iframe. The strin
g before the dot is the iframe id |
26 and the string after the dot is the element name in that iframe. | 28 and the string after the dot is the element name in that iframe. |
27 | 29 |
28 [2] If the CSS property name is "webkitTransform", expected value must be an
array of 1 or more numbers corresponding to the matrix elements, | 30 [2] Appending ".N" to the CSS property name (e.g. "transform.N") makes |
29 or a string which will be compared directly (useful if the expected value is
"none") | 31 us only check the Nth numeric substring of the computed style. |
30 If the CSS property name is "webkitTransform.N", expected value must be a nu
mber corresponding to the Nth element of the matrix | 32 |
| 33 [3] The expected value has several supported formats. If an array is given, |
| 34 we extract numeric substrings from the computed style and compare the |
| 35 number of these as well as the values. If a number is given, we treat it as |
| 36 an array of length one. If a string is given, we compare numeric substrings |
| 37 with the computed style with the given tolerance and also the remaining |
| 38 non-numeric substrings. |
31 | 39 |
32 */ | 40 */ |
33 | 41 |
34 // Set to true to log debug information in failing tests. Note that these logs | 42 // Set to true to log debug information in failing tests. Note that these logs |
35 // contain timestamps, so are non-deterministic and will introduce flakiness if | 43 // contain timestamps, so are non-deterministic and will introduce flakiness if |
36 // any expected results include failures. | 44 // any expected results include failures. |
37 var ENABLE_ERROR_LOGGING = false; | 45 var ENABLE_ERROR_LOGGING = false; |
38 | 46 |
39 function isCloseEnough(actual, desired, tolerance) | 47 function isCloseEnough(actual, expected, tolerance) |
40 { | 48 { |
41 if (typeof desired === "string") | 49 return Math.abs(actual - expected) <= tolerance; |
42 return actual === desired; | |
43 var diff = Math.abs(actual - desired); | |
44 return diff <= tolerance; | |
45 } | 50 } |
46 | 51 |
47 function roundNumber(num, decimalPlaces) | 52 function roundNumber(num, decimalPlaces) |
48 { | 53 { |
49 return Math.round(num * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPla
ces); | 54 return Math.round(num * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPla
ces); |
50 } | 55 } |
51 | 56 |
52 function matrixStringToArray(s) | |
53 { | |
54 if (s == "none") | |
55 return [ 1, 0, 0, 1, 0, 0 ]; | |
56 var m = s.split("("); | |
57 m = m[1].split(")"); | |
58 return m[0].split(","); | |
59 } | |
60 | |
61 function parseCrossFade(s) | |
62 { | |
63 var matches = s.match("-webkit-cross-fade\\((.*)\\s*,\\s*(.*)\\s*,\\s*(.*)\\
)"); | |
64 | |
65 if (!matches) | |
66 return null; | |
67 | |
68 return {"from": matches[1], "to": matches[2], "percent": parseFloat(matches[
3])} | |
69 } | |
70 | |
71 function parseBasicShape(s) | |
72 { | |
73 var functionParse = s.match(/(\w+)\((.+)\)/); | |
74 if (!functionParse) | |
75 return null; | |
76 | |
77 var name = functionParse[1]; | |
78 var params = functionParse[2]; | |
79 params = params.split(/\s*[,\s]\s*/); | |
80 | |
81 // Parse numbers and normalize percentages | |
82 for (var i = 0; i < params.length; ++i) { | |
83 var param = params[i]; | |
84 if (!/$\d/.test(param)) | |
85 continue; | |
86 params[i] = parseFloat(params[i]); | |
87 if (param.indexOf('%') != -1) | |
88 params[i] = params[i] / 100; | |
89 } | |
90 | |
91 return {"shape": name, "params": params}; | |
92 } | |
93 | |
94 function basicShapeParametersMatch(paramList1, paramList2, tolerance) | |
95 { | |
96 if (paramList1.shape != paramList2.shape | |
97 || paramList1.params.length != paramList2.params.length) | |
98 return false; | |
99 for (var i = 0; i < paramList1.params.length; ++i) { | |
100 var param1 = paramList1.params[i], | |
101 param2 = paramList2.params[i]; | |
102 var match = isCloseEnough(param1, param2, tolerance); | |
103 if (!match) | |
104 return false; | |
105 } | |
106 return true; | |
107 } | |
108 | |
109 // Return an array of numeric filter params in 0-1. | |
110 function getFilterParameters(s) | |
111 { | |
112 var filterResult = s.match(/(\w+)\((.+)\)/); | |
113 if (!filterResult) | |
114 throw new Error("There's no filter in \"" + s + "\""); | |
115 var filterParams = filterResult[2]; | |
116 var paramList = filterParams.split(' '); // FIXME: the spec may allow comma
separation at some point. | |
117 | |
118 // Normalize percentage values. | |
119 for (var i = 0; i < paramList.length; ++i) { | |
120 var param = paramList[i]; | |
121 paramList[i] = parseFloat(paramList[i]); | |
122 if (param.indexOf('%') != -1) | |
123 paramList[i] = paramList[i] / 100; | |
124 } | |
125 | |
126 return paramList; | |
127 } | |
128 | |
129 function filterParametersMatch(paramList1, paramList2, tolerance) | |
130 { | |
131 if (paramList1.length != paramList2.length) | |
132 return false; | |
133 for (var i = 0; i < paramList1.length; ++i) { | |
134 var param1 = paramList1[i], | |
135 param2 = paramList2[i]; | |
136 var match = isCloseEnough(param1, param2, tolerance); | |
137 if (!match) | |
138 return false; | |
139 } | |
140 return true; | |
141 } | |
142 | |
143 function checkExpectedValue(expected, index) | 57 function checkExpectedValue(expected, index) |
144 { | 58 { |
145 log('Checking expectation: ' + JSON.stringify(expected[index])); | 59 log('Checking expectation: ' + JSON.stringify(expected[index])); |
146 var time = expected[index][0]; | 60 var time = expected[index][0]; |
147 var elementId = expected[index][1]; | 61 var elementId = expected[index][1]; |
148 var property = expected[index][2]; | 62 var specifiedProperty = expected[index][2]; |
149 var expectedValue = expected[index][3]; | 63 var expectedValue = expected[index][3]; |
150 var tolerance = expected[index][4]; | 64 var tolerance = expected[index][4]; |
| 65 var postCompletionCallback = expected[index][5]; |
| 66 |
| 67 var expectedIndex = specifiedProperty.split(".")[1]; |
| 68 var property = specifiedProperty.split(".")[0]; |
151 | 69 |
152 // Check for a pair of element Ids | 70 // Check for a pair of element Ids |
153 var compareElements = false; | |
154 var elementId2; | |
155 if (typeof elementId != "string") { | 71 if (typeof elementId != "string") { |
156 if (elementId.length != 2) | 72 if (elementId.length != 2) |
157 return; | 73 return; |
158 | 74 |
159 elementId2 = elementId[1]; | 75 var elementId2 = elementId[1]; |
160 elementId = elementId[0]; | 76 elementId = elementId[0]; |
161 | 77 |
162 compareElements = true; | 78 var computedValue = getPropertyValue(property, elementId); |
163 } | 79 var computedValue2 = getPropertyValue(property, elementId2); |
164 | 80 |
165 // Check for a dot separated string | 81 if (comparePropertyValue(computedValue, computedValue2, tolerance, expec
tedIndex)) |
166 var iframeId; | 82 result += "PASS - \"" + specifiedProperty + "\" property for \"" + e
lementId + "\" and \"" + elementId2 + |
167 if (!compareElements) { | 83 "\" elements at " + time + "s are close enough to ea
ch other" + "<br>"; |
| 84 else |
| 85 result += "FAIL - \"" + specifiedProperty + "\" property for \"" + e
lementId + "\" and \"" + elementId2 + |
| 86 "\" elements at " + time + "s saw: \"" + computedVal
ue + "\" and \"" + computedValue2 + |
| 87 "\" which are not close enough to ea
ch other" + "<br>"; |
| 88 } else { |
| 89 var elementName = elementId; |
168 var array = elementId.split('.'); | 90 var array = elementId.split('.'); |
| 91 var iframeId; |
169 if (array.length == 2) { | 92 if (array.length == 2) { |
170 iframeId = array[0]; | 93 iframeId = array[0]; |
171 elementId = array[1]; | 94 elementId = array[1]; |
172 } | 95 } |
173 } | |
174 | 96 |
175 var computedValue, computedValue2; | 97 var computedValue = getPropertyValue(property, elementId, iframeId); |
176 if (compareElements) { | |
177 computedValue = getPropertyValue(property, elementId, iframeId); | |
178 computedValue2 = getPropertyValue(property, elementId2, iframeId); | |
179 | 98 |
180 if (comparePropertyValue(property, computedValue, computedValue2, tolera
nce)) | 99 if (comparePropertyValue(computedValue, expectedValue, tolerance, expect
edIndex)) |
181 result += "PASS - \"" + property + "\" property for \"" + elementId
+ "\" and \"" + elementId2 + | 100 result += "PASS - \"" + specifiedProperty + "\" property for \"" + e
lementName + "\" element at " + time + |
182 "\" elements at " + time + "s are close enough to ea
ch other" + "<br>"; | |
183 else | |
184 result += "FAIL - \"" + property + "\" property for \"" + elementId
+ "\" and \"" + elementId2 + | |
185 "\" elements at " + time + "s saw: \"" + computedVal
ue + "\" and \"" + computedValue2 + | |
186 "\" which are not close enough to ea
ch other" + "<br>"; | |
187 } else { | |
188 var elementName; | |
189 if (iframeId) | |
190 elementName = iframeId + '.' + elementId; | |
191 else | |
192 elementName = elementId; | |
193 | |
194 computedValue = getPropertyValue(property, elementId, iframeId); | |
195 | |
196 if (comparePropertyValue(property, computedValue, expectedValue, toleran
ce)) | |
197 result += "PASS - \"" + property + "\" property for \"" + elementNam
e + "\" element at " + time + | |
198 "s saw something close to: " + expectedValue + "<br>
"; | 101 "s saw something close to: " + expectedValue + "<br>
"; |
199 else | 102 else |
200 result += "FAIL - \"" + property + "\" property for \"" + elementNam
e + "\" element at " + time + | 103 result += "FAIL - \"" + specifiedProperty + "\" property for \"" + e
lementName + "\" element at " + time + |
201 "s expected: " + expectedValue + " but saw: " + comp
utedValue + "<br>"; | 104 "s expected: " + expectedValue + " but saw: " + comp
utedValue + "<br>"; |
202 } | 105 } |
203 } | |
204 | |
205 function compareRGB(rgb, expected, tolerance) | |
206 { | |
207 return (isCloseEnough(parseInt(rgb[0]), expected[0], tolerance) && | |
208 isCloseEnough(parseInt(rgb[1]), expected[1], tolerance) && | |
209 isCloseEnough(parseInt(rgb[2]), expected[2], tolerance)); | |
210 } | |
211 | |
212 function checkExpectedTransitionValue(expected, index) | |
213 { | |
214 log('Checking expectation: ' + JSON.stringify(expected[index])); | |
215 var time = expected[index][0]; | |
216 var elementId = expected[index][1]; | |
217 var property = expected[index][2]; | |
218 var expectedValue = expected[index][3]; | |
219 var tolerance = expected[index][4]; | |
220 var postCompletionCallback = expected[index][5]; | |
221 | |
222 var computedValue; | |
223 var pass = false; | |
224 var transformRegExp = /^-webkit-transform(\.\d+)?$/; | |
225 if (transformRegExp.test(property)) { | |
226 computedValue = window.getComputedStyle(document.getElementById(elementI
d)).webkitTransform; | |
227 if (typeof expectedValue === "string" || computedValue === "none") | |
228 pass = (computedValue == expectedValue); | |
229 else if (typeof expectedValue === "number") { | |
230 var m = computedValue.split("("); | |
231 var m = m[1].split(","); | |
232 pass = isCloseEnough(parseFloat(m[parseInt(property.substring(18))])
, expectedValue, tolerance); | |
233 } else { | |
234 var m = computedValue.split("("); | |
235 var m = m[1].split(","); | |
236 for (i = 0; i < expectedValue.length; ++i) { | |
237 pass = isCloseEnough(parseFloat(m[i]), expectedValue[i], toleran
ce); | |
238 if (!pass) | |
239 break; | |
240 } | |
241 } | |
242 } else if (property == "fill" || property == "stroke" || property == "stop-c
olor" || property == "flood-color" || property == "lighting-color") { | |
243 computedValue = window.getComputedStyle(document.getElementById(elementI
d)).getPropertyCSSValue(property); | |
244 // The computedValue cssText is rgb(num, num, num) | |
245 var components = computedValue.cssText.split("(")[1].split(")")[0].split
(","); | |
246 if (compareRGB(components, expectedValue, tolerance)) | |
247 pass = true; | |
248 else { | |
249 // We failed. Make sure computed value is something we can read in t
he error message | |
250 computedValue = computedValue.cssText; | |
251 } | |
252 } else if (property == "lineHeight") { | |
253 computedValue = parseInt(window.getComputedStyle(document.getElementById
(elementId)).lineHeight); | |
254 pass = isCloseEnough(computedValue, expectedValue, tolerance); | |
255 } else if (property == "background-image" | |
256 || property == "border-image-source" | |
257 || property == "border-image" | |
258 || property == "list-style-image" | |
259 || property == "-webkit-mask-image" | |
260 || property == "-webkit-mask-box-image") { | |
261 if (property == "border-image" || property == "-webkit-mask-image" || pr
operty == "-webkit-mask-box-image") | |
262 property += "-source"; | |
263 | |
264 computedValue = window.getComputedStyle(document.getElementById(elementI
d)).getPropertyCSSValue(property).cssText; | |
265 computedCrossFade = parseCrossFade(computedValue); | |
266 | |
267 if (!computedCrossFade) { | |
268 pass = false; | |
269 } else { | |
270 pass = isCloseEnough(computedCrossFade.percent, expectedValue, toler
ance); | |
271 } | |
272 } else if (property == "object-position") { | |
273 computedValue = window.getComputedStyle(document.getElementById(elementI
d)).objectPosition; | |
274 var actualArray = computedValue.split(" "); | |
275 var expectedArray = expectedValue.split(" "); | |
276 if (actualArray.length != expectedArray.length) { | |
277 pass = false; | |
278 } else { | |
279 for (i = 0; i < expectedArray.length; ++i) { | |
280 pass = isCloseEnough(parseFloat(actualArray[i]), parseFloat(expe
ctedArray[i]), tolerance); | |
281 if (!pass) | |
282 break; | |
283 } | |
284 } | |
285 } else if (property === "shape-outside") { | |
286 computedValue = window.getComputedStyle(document.getElementById(elementI
d)).getPropertyValue(property); | |
287 var actualShape = parseBasicShape(computedValue); | |
288 var expectedShape = parseBasicShape(expectedValue); | |
289 pass = basicShapeParametersMatch(actualShape, expectedShape, tolerance); | |
290 } else { | |
291 var computedStyle = window.getComputedStyle(document.getElementById(elem
entId)).getPropertyCSSValue(property); | |
292 if (computedStyle.cssValueType == CSSValue.CSS_VALUE_LIST) { | |
293 var values = []; | |
294 for (var i = 0; i < computedStyle.length; ++i) { | |
295 switch (computedStyle[i].cssValueType) { | |
296 case CSSValue.CSS_PRIMITIVE_VALUE: | |
297 if (computedStyle[i].primitiveType == CSSPrimitiveValue.CSS_
STRING) | |
298 values.push(computedStyle[i].getStringValue()); | |
299 else | |
300 values.push(computedStyle[i].getFloatValue(CSSPrimitiveV
alue.CSS_NUMBER)); | |
301 break; | |
302 case CSSValue.CSS_CUSTOM: | |
303 // arbitrarily pick shadow-x and shadow-y | |
304 if (property == 'box-shadow' || property == 'text-shadow') { | |
305 var text = computedStyle[i].cssText; | |
306 // Shadow cssText looks like "rgb(0, 0, 255) 0px -3px 10px
0px" and can be fractional. | |
307 var shadowPositionRegExp = /\)\s*(-?[\d.]+)px\s*(-?[\d.]+)
px/; | |
308 var match = shadowPositionRegExp.exec(text); | |
309 var shadowXY = [parseInt(match[1]), parseInt(match[2])]; | |
310 values.push(shadowXY[0]); | |
311 values.push(shadowXY[1]); | |
312 } else | |
313 values.push(computedStyle[i].cssText); | |
314 break; | |
315 } | |
316 } | |
317 computedValue = values.join(','); | |
318 pass = true; | |
319 for (var i = 0; i < values.length; ++i) | |
320 pass &= isCloseEnough(values[i], expectedValue[i], tolerance); | |
321 } else if (computedStyle.cssValueType == CSSValue.CSS_PRIMITIVE_VALUE) { | |
322 switch (computedStyle.primitiveType) { | |
323 case CSSPrimitiveValue.CSS_STRING: | |
324 case CSSPrimitiveValue.CSS_IDENT: | |
325 computedValue = computedStyle.getStringValue(); | |
326 pass = computedValue == expectedValue; | |
327 break; | |
328 case CSSPrimitiveValue.CSS_RGBCOLOR: | |
329 var rgbColor = computedStyle.getRGBColorValue(); | |
330 computedValue = [rgbColor.red.getFloatValue(CSSPrimitiveValu
e.CSS_NUMBER), | |
331 rgbColor.green.getFloatValue(CSSPrimitiveVa
lue.CSS_NUMBER), | |
332 rgbColor.blue.getFloatValue(CSSPrimitiveVal
ue.CSS_NUMBER)]; // alpha is not exposed to JS | |
333 pass = true; | |
334 for (var i = 0; i < 3; ++i) | |
335 pass &= isCloseEnough(computedValue[i], expectedValue[i]
, tolerance); | |
336 break; | |
337 case CSSPrimitiveValue.CSS_RECT: | |
338 computedValue = computedStyle.getRectValue(); | |
339 computedValue = [computedValue.top.getFloatValue(CSSPrimitiv
eValue.CSS_NUMBER), | |
340 computedValue.right.getFloatValue(CSSPrimit
iveValue.CSS_NUMBER), | |
341 computedValue.bottom.getFloatValue(CSSPrimi
tiveValue.CSS_NUMBER), | |
342 computedValue.left.getFloatValue(CSSPrimiti
veValue.CSS_NUMBER)]; | |
343 pass = true; | |
344 for (var i = 0; i < 4; ++i) | |
345 pass &= isCloseEnough(computedValue[i], expectedValue[i
], tolerance); | |
346 break; | |
347 case CSSPrimitiveValue.CSS_PERCENTAGE: | |
348 computedValue = parseFloat(computedStyle.cssText); | |
349 pass = isCloseEnough(computedValue, expectedValue, tolerance
); | |
350 break; | |
351 default: | |
352 computedValue = computedStyle.getFloatValue(CSSPrimitiveValu
e.CSS_NUMBER); | |
353 pass = isCloseEnough(computedValue, expectedValue, tolerance
); | |
354 } | |
355 } | |
356 } | |
357 | |
358 if (pass) | |
359 result += "PASS - \"" + property + "\" property for \"" + elementId + "\
" element at " + time + "s saw something close to: " + expectedValue + "<br>"; | |
360 else | |
361 result += "FAIL - \"" + property + "\" property for \"" + elementId + "\
" element at " + time + "s expected: " + expectedValue + " but saw: " + computed
Value + "<br>"; | |
362 | 106 |
363 if (postCompletionCallback) | 107 if (postCompletionCallback) |
364 result += postCompletionCallback(); | 108 result += postCompletionCallback(); |
365 } | 109 } |
366 | 110 |
367 | |
368 function getPropertyValue(property, elementId, iframeId) | 111 function getPropertyValue(property, elementId, iframeId) |
369 { | 112 { |
370 var computedValue; | 113 var context = iframeId ? document.getElementById(iframeId).contentDocument :
document; |
371 var element; | 114 var element = context.getElementById(elementId); |
372 if (iframeId) | 115 return window.getComputedStyle(element)[property]; |
373 element = document.getElementById(iframeId).contentDocument.getElementBy
Id(elementId); | 116 } |
374 else | |
375 element = document.getElementById(elementId); | |
376 | 117 |
377 if (property == "lineHeight") | 118 // splitValue("calc(12.5px + 10%)") -> [["calc(", "px + ", "%)"], [12.5, 10]] |
378 computedValue = parseInt(window.getComputedStyle(element).lineHeight); | 119 function splitValue(value) |
379 else if (property == "backgroundImage" | 120 { |
380 || property == "borderImageSource" | 121 var substrings = value.split(/(-?\d+(?:\.\d+)?(?:e-?\d+)?)/g); |
381 || property == "listStyleImage" | 122 var strings = []; |
382 || property == "webkitMaskImage" | 123 var numbers = []; |
383 || property == "webkitMaskBoxImage" | 124 for (var i = 0; i < substrings.length; i++) { |
384 || property == "webkitFilter" | 125 if (i % 2 == 0) |
385 || property == "webkitClipPath" | 126 strings.push(substrings[i]); |
386 || !property.indexOf("webkitTransform")) { | 127 else |
387 computedValue = window.getComputedStyle(element)[property.split(".")[0]]
; | 128 numbers.push(parseFloat(substrings[i])); |
| 129 } |
| 130 return [strings, numbers]; |
| 131 } |
| 132 |
| 133 function comparePropertyValue(computedValue, expectedValue, tolerance, expectedI
ndex) |
| 134 { |
| 135 computedValue = splitValue(computedValue); |
| 136 var computedStrings = computedValue[0]; |
| 137 var computedNumbers = computedValue[1]; |
| 138 |
| 139 var expectedStrings, expectedNumbers; |
| 140 |
| 141 if (expectedIndex !== undefined) |
| 142 return isCloseEnough(computedNumbers[expectedIndex], expectedValue, tole
rance); |
| 143 |
| 144 if (typeof expectedValue === "string") { |
| 145 expectedValue = splitValue(expectedValue); |
| 146 |
| 147 expectedStrings = expectedValue[0]; |
| 148 if (computedStrings.length !== expectedStrings.length) |
| 149 return false; |
| 150 for (var i = 0; i < expectedStrings.length; i++) |
| 151 if (expectedStrings[i] !== computedStrings[i]) |
| 152 return false; |
| 153 |
| 154 expectedNumbers = expectedValue[1]; |
| 155 } else if (typeof expectedValue === "number") { |
| 156 expectedNumbers = [expectedValue]; |
388 } else { | 157 } else { |
389 var computedStyle = window.getComputedStyle(element).getPropertyCSSValue
(property); | 158 expectedNumbers = expectedValue; |
390 try { | |
391 computedValue = computedStyle.getFloatValue(CSSPrimitiveValue.CSS_NU
MBER); | |
392 } catch (e) { | |
393 computedValue = computedStyle.cssText; | |
394 } | |
395 } | 159 } |
396 | 160 |
397 return computedValue; | 161 if (computedNumbers.length !== expectedNumbers.length) |
398 } | 162 return false; |
| 163 for (var i = 0; i < expectedNumbers.length; i++) |
| 164 if (!isCloseEnough(computedNumbers[i], expectedNumbers[i], tolerance)) |
| 165 return false; |
399 | 166 |
400 function comparePropertyValue(property, computedValue, expectedValue, tolerance) | 167 return true; |
401 { | |
402 var result = true; | |
403 | |
404 if (!property.indexOf("webkitTransform")) { | |
405 if (typeof expectedValue == "string") | |
406 result = (computedValue == expectedValue); | |
407 else if (typeof expectedValue == "number") { | |
408 var m = matrixStringToArray(computedValue); | |
409 result = isCloseEnough(parseFloat(m[parseInt(property.substring(16))
]), expectedValue, tolerance); | |
410 } else { | |
411 var m = matrixStringToArray(computedValue); | |
412 for (i = 0; i < expectedValue.length; ++i) { | |
413 result = isCloseEnough(parseFloat(m[i]), expectedValue[i], toler
ance); | |
414 if (!result) | |
415 break; | |
416 } | |
417 } | |
418 } else if (property == "webkitFilter") { | |
419 var filterParameters = getFilterParameters(computedValue); | |
420 var filter2Parameters = getFilterParameters(expectedValue); | |
421 result = filterParametersMatch(filterParameters, filter2Parameters, tole
rance); | |
422 } else if (property == "webkitClipPath") { | |
423 var clipPathParameters = parseBasicShape(computedValue); | |
424 var clipPathParameters2 = parseBasicShape(expectedValue); | |
425 if (!clipPathParameters || !clipPathParameters2) | |
426 result = false; | |
427 result = basicShapeParametersMatch(clipPathParameters, clipPathParameter
s2, tolerance); | |
428 } else if (property == "backgroundImage" | |
429 || property == "borderImageSource" | |
430 || property == "listStyleImage" | |
431 || property == "webkitMaskImage" | |
432 || property == "webkitMaskBoxImage") { | |
433 var computedCrossFade = parseCrossFade(computedValue); | |
434 | |
435 if (!computedCrossFade) { | |
436 result = false; | |
437 } else { | |
438 if (typeof expectedValue == "string") { | |
439 var computedCrossFade2 = parseCrossFade(expectedValue); | |
440 result = isCloseEnough(computedCrossFade.percent, computedCrossF
ade2.percent, tolerance) && computedCrossFade.from == computedCrossFade2.from &&
computedCrossFade.to == computedCrossFade2.to; | |
441 } else { | |
442 result = isCloseEnough(computedCrossFade.percent, expectedValue,
tolerance) | |
443 } | |
444 } | |
445 } else { | |
446 if (typeof expectedValue == "string") | |
447 result = (computedValue == expectedValue); | |
448 else | |
449 result = isCloseEnough(computedValue, expectedValue, tolerance); | |
450 } | |
451 return result; | |
452 } | 168 } |
453 | 169 |
454 function endTest() | 170 function endTest() |
455 { | 171 { |
456 log('Ending test'); | 172 log('Ending test'); |
457 var resultElement = useResultElement ? document.getElementById('result') : d
ocument.documentElement; | 173 var resultElement = useResultElement ? document.getElementById('result') : d
ocument.documentElement; |
458 if (ENABLE_ERROR_LOGGING && result.indexOf('FAIL') >= 0) | 174 if (ENABLE_ERROR_LOGGING && result.indexOf('FAIL') >= 0) |
459 result += '<br>Log:<br>' + logMessages.join('<br>'); | 175 result += '<br>Log:<br>' + logMessages.join('<br>'); |
460 resultElement.innerHTML = result; | 176 resultElement.innerHTML = result; |
461 | 177 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 } else for (var time in callbacks) { | 261 } else for (var time in callbacks) { |
546 timeMs = Math.round(time * 1000); | 262 timeMs = Math.round(time * 1000); |
547 checks[timeMs] = [callbacks[time]]; | 263 checks[timeMs] = [callbacks[time]]; |
548 } | 264 } |
549 | 265 |
550 for (var i = 0; i < expected.length; i++) { | 266 for (var i = 0; i < expected.length; i++) { |
551 var expectation = expected[i]; | 267 var expectation = expected[i]; |
552 var timeMs = Math.round(expectation[0] * 1000); | 268 var timeMs = Math.round(expectation[0] * 1000); |
553 if (!checks[timeMs]) | 269 if (!checks[timeMs]) |
554 checks[timeMs] = []; | 270 checks[timeMs] = []; |
555 if (isTransitionsTest) | 271 checks[timeMs].push(checkExpectedValue.bind(null, expected, i)); |
556 checks[timeMs].push(checkExpectedTransitionValue.bind(null, expected
, i)); | |
557 else | |
558 checks[timeMs].push(checkExpectedValue.bind(null, expected, i)); | |
559 } | 272 } |
560 | 273 |
561 var doPixelTest = Boolean(doPixelTest); | 274 var doPixelTest = Boolean(doPixelTest); |
562 useResultElement = doPixelTest; | 275 useResultElement = doPixelTest; |
563 | 276 |
564 if (window.testRunner) { | 277 if (window.testRunner) { |
565 if (doPixelTest) { | 278 if (doPixelTest) { |
566 testRunner.dumpAsTextWithPixelResults(); | 279 testRunner.dumpAsTextWithPixelResults(); |
567 } else { | 280 } else { |
568 testRunner.dumpAsText(); | 281 testRunner.dumpAsText(); |
(...skipping 22 matching lines...) Expand all Loading... |
591 var startTestImmediately = Boolean(startTestImmediately); | 304 var startTestImmediately = Boolean(startTestImmediately); |
592 if (startTestImmediately) { | 305 if (startTestImmediately) { |
593 begin(); | 306 begin(); |
594 } else { | 307 } else { |
595 var target = isTransitionsTest ? window : document; | 308 var target = isTransitionsTest ? window : document; |
596 var event = isTransitionsTest ? 'load' : 'webkitAnimationStart'; | 309 var event = isTransitionsTest ? 'load' : 'webkitAnimationStart'; |
597 target.addEventListener(event, begin, false); | 310 target.addEventListener(event, begin, false); |
598 } | 311 } |
599 } | 312 } |
600 | 313 |
601 /* This is the helper function to run transition tests: | |
602 | |
603 Test page requirements: | |
604 - The body must contain an empty div with id "result" | |
605 - Call this function directly from the <script> inside the test page | |
606 | |
607 Function parameters: | |
608 expected [required]: an array of arrays defining a set of CSS properties tha
t must have given values at specific times (see below) | |
609 trigger [optional]: a function to be executed just before the test starts (n
one by default) | |
610 callbacks [optional]: an object in the form {timeS: function} specifing call
backs to be made during the test | |
611 doPixelTest [optional]: whether to dump pixels during the test (false by def
ault) | |
612 disablePauseAnimationAPI [optional]: whether to disable the pause API and ru
n a RAF-based test (false by default) | |
613 | |
614 Each sub-array must contain these items in this order: | |
615 - the time in seconds at which to snapshot the CSS property | |
616 - the id of the element on which to get the CSS property value | |
617 - the name of the CSS property to get [1] | |
618 - the expected value for the CSS property | |
619 - the tolerance to use when comparing the effective CSS property value with
its expected value | |
620 | |
621 [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, | |
622 or a string which will be compared directly (useful if the expected value is
"none") | |
623 If the CSS property name is "-webkit-transform.N", expected value must be a
number corresponding to the Nth element of the matrix | |
624 | |
625 */ | |
626 function runTransitionTest(expected, trigger, callbacks, doPixelTest, disablePau
seAnimationAPI) { | 314 function runTransitionTest(expected, trigger, callbacks, doPixelTest, disablePau
seAnimationAPI) { |
627 isTransitionsTest = true; | 315 isTransitionsTest = true; |
628 runAnimationTest(expected, callbacks, trigger, disablePauseAnimationAPI, doP
ixelTest); | 316 runAnimationTest(expected, callbacks, trigger, disablePauseAnimationAPI, doP
ixelTest); |
629 } | 317 } |
OLD | NEW |