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

Side by Side Diff: LayoutTests/animations/resources/animation-test-helpers.js

Issue 15738009: Beat the transition tests with a sanity stick. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: More better. 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
« no previous file with comments | « no previous file | LayoutTests/compositing/animation/animated-composited-inside-hidden.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* This is the helper function to run animation tests: 1 /* This is the helper function to run 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 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) 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
(...skipping 22 matching lines...) Expand all
33 If the CSS property name is "webkitTransform.N", expected value must be a nu mber corresponding to the Nth element of the matrix 33 If the CSS property name is "webkitTransform.N", expected value must be a nu mber corresponding to the Nth element of the matrix
34 34
35 */ 35 */
36 36
37 function isCloseEnough(actual, desired, tolerance) 37 function isCloseEnough(actual, desired, tolerance)
38 { 38 {
39 var diff = Math.abs(actual - desired); 39 var diff = Math.abs(actual - desired);
40 return diff <= tolerance; 40 return diff <= tolerance;
41 } 41 }
42 42
43 function roundNumber(num, decimalPlaces)
44 {
45 return Math.round(num * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPla ces);
46 }
47
43 function matrixStringToArray(s) 48 function matrixStringToArray(s)
44 { 49 {
45 if (s == "none") 50 if (s == "none")
46 return [ 1, 0, 0, 1, 0, 0 ]; 51 return [ 1, 0, 0, 1, 0, 0 ];
47 var m = s.split("("); 52 var m = s.split("(");
48 m = m[1].split(")"); 53 m = m[1].split(")");
49 return m[0].split(","); 54 return m[0].split(",");
50 } 55 }
51 56
52 function parseCrossFade(s) 57 function parseCrossFade(s)
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 268
264 if (comparePropertyValue(property, computedValue, expectedValue, toleran ce)) 269 if (comparePropertyValue(property, computedValue, expectedValue, toleran ce))
265 result += "PASS - \"" + property + "\" property for \"" + elementNam e + "\" element at " + time + 270 result += "PASS - \"" + property + "\" property for \"" + elementNam e + "\" element at " + time +
266 "s saw something close to: " + expectedValue + "<br> "; 271 "s saw something close to: " + expectedValue + "<br> ";
267 else 272 else
268 result += "FAIL - \"" + property + "\" property for \"" + elementNam e + "\" element at " + time + 273 result += "FAIL - \"" + property + "\" property for \"" + elementNam e + "\" element at " + time +
269 "s expected: " + expectedValue + " but saw: " + comp utedValue + "<br>"; 274 "s expected: " + expectedValue + " but saw: " + comp utedValue + "<br>";
270 } 275 }
271 } 276 }
272 277
278 function compareRGB(rgb, expected, tolerance)
279 {
280 return (isCloseEnough(parseInt(rgb[0]), expected[0], tolerance) &&
281 isCloseEnough(parseInt(rgb[1]), expected[1], tolerance) &&
282 isCloseEnough(parseInt(rgb[2]), expected[2], tolerance));
283 }
284
285 function parseCrossFade(s)
286 {
287 var matches = s.match("-webkit-cross-fade\\((.*)\\s*,\\s*(.*)\\s*,\\s*(.*)\\ )");
288
289 if (!matches)
290 return null;
291
292 return {"from": matches[1], "to": matches[2], "percent": parseFloat(matches[ 3])}
293 }
294
295 function checkExpectedTransitionValue(expected, index)
Steve Block 2013/05/23 03:47:09 Have you changed this function at all from transit
dstockwell 2013/05/23 03:59:33 Only some trivial changes, inlining some simple fu
296 {
297 expected[index].shift();
298 var time = expected[index][0];
299 var elementId = expected[index][1];
300 var property = expected[index][2];
301 var expectedValue = expected[index][3];
302 var tolerance = expected[index][4];
303 var postCompletionCallback = expected[index][5];
304
305 var computedValue;
306 var pass = false;
307 var transformRegExp = /^-webkit-transform(\.\d+)?$/;
308 if (transformRegExp.test(property)) {
309 computedValue = window.getComputedStyle(document.getElementById(elementI d)).webkitTransform;
310 if (typeof expectedValue == "string")
311 pass = (computedValue == expectedValue);
312 else if (typeof expectedValue == "number") {
313 var m = computedValue.split("(");
314 var m = m[1].split(",");
315 pass = isCloseEnough(parseFloat(m[parseInt(property.substring(18))]) , expectedValue, tolerance);
316 } else {
317 var m = computedValue.split("(");
318 var m = m[1].split(",");
319 for (i = 0; i < expectedValue.length; ++i) {
320 pass = isCloseEnough(parseFloat(m[i]), expectedValue[i], toleran ce);
321 if (!pass)
322 break;
323 }
324 }
325 } else if (property == "fill" || property == "stroke") {
326 computedValue = window.getComputedStyle(document.getElementById(elementI d)).getPropertyCSSValue(property).rgbColor;
327 if (compareRGB([computedValue.red.cssText, computedValue.green.cssText, computedValue.blue.cssText], expectedValue, tolerance))
328 pass = true;
329 else {
330 // We failed. Make sure computed value is something we can read in t he error message
331 computedValue = window.getComputedStyle(document.getElementById(elem entId)).getPropertyCSSValue(property).cssText;
332 }
333 } else if (property == "stop-color" || property == "flood-color" || property == "lighting-color") {
334 computedValue = window.getComputedStyle(document.getElementById(elementI d)).getPropertyCSSValue(property);
335 // The computedValue cssText is rgb(num, num, num)
336 var components = computedValue.cssText.split("(")[1].split(")")[0].split (",");
337 if (compareRGB(components, expectedValue, tolerance))
338 pass = true;
339 else {
340 // We failed. Make sure computed value is something we can read in t he error message
341 computedValue = computedValue.cssText;
342 }
343 } else if (property == "lineHeight") {
344 computedValue = parseInt(window.getComputedStyle(document.getElementById (elementId)).lineHeight);
345 pass = isCloseEnough(computedValue, expectedValue, tolerance);
346 } else if (property == "background-image"
347 || property == "border-image-source"
348 || property == "border-image"
349 || property == "list-style-image"
350 || property == "-webkit-mask-image"
351 || property == "-webkit-mask-box-image") {
352 if (property == "border-image" || property == "-webkit-mask-image" || pr operty == "-webkit-mask-box-image")
353 property += "-source";
354
355 computedValue = window.getComputedStyle(document.getElementById(elementI d)).getPropertyCSSValue(property).cssText;
356 computedCrossFade = parseCrossFade(computedValue);
357
358 if (!computedCrossFade) {
359 pass = false;
360 } else {
361 pass = isCloseEnough(computedCrossFade.percent, expectedValue, toler ance);
362 }
363 } else {
364 var computedStyle = window.getComputedStyle(document.getElementById(elem entId)).getPropertyCSSValue(property);
365 if (computedStyle.cssValueType == CSSValue.CSS_VALUE_LIST) {
366 var values = [];
367 for (var i = 0; i < computedStyle.length; ++i) {
368 switch (computedStyle[i].cssValueType) {
369 case CSSValue.CSS_PRIMITIVE_VALUE:
370 values.push(computedStyle[i].getFloatValue(CSSPrimitiveValue .CSS_NUMBER));
371 break;
372 case CSSValue.CSS_CUSTOM:
373 // arbitrarily pick shadow-x and shadow-y
374 if (property == 'box-shadow' || property == 'text-shadow') {
375 var text = computedStyle[i].cssText;
376 // Shadow cssText looks like "rgb(0, 0, 255) 0px -3px 10px 0px"
377 var shadowPositionRegExp = /\)\s*(-?\d+)px\s*(-?\d+)px/;
378 var match = shadowPositionRegExp.exec(text);
379 var shadowXY = [parseInt(match[1]), parseInt(match[2])];
380 values.push(shadowXY[0]);
381 values.push(shadowXY[1]);
382 } else
383 values.push(computedStyle[i].cssText);
384 break;
385 }
386 }
387 computedValue = values.join(',');
388 pass = true;
389 for (var i = 0; i < values.length; ++i)
390 pass &= isCloseEnough(values[i], expectedValue[i], tolerance);
391 } else if (computedStyle.cssValueType == CSSValue.CSS_PRIMITIVE_VALUE) {
392 switch (computedStyle.primitiveType) {
393 case CSSPrimitiveValue.CSS_STRING:
394 case CSSPrimitiveValue.CSS_IDENT:
395 computedValue = computedStyle.getStringValue();
396 pass = computedValue == expectedValue;
397 break;
398 case CSSPrimitiveValue.CSS_RGBCOLOR:
399 var rgbColor = computedStyle.getRGBColorValue();
400 computedValue = [rgbColor.red.getFloatValue(CSSPrimitiveValu e.CSS_NUMBER),
401 rgbColor.green.getFloatValue(CSSPrimitiveVa lue.CSS_NUMBER),
402 rgbColor.blue.getFloatValue(CSSPrimitiveVal ue.CSS_NUMBER)]; // alpha is not exposed to JS
403 pass = true;
404 for (var i = 0; i < 3; ++i)
405 pass &= isCloseEnough(computedValue[i], expectedValue[i] , tolerance);
406 break;
407 case CSSPrimitiveValue.CSS_RECT:
408 computedValue = computedStyle.getRectValue();
409 computedValue = [computedValue.top.getFloatValue(CSSPrimitiv eValue.CSS_NUMBER),
410 computedValue.right.getFloatValue(CSSPrimit iveValue.CSS_NUMBER),
411 computedValue.bottom.getFloatValue(CSSPrimi tiveValue.CSS_NUMBER),
412 computedValue.left.getFloatValue(CSSPrimiti veValue.CSS_NUMBER)];
413 pass = true;
414 for (var i = 0; i < 4; ++i)
415 pass &= isCloseEnough(computedValue[i], expectedValue[i ], tolerance);
416 break;
417 case CSSPrimitiveValue.CSS_PERCENTAGE:
418 computedValue = parseFloat(computedStyle.cssText);
419 pass = isCloseEnough(computedValue, expectedValue, tolerance );
420 break;
421 default:
422 computedValue = computedStyle.getFloatValue(CSSPrimitiveValu e.CSS_NUMBER);
423 pass = isCloseEnough(computedValue, expectedValue, tolerance );
424 }
425 }
426 }
427
428 if (pass)
429 result += "PASS - \"" + property + "\" property for \"" + elementId + "\ " element at " + time + "s saw something close to: " + expectedValue + "<br>";
430 else
431 result += "FAIL - \"" + property + "\" property for \"" + elementId + "\ " element at " + time + "s expected: " + expectedValue + " but saw: " + computed Value + "<br>";
432
433 if (postCompletionCallback)
434 result += postCompletionCallback();
435 }
436
273 437
274 function getPropertyValue(property, elementId, iframeId) 438 function getPropertyValue(property, elementId, iframeId)
275 { 439 {
276 var computedValue; 440 var computedValue;
277 var element; 441 var element;
278 if (iframeId) 442 if (iframeId)
279 element = document.getElementById(iframeId).contentDocument.getElementBy Id(elementId); 443 element = document.getElementById(iframeId).contentDocument.getElementBy Id(elementId);
280 else 444 else
281 element = document.getElementById(elementId); 445 element = document.getElementById(elementId);
282 446
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 if (hasPauseAnimationAPI) 559 if (hasPauseAnimationAPI)
396 runChecksWithPauseAPI(checks); 560 runChecksWithPauseAPI(checks);
397 else 561 else
398 runChecksWithRAF(checks); 562 runChecksWithRAF(checks);
399 } 563 }
400 564
401 var useResultElement = false; 565 var useResultElement = false;
402 var result = ""; 566 var result = "";
403 var hasPauseAnimationAPI; 567 var hasPauseAnimationAPI;
404 var animStartTime; 568 var animStartTime;
569 var isTransitionsTest = false;
570
571 var usePauseAPI = true;
572 var dontUsePauseAPI = false;
573 var shouldBeTransitioning = 'should-be-transitioning';
574 var shouldNotBeTransitioning = 'should-not-be-transitioning';
405 575
406 // FIXME: remove deprecatedEvent, disablePauseAnimationAPI and doPixelTest 576 // FIXME: remove deprecatedEvent, disablePauseAnimationAPI and doPixelTest
407 function runAnimationTest(expected, callbacks, deprecatedEvent, disablePauseAnim ationAPI, doPixelTest) 577 function runAnimationTest(expected, callbacks, deprecatedEvent, disablePauseAnim ationAPI, doPixelTest)
408 { 578 {
409 if (disablePauseAnimationAPI) 579 if (disablePauseAnimationAPI)
410 result += 'Warning this test is running in real-time and may be flaky.<b r>'; 580 result += 'Warning this test is running in real-time and may be flaky.<b r>';
411 if (deprecatedEvent) 581 if (deprecatedEvent)
412 throw 'Event argument is deprecated!'; 582 throw 'Event argument is deprecated!';
413 if (!expected) 583 if (!expected)
414 throw "Expected results are missing!"; 584 throw "Expected results are missing!";
415 585
416 hasPauseAnimationAPI = 'internals' in window; 586 hasPauseAnimationAPI = 'internals' in window;
417 if (disablePauseAnimationAPI) 587 if (disablePauseAnimationAPI)
418 hasPauseAnimationAPI = false; 588 hasPauseAnimationAPI = false;
419 589
420 var checks = {}; 590 var checks = {};
591 var trigger = function() {};
421 592
422 if (typeof callbacks == 'function') 593 if (isTransitionsTest) {
594 var transitionTrigger = callbacks;
595 callbacks = null;
596 trigger = function() {
597 transitionTrigger();
598 document.body.offsetTop
599 if (window.testRunner)
600 testRunner.display();
601 };
602 }
603
604 if (typeof callbacks == 'function') {
423 checks[0] = [callbacks]; 605 checks[0] = [callbacks];
424 else for (var time in callbacks) { 606 } else for (var time in callbacks) {
425 timeMs = Math.round(time * 1000); 607 timeMs = Math.round(time * 1000);
426 checks[timeMs] = [callbacks[time]]; 608 checks[timeMs] = [callbacks[time]];
427 } 609 }
428 610
429 for (var i = 0; i < expected.length; i++) { 611 for (var i = 0; i < expected.length; i++) {
430 var expectation = expected[i]; 612 var expectation = expected[i];
431 var timeMs = Math.round(expectation[1] * 1000); 613 var timeMs = Math.round(expectation[1] * 1000);
432 if (!checks[timeMs]) 614 if (!checks[timeMs])
433 checks[timeMs] = []; 615 checks[timeMs] = [];
434 checks[timeMs].push(checkExpectedValue.bind(null, expected, i)); 616 if (isTransitionsTest)
617 checks[timeMs].push(checkExpectedTransitionValue.bind(null, expected , i));
618 else
619 checks[timeMs].push(checkExpectedValue.bind(null, expected, i));
435 } 620 }
436 621
437 var doPixelTest = Boolean(doPixelTest); 622 var doPixelTest = Boolean(doPixelTest);
438 useResultElement = doPixelTest; 623 useResultElement = doPixelTest;
439 624
440 if (window.testRunner) { 625 if (window.testRunner) {
441 testRunner.dumpAsText(doPixelTest); 626 testRunner.dumpAsText(doPixelTest);
442 testRunner.waitUntilDone(); 627 testRunner.waitUntilDone();
443 } 628 }
444 629
445 var started = false; 630 var started = false;
446 document.addEventListener('webkitAnimationStart', function() { 631 var target = isTransitionsTest ? window : document;
632 var event = isTransitionsTest ? 'load' : 'webkitAnimationStart';
633 target.addEventListener(event, function() {
447 if (!started) { 634 if (!started) {
448 started = true; 635 started = true;
636 trigger();
449 animStartTime = performance.now(); 637 animStartTime = performance.now();
450 // delay to give hardware animations a chance to start 638 // delay to give hardware animations a chance to start
451 setTimeout(function() { 639 setTimeout(function() {
452 startTest(checks); 640 startTest(checks);
453 }, 0); 641 }, 0);
454 } 642 }
455 }, false); 643 }, false);
456 } 644 }
645
646 /* This is the helper function to run transition tests:
647
648 Test page requirements:
649 - The body must contain an empty div with id "result"
650 - Call this function directly from the <script> inside the test page
651
652 Function parameters:
653 expected [required]: an array of arrays defining a set of CSS properties tha t must have given values at specific times (see below)
654 callback [optional]: a function to be executed just before the test starts ( none by default)
655
656 Each sub-array must contain these items in this order:
657 - the time in seconds at which to snapshot the CSS property
658 - the id of the element on which to get the CSS property value
659 - the name of the CSS property to get [1]
660 - the expected value for the CSS property
661 - the tolerance to use when comparing the effective CSS property value with its expected value
662
663 [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,
664 or a string which will be compared directly (useful if the expected value is "none")
665 If the CSS property name is "-webkit-transform.N", expected value must be a number corresponding to the Nth element of the matrix
666
667 */
668 function runTransitionTest(expected, callback, usePauseAPI, doPixelTest) {
669 expected = expected.map(function(expectation) { expectation.unshift(null); r eturn expectation; });
670 isTransitionsTest = true;
671 runAnimationTest(expected, callback, undefined, usePauseAPI !== true, doPixe lTest);
Steve Block 2013/05/23 03:47:09 Regarding usePauseAPI, are there really cases wher
dstockwell 2013/05/23 03:59:33 Done.
672 }
OLDNEW
« no previous file with comments | « no previous file | LayoutTests/compositing/animation/animated-composited-inside-hidden.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698