Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / LayoutTests / animations / resources / animation-test-helpers.js
1 /* This is the helper function to run animation 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 that must have given values at specific times (see below)
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
11                           called at the specified times (in seconds) during animation.
12     trigger [optional]: a function to trigger transitions at the start of the test
13
14     Each sub-array must contain these items in this order:
15     - 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]
17     - the name of the CSS property to get [2]
18     - the expected value for the CSS property
19     - the tolerance to use when comparing the effective CSS property value with its expected value
20
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
22     are the ids of 2 elements, whose values are compared for equality. In this case the expected value is ignored
23     but the tolerance is used in the comparison. If the second element is prefixed with "static:", no animation on that
24     element is required, allowing comparison with an unanimated "expected value" element.
25
26     If a string with a '.' is passed, this is an element in an iframe. The string before the dot is the iframe id
27     and the string after the dot is the element name in that iframe.
28
29     [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     or a string which will be compared directly (useful if the expected value is "none")
31     If the CSS property name is "webkitTransform.N", expected value must be a number corresponding to the Nth element of the matrix
32
33 */
34
35 // Set to true to log debug information in failing tests. Note that these logs
36 // contain timestamps, so are non-deterministic and will introduce flakiness if
37 // any expected results include failures.
38 var ENABLE_ERROR_LOGGING = false;
39
40 function isCloseEnough(actual, desired, tolerance)
41 {
42     if (typeof desired === "string")
43         return actual === desired;
44     var diff = Math.abs(actual - desired);
45     return diff <= tolerance;
46 }
47
48 function roundNumber(num, decimalPlaces)
49 {
50   return Math.round(num * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces);
51 }
52
53 function matrixStringToArray(s)
54 {
55     if (s == "none")
56         return [ 1, 0, 0, 1, 0, 0 ];
57     var m = s.split("(");
58     m = m[1].split(")");
59     return m[0].split(",");
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 parseBasicShape(s)
73 {
74     var functionParse = s.match(/(\w+)\((.+)\)/);
75     if (!functionParse)
76         return null;
77
78     var name = functionParse[1];
79     var params = functionParse[2];
80     params = params.split(/\s*[,\s]\s*/);
81
82     // Parse numbers and normalize percentages
83     for (var i = 0; i < params.length; ++i) {
84         var param = params[i];
85         if (!/$\d/.test(param))
86             continue;
87         params[i] = parseFloat(params[i]);
88         if (param.indexOf('%') != -1)
89             params[i] = params[i] / 100;
90     }
91
92     return {"shape": name, "params": params};
93 }
94
95 function basicShapeParametersMatch(paramList1, paramList2, tolerance)
96 {
97     if (paramList1.shape != paramList2.shape
98         || paramList1.params.length != paramList2.params.length)
99         return false;
100     for (var i = 0; i < paramList1.params.length; ++i) {
101         var param1 = paramList1.params[i], 
102             param2 = paramList2.params[i];
103         var match = isCloseEnough(param1, param2, tolerance);
104         if (!match)
105             return false;
106     }
107     return true;
108 }
109
110 // Return an array of numeric filter params in 0-1.
111 function getFilterParameters(s)
112 {
113     var filterResult = s.match(/(\w+)\((.+)\)/);
114     if (!filterResult)
115         throw new Error("There's no filter in \"" + s + "\"");
116     var filterParams = filterResult[2];
117     var paramList = filterParams.split(' '); // FIXME: the spec may allow comma separation at some point.
118     
119     // Normalize percentage values.
120     for (var i = 0; i < paramList.length; ++i) {
121         var param = paramList[i];
122         paramList[i] = parseFloat(paramList[i]);
123         if (param.indexOf('%') != -1)
124             paramList[i] = paramList[i] / 100;
125     }
126
127     return paramList;
128 }
129
130 function filterParametersMatch(paramList1, paramList2, tolerance)
131 {
132     if (paramList1.length != paramList2.length)
133         return false;
134     for (var i = 0; i < paramList1.length; ++i) {
135         var param1 = paramList1[i], 
136             param2 = paramList2[i];
137         var match = isCloseEnough(param1, param2, tolerance);
138         if (!match)
139             return false;
140     }
141     return true;
142 }
143
144 function checkExpectedValue(expected, index)
145 {
146     log('Checking expectation: ' + JSON.stringify(expected[index]));
147     var time = expected[index][0];
148     var elementId = expected[index][1];
149     var property = expected[index][2];
150     var expectedValue = expected[index][3];
151     var tolerance = expected[index][4];
152
153     // Check for a pair of element Ids
154     var compareElements = false;
155     var element2Static = false;
156     var elementId2;
157     if (typeof elementId != "string") {
158         if (elementId.length != 2)
159             return;
160             
161         elementId2 = elementId[1];
162         elementId = elementId[0];
163
164         if (elementId2.indexOf("static:") == 0) {
165             elementId2 = elementId2.replace("static:", "");
166             element2Static = true;
167         }
168
169         compareElements = true;
170     }
171
172     // Check for a dot separated string
173     var iframeId;
174     if (!compareElements) {
175         var array = elementId.split('.');
176         if (array.length == 2) {
177             iframeId = array[0];
178             elementId = array[1];
179         }
180     }
181
182     var computedValue, computedValue2;
183     if (compareElements) {
184         computedValue = getPropertyValue(property, elementId, iframeId);
185         computedValue2 = getPropertyValue(property, elementId2, iframeId);
186
187         if (comparePropertyValue(property, computedValue, computedValue2, tolerance))
188             result += "PASS - \"" + property + "\" property for \"" + elementId + "\" and \"" + elementId2 + 
189                             "\" elements at " + time + "s are close enough to each other" + "<br>";
190         else
191             result += "FAIL - \"" + property + "\" property for \"" + elementId + "\" and \"" + elementId2 + 
192                             "\" elements at " + time + "s saw: \"" + computedValue + "\" and \"" + computedValue2 + 
193                                             "\" which are not close enough to each other" + "<br>";
194     } else {
195         var elementName;
196         if (iframeId)
197             elementName = iframeId + '.' + elementId;
198         else
199             elementName = elementId;
200
201         computedValue = getPropertyValue(property, elementId, iframeId);
202
203         if (comparePropertyValue(property, computedValue, expectedValue, tolerance))
204             result += "PASS - \"" + property + "\" property for \"" + elementName + "\" element at " + time + 
205                             "s saw something close to: " + expectedValue + "<br>";
206         else
207             result += "FAIL - \"" + property + "\" property for \"" + elementName + "\" element at " + time + 
208                             "s expected: " + expectedValue + " but saw: " + computedValue + "<br>";
209     }
210 }
211
212 function compareRGB(rgb, expected, tolerance)
213 {
214     return (isCloseEnough(parseInt(rgb[0]), expected[0], tolerance) &&
215             isCloseEnough(parseInt(rgb[1]), expected[1], tolerance) &&
216             isCloseEnough(parseInt(rgb[2]), expected[2], tolerance));
217 }
218
219 function checkExpectedTransitionValue(expected, index)
220 {
221     log('Checking expectation: ' + JSON.stringify(expected[index]));
222     var time = expected[index][0];
223     var elementId = expected[index][1];
224     var property = expected[index][2];
225     var expectedValue = expected[index][3];
226     var tolerance = expected[index][4];
227     var postCompletionCallback = expected[index][5];
228
229     var computedValue;
230     var pass = false;
231     var transformRegExp = /^-webkit-transform(\.\d+)?$/;
232     if (transformRegExp.test(property)) {
233         computedValue = window.getComputedStyle(document.getElementById(elementId)).webkitTransform;
234         if (typeof expectedValue === "string" || computedValue === "none")
235             pass = (computedValue == expectedValue);
236         else if (typeof expectedValue === "number") {
237             var m = computedValue.split("(");
238             var m = m[1].split(",");
239             pass = isCloseEnough(parseFloat(m[parseInt(property.substring(18))]), expectedValue, tolerance);
240         } else {
241             var m = computedValue.split("(");
242             var m = m[1].split(",");
243             for (i = 0; i < expectedValue.length; ++i) {
244                 pass = isCloseEnough(parseFloat(m[i]), expectedValue[i], tolerance);
245                 if (!pass)
246                     break;
247             }
248         }
249     } else if (property == "fill" || property == "stroke" || property == "stop-color" || property == "flood-color" || property == "lighting-color") {
250         computedValue = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property);
251         // The computedValue cssText is rgb(num, num, num)
252         var components = computedValue.cssText.split("(")[1].split(")")[0].split(",");
253         if (compareRGB(components, expectedValue, tolerance))
254             pass = true;
255         else {
256             // We failed. Make sure computed value is something we can read in the error message
257             computedValue = computedValue.cssText;
258         }
259     } else if (property == "lineHeight") {
260         computedValue = parseInt(window.getComputedStyle(document.getElementById(elementId)).lineHeight);
261         pass = isCloseEnough(computedValue, expectedValue, tolerance);
262     } else if (property == "background-image"
263                || property == "border-image-source"
264                || property == "border-image"
265                || property == "list-style-image"
266                || property == "-webkit-mask-image"
267                || property == "-webkit-mask-box-image") {
268         if (property == "border-image" || property == "-webkit-mask-image" || property == "-webkit-mask-box-image")
269             property += "-source";
270
271         computedValue = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property).cssText;
272         computedCrossFade = parseCrossFade(computedValue);
273
274         if (!computedCrossFade) {
275             pass = false;
276         } else {
277             pass = isCloseEnough(computedCrossFade.percent, expectedValue, tolerance);
278         }
279     } else if (property == "object-position") {
280         computedValue = window.getComputedStyle(document.getElementById(elementId)).objectPosition;
281         var actualArray = computedValue.split(" ");
282         var expectedArray = expectedValue.split(" ");
283         if (actualArray.length != expectedArray.length) {
284             pass = false;
285         } else {
286             for (i = 0; i < expectedArray.length; ++i) {
287                 pass = isCloseEnough(parseFloat(actualArray[i]), parseFloat(expectedArray[i]), tolerance);
288                 if (!pass)
289                     break;
290             }
291         }
292     } else if (property === "shape-outside") {
293         computedValue = window.getComputedStyle(document.getElementById(elementId)).getPropertyValue(property);
294         var actualShape = parseBasicShape(computedValue);
295         var expectedShape = parseBasicShape(expectedValue);
296         pass = basicShapeParametersMatch(actualShape, expectedShape, tolerance);
297     } else {
298         var computedStyle = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property);
299         if (computedStyle.cssValueType == CSSValue.CSS_VALUE_LIST) {
300             var values = [];
301             for (var i = 0; i < computedStyle.length; ++i) {
302                 switch (computedStyle[i].cssValueType) {
303                   case CSSValue.CSS_PRIMITIVE_VALUE:
304                     if (computedStyle[i].primitiveType == CSSPrimitiveValue.CSS_STRING)
305                         values.push(computedStyle[i].getStringValue());
306                     else
307                         values.push(computedStyle[i].getFloatValue(CSSPrimitiveValue.CSS_NUMBER));
308                     break;
309                   case CSSValue.CSS_CUSTOM:
310                     // arbitrarily pick shadow-x and shadow-y
311                     if (property == 'box-shadow' || property == 'text-shadow') {
312                       var text = computedStyle[i].cssText;
313                       // Shadow cssText looks like "rgb(0, 0, 255) 0px -3px 10px 0px" and can be fractional.
314                       var shadowPositionRegExp = /\)\s*(-?[\d.]+)px\s*(-?[\d.]+)px/;
315                       var match = shadowPositionRegExp.exec(text);
316                       var shadowXY = [parseInt(match[1]), parseInt(match[2])];
317                       values.push(shadowXY[0]);
318                       values.push(shadowXY[1]);
319                     } else
320                       values.push(computedStyle[i].cssText);
321                     break;
322                 }
323             }
324             computedValue = values.join(',');
325             pass = true;
326             for (var i = 0; i < values.length; ++i)
327                 pass &= isCloseEnough(values[i], expectedValue[i], tolerance);
328         } else if (computedStyle.cssValueType == CSSValue.CSS_PRIMITIVE_VALUE) {
329             switch (computedStyle.primitiveType) {
330                 case CSSPrimitiveValue.CSS_STRING:
331                 case CSSPrimitiveValue.CSS_IDENT:
332                     computedValue = computedStyle.getStringValue();
333                     pass = computedValue == expectedValue;
334                     break;
335                 case CSSPrimitiveValue.CSS_RGBCOLOR:
336                     var rgbColor = computedStyle.getRGBColorValue();
337                     computedValue = [rgbColor.red.getFloatValue(CSSPrimitiveValue.CSS_NUMBER),
338                                      rgbColor.green.getFloatValue(CSSPrimitiveValue.CSS_NUMBER),
339                                      rgbColor.blue.getFloatValue(CSSPrimitiveValue.CSS_NUMBER)]; // alpha is not exposed to JS
340                     pass = true;
341                     for (var i = 0; i < 3; ++i)
342                         pass &= isCloseEnough(computedValue[i], expectedValue[i], tolerance);
343                     break;
344                 case CSSPrimitiveValue.CSS_RECT:
345                     computedValue = computedStyle.getRectValue();
346                     computedValue = [computedValue.top.getFloatValue(CSSPrimitiveValue.CSS_NUMBER),
347                                      computedValue.right.getFloatValue(CSSPrimitiveValue.CSS_NUMBER),
348                                      computedValue.bottom.getFloatValue(CSSPrimitiveValue.CSS_NUMBER),
349                                      computedValue.left.getFloatValue(CSSPrimitiveValue.CSS_NUMBER)];
350                      pass = true;
351                      for (var i = 0; i < 4; ++i)
352                          pass &= isCloseEnough(computedValue[i], expectedValue[i], tolerance);
353                     break;
354                 case CSSPrimitiveValue.CSS_PERCENTAGE:
355                     computedValue = parseFloat(computedStyle.cssText);
356                     pass = isCloseEnough(computedValue, expectedValue, tolerance);
357                     break;
358                 default:
359                     computedValue = computedStyle.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
360                     pass = isCloseEnough(computedValue, expectedValue, tolerance);
361             }
362         }
363     }
364
365     if (pass)
366         result += "PASS - \"" + property + "\" property for \"" + elementId + "\" element at " + time + "s saw something close to: " + expectedValue + "<br>";
367     else
368         result += "FAIL - \"" + property + "\" property for \"" + elementId + "\" element at " + time + "s expected: " + expectedValue + " but saw: " + computedValue + "<br>";
369
370     if (postCompletionCallback)
371       result += postCompletionCallback();
372 }
373
374
375 function getPropertyValue(property, elementId, iframeId)
376 {
377     var computedValue;
378     var element;
379     if (iframeId)
380         element = document.getElementById(iframeId).contentDocument.getElementById(elementId);
381     else
382         element = document.getElementById(elementId);
383
384     if (property == "lineHeight")
385         computedValue = parseInt(window.getComputedStyle(element).lineHeight);
386     else if (property == "backgroundImage"
387                || property == "borderImageSource"
388                || property == "listStyleImage"
389                || property == "webkitMaskImage"
390                || property == "webkitMaskBoxImage"
391                || property == "webkitFilter"
392                || property == "webkitClipPath"
393                || !property.indexOf("webkitTransform")) {
394         computedValue = window.getComputedStyle(element)[property.split(".")[0]];
395     } else {
396         var computedStyle = window.getComputedStyle(element).getPropertyCSSValue(property);
397         try {
398             computedValue = computedStyle.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
399         } catch (e) {
400             computedValue = computedStyle.cssText;
401         }
402     }
403
404     return computedValue;
405 }
406
407 function comparePropertyValue(property, computedValue, expectedValue, tolerance)
408 {
409     var result = true;
410
411     if (!property.indexOf("webkitTransform")) {
412         if (typeof expectedValue == "string")
413             result = (computedValue == expectedValue);
414         else if (typeof expectedValue == "number") {
415             var m = matrixStringToArray(computedValue);
416             result = isCloseEnough(parseFloat(m[parseInt(property.substring(16))]), expectedValue, tolerance);
417         } else {
418             var m = matrixStringToArray(computedValue);
419             for (i = 0; i < expectedValue.length; ++i) {
420                 result = isCloseEnough(parseFloat(m[i]), expectedValue[i], tolerance);
421                 if (!result)
422                     break;
423             }
424         }
425     } else if (property == "webkitFilter") {
426         var filterParameters = getFilterParameters(computedValue);
427         var filter2Parameters = getFilterParameters(expectedValue);
428         result = filterParametersMatch(filterParameters, filter2Parameters, tolerance);
429     } else if (property == "webkitClipPath") {
430         var clipPathParameters = parseBasicShape(computedValue);
431         var clipPathParameters2 = parseBasicShape(expectedValue);
432         if (!clipPathParameters || !clipPathParameters2)
433             result = false;
434         result = basicShapeParametersMatch(clipPathParameters, clipPathParameters2, tolerance);
435     } else if (property == "backgroundImage"
436                || property == "borderImageSource"
437                || property == "listStyleImage"
438                || property == "webkitMaskImage"
439                || property == "webkitMaskBoxImage") {
440         var computedCrossFade = parseCrossFade(computedValue);
441
442         if (!computedCrossFade) {
443             result = false;
444         } else {
445             if (typeof expectedValue == "string") {
446                 var computedCrossFade2 = parseCrossFade(expectedValue);
447                 result = isCloseEnough(computedCrossFade.percent, computedCrossFade2.percent, tolerance) && computedCrossFade.from == computedCrossFade2.from && computedCrossFade.to == computedCrossFade2.to;
448             } else {
449                 result = isCloseEnough(computedCrossFade.percent, expectedValue, tolerance)
450             }
451         }
452     } else {
453         if (typeof expectedValue == "string")
454             result = (computedValue == expectedValue);
455         else
456             result = isCloseEnough(computedValue, expectedValue, tolerance);
457     }
458     return result;
459 }
460
461 function endTest()
462 {
463     log('Ending test');
464     var resultElement = useResultElement ? document.getElementById('result') : document.documentElement;
465     if (ENABLE_ERROR_LOGGING && result.indexOf('FAIL') >= 0)
466         result += '<br>Log:<br>' + logMessages.join('<br>');
467     resultElement.innerHTML = result;
468
469     if (window.testRunner)
470         testRunner.notifyDone();
471 }
472
473 function runChecksWithRAF(checks)
474 {
475     var finished = true;
476     var time = performance.now() - animStartTime;
477
478     log('RAF callback, animation time: ' + time);
479     for (var k in checks) {
480         var checkTime = Number(k);
481         if (checkTime > time) {
482             finished = false;
483             break;
484         }
485         log('Running checks for time: ' + checkTime + ', delay: ' + (time - checkTime));
486         checks[k].forEach(function(check) { check(); });
487         delete checks[k];
488     }
489
490     if (finished)
491         endTest();
492     else
493         requestAnimationFrame(runChecksWithRAF.bind(null, checks));
494 }
495
496 function runChecksWithPauseAPI(checks) {
497     for (var k in checks) {
498         var timeMs = Number(k);
499         log('Pausing at time: ' + timeMs + ', active animations: ' + internals.numberOfActiveAnimations());
500         internals.pauseAnimations(timeMs / 1000);
501         checks[k].forEach(function(check) { check(); });
502     }
503     endTest();
504 }
505
506 function startTest(checks)
507 {
508     if (hasPauseAnimationAPI)
509         runChecksWithPauseAPI(checks);
510     else {
511         result += 'Warning this test is running in real-time and may be flaky.<br>';
512         runChecksWithRAF(checks);
513     }
514 }
515
516 var logMessages = [];
517 var useResultElement = false;
518 var result = "";
519 var hasPauseAnimationAPI;
520 var animStartTime;
521 var isTransitionsTest = false;
522
523 function log(message)
524 {
525     logMessages.push(performance.now() + ' - ' + message);
526 }
527
528 function waitForAnimationsToStart(callback)
529 {
530     if (!window.internals || internals.numberOfActiveAnimations() > 0) {
531         callback();
532     } else {
533         setTimeout(waitForAnimationsToStart.bind(this, callback), 0);
534     }
535 }
536
537 // FIXME: disablePauseAnimationAPI and doPixelTest
538 function runAnimationTest(expected, callbacks, trigger, disablePauseAnimationAPI, doPixelTest, startTestImmediately)
539 {
540     log('runAnimationTest');
541     if (!expected)
542         throw "Expected results are missing!";
543
544     hasPauseAnimationAPI = 'internals' in window;
545     if (disablePauseAnimationAPI)
546         hasPauseAnimationAPI = false;
547
548     var checks = {};
549
550     if (typeof callbacks == 'function') {
551         checks[0] = [callbacks];
552     } else for (var time in callbacks) {
553         timeMs = Math.round(time * 1000);
554         checks[timeMs] = [callbacks[time]];
555     }
556
557     for (var i = 0; i < expected.length; i++) {
558         var expectation = expected[i];
559         var timeMs = Math.round(expectation[0] * 1000);
560         if (!checks[timeMs])
561             checks[timeMs] = [];
562         if (isTransitionsTest)
563             checks[timeMs].push(checkExpectedTransitionValue.bind(null, expected, i));
564         else
565             checks[timeMs].push(checkExpectedValue.bind(null, expected, i));
566     }
567
568     var doPixelTest = Boolean(doPixelTest);
569     useResultElement = doPixelTest;
570
571     if (window.testRunner) {
572         if (doPixelTest) {
573             testRunner.dumpAsTextWithPixelResults();
574         } else {
575             testRunner.dumpAsText();
576         }
577         testRunner.waitUntilDone();
578     }
579
580     var started = false;
581
582     function begin() {
583         if (!started) {
584             log('First ' + event + ' event fired');
585             started = true;
586             if (trigger) {
587                 trigger();
588                 document.documentElement.offsetTop
589             }
590             waitForAnimationsToStart(function() {
591                 log('Finished waiting for animations to start');
592                 animStartTime = performance.now();
593                 startTest(checks);
594             });
595         }
596     }
597
598     var startTestImmediately = Boolean(startTestImmediately);
599     if (startTestImmediately) {
600         begin();
601     } else {
602         var target = isTransitionsTest ? window : document;
603         var event = isTransitionsTest ? 'load' : 'webkitAnimationStart';
604         target.addEventListener(event, begin, false);
605     }
606 }
607
608 /* This is the helper function to run transition tests:
609
610 Test page requirements:
611 - The body must contain an empty div with id "result"
612 - Call this function directly from the <script> inside the test page
613
614 Function parameters:
615     expected [required]: an array of arrays defining a set of CSS properties that must have given values at specific times (see below)
616     trigger [optional]: a function to be executed just before the test starts (none by default)
617     callbacks [optional]: an object in the form {timeS: function} specifing callbacks to be made during the test
618     doPixelTest [optional]: whether to dump pixels during the test (false by default)
619     disablePauseAnimationAPI [optional]: whether to disable the pause API and run a RAF-based test (false by default)
620
621     Each sub-array must contain these items in this order:
622     - the time in seconds at which to snapshot the CSS property
623     - the id of the element on which to get the CSS property value
624     - the name of the CSS property to get [1]
625     - the expected value for the CSS property
626     - the tolerance to use when comparing the effective CSS property value with its expected value
627
628     [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,
629     or a string which will be compared directly (useful if the expected value is "none")
630     If the CSS property name is "-webkit-transform.N", expected value must be a number corresponding to the Nth element of the matrix
631
632 */
633 function runTransitionTest(expected, trigger, callbacks, doPixelTest, disablePauseAnimationAPI) {
634     isTransitionsTest = true;
635     runAnimationTest(expected, callbacks, trigger, disablePauseAnimationAPI, doPixelTest);
636 }