| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2015 Google Inc. All rights reserved. | 2 * Copyright (C) 2015 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 * generated according to each interpolation method's handling of values | 43 * generated according to each interpolation method's handling of values |
| 44 * that don't interpolate. | 44 * that don't interpolate. |
| 45 * - assertComposition({property, underlying, [addFrom], [addTo], [replaceFrom]
, [replaceTo]}, [{at: fraction, is: value}]) | 45 * - assertComposition({property, underlying, [addFrom], [addTo], [replaceFrom]
, [replaceTo]}, [{at: fraction, is: value}]) |
| 46 * Similar to assertInterpolation() instead using only the Web Animations
API | 46 * Similar to assertInterpolation() instead using only the Web Animations
API |
| 47 * to animate composite specified keyframes (add or replace) on top of | 47 * to animate composite specified keyframes (add or replace) on top of |
| 48 * an underlying value. | 48 * an underlying value. |
| 49 * Exactly one of (addFrom, replaceFrom) must be specified. | 49 * Exactly one of (addFrom, replaceFrom) must be specified. |
| 50 * Exactly one of (addTo, replaceTo) must be specified. | 50 * Exactly one of (addTo, replaceTo) must be specified. |
| 51 * - afterTest(callback) | 51 * - afterTest(callback) |
| 52 * Calls callback after all the tests have executed. | 52 * Calls callback after all the tests have executed. |
| 53 * |
| 54 * The following object is exported: |
| 55 * - neutralKeyframe |
| 56 * Can be used as the from/to value to use a neutral keyframe. |
| 53 */ | 57 */ |
| 54 'use strict'; | 58 'use strict'; |
| 55 (function() { | 59 (function() { |
| 56 var interpolationTests = []; | 60 var interpolationTests = []; |
| 57 var compositionTests = []; | 61 var compositionTests = []; |
| 58 var cssAnimationsData = { | 62 var cssAnimationsData = { |
| 59 sharedStyle: null, | 63 sharedStyle: null, |
| 60 nextID: 0, | 64 nextID: 0, |
| 61 }; | 65 }; |
| 62 var webAnimationsEnabled = typeof Element.prototype.animate === 'function'; | 66 var webAnimationsEnabled = typeof Element.prototype.animate === 'function'; |
| 63 var expectNoInterpolation = {}; | 67 var expectNoInterpolation = {}; |
| 64 var afterTestHook = function() {}; | 68 var afterTestHook = function() {}; |
| 69 var neutralKeyframe = {}; |
| 70 function isNeutralKeyframe(keyframe) { |
| 71 return keyframe === neutralKeyframe; |
| 72 } |
| 65 | 73 |
| 66 var cssAnimationsInterpolation = { | 74 var cssAnimationsInterpolation = { |
| 67 name: 'CSS Animations', | 75 name: 'CSS Animations', |
| 68 supportsProperty: function() {return true;}, | 76 supportsProperty: function() {return true;}, |
| 69 supportsValue: function() {return true;}, | 77 supportsValue: function() {return true;}, |
| 70 setup: function() {}, | 78 setup: function() {}, |
| 71 nonInterpolationExpectations: function(from, to) { | 79 nonInterpolationExpectations: function(from, to) { |
| 72 return expectFlip(from, to, 0.5); | 80 return expectFlip(from, to, 0.5); |
| 73 }, | 81 }, |
| 74 interpolate: function(property, from, to, at, target) { | 82 interpolate: function(property, from, to, at, target) { |
| 75 var id = cssAnimationsData.nextID++; | 83 var id = cssAnimationsData.nextID++; |
| 76 if (!cssAnimationsData.sharedStyle) { | 84 if (!cssAnimationsData.sharedStyle) { |
| 77 cssAnimationsData.sharedStyle = createElement(document.body, 'style'); | 85 cssAnimationsData.sharedStyle = createElement(document.body, 'style'); |
| 78 } | 86 } |
| 79 cssAnimationsData.sharedStyle.textContent += '' + | 87 cssAnimationsData.sharedStyle.textContent += '' + |
| 80 '@keyframes animation' + id + ' {' + | 88 '@keyframes animation' + id + ' {' + |
| 81 'from {' + property + ': ' + from + ';}' + | 89 (isNeutralKeyframe(from) ? '' : `from {${property}: ${from};}`) + |
| 82 'to {' + property + ': ' + to + ';}' + | 90 (isNeutralKeyframe(to) ? '' : `to {${property}: ${to};}`) + |
| 83 '}'; | 91 '}'; |
| 84 target.style.animationName = 'animation' + id; | 92 target.style.animationName = 'animation' + id; |
| 85 target.style.animationDuration = '2e10s'; | 93 target.style.animationDuration = '2e10s'; |
| 86 target.style.animationDelay = '-1e10s'; | 94 target.style.animationDelay = '-1e10s'; |
| 87 target.style.animationTimingFunction = createEasing(at); | 95 target.style.animationTimingFunction = createEasing(at); |
| 88 }, | 96 }, |
| 89 rebaseline: false, | 97 rebaseline: false, |
| 90 }; | 98 }; |
| 91 | 99 |
| 92 var cssTransitionsInterpolation = { | 100 var cssTransitionsInterpolation = { |
| 93 name: 'CSS Transitions', | 101 name: 'CSS Transitions', |
| 94 supportsProperty: function() {return true;}, | 102 supportsProperty: function() {return true;}, |
| 95 supportsValue: function() {return true;}, | 103 supportsValue: function() {return true;}, |
| 96 setup: function(property, from, target) { | 104 setup: function(property, from, target) { |
| 97 target.style[property] = from; | 105 target.style[property] = isNeutralKeyframe(from) ? '' : from; |
| 98 }, | 106 }, |
| 99 nonInterpolationExpectations: function(from, to) { | 107 nonInterpolationExpectations: function(from, to) { |
| 100 return expectFlip(from, to, -Infinity); | 108 return expectFlip(from, to, -Infinity); |
| 101 }, | 109 }, |
| 102 interpolate: function(property, from, to, at, target) { | 110 interpolate: function(property, from, to, at, target) { |
| 103 target.style.transitionDuration = '2e10s'; | 111 target.style.transitionDuration = '2e10s'; |
| 104 target.style.transitionDelay = '-1e10s'; | 112 target.style.transitionDelay = '-1e10s'; |
| 105 target.style.transitionTimingFunction = createEasing(at); | 113 target.style.transitionTimingFunction = createEasing(at); |
| 106 target.style.transitionProperty = property; | 114 target.style.transitionProperty = property; |
| 107 target.style[property] = to; | 115 target.style[property] = isNeutralKeyframe(to) ? '' : to; |
| 108 }, | 116 }, |
| 109 rebaseline: false, | 117 rebaseline: false, |
| 110 }; | 118 }; |
| 111 | 119 |
| 112 var webAnimationsInterpolation = { | 120 var webAnimationsInterpolation = { |
| 113 name: 'Web Animations', | 121 name: 'Web Animations', |
| 114 supportsProperty: function(property) {return property.indexOf('-webkit-') !=
= 0;}, | 122 supportsProperty: function(property) {return property.indexOf('-webkit-') !=
= 0;}, |
| 115 supportsValue: function(value) {return value !== '';}, | 123 supportsValue: function(value) {return value !== '';}, |
| 116 setup: function() {}, | 124 setup: function() {}, |
| 117 nonInterpolationExpectations: function(from, to) { | 125 nonInterpolationExpectations: function(from, to) { |
| 118 return expectFlip(from, to, 0.5); | 126 return expectFlip(from, to, 0.5); |
| 119 }, | 127 }, |
| 120 interpolate: function(property, from, to, at, target) { | 128 interpolate: function(property, from, to, at, target) { |
| 129 this.interpolateComposite(property, from, 'replace', to, 'replace', at, ta
rget); |
| 130 }, |
| 131 interpolateComposite: function(property, from, fromComposite, to, toComposit
e, at, target) { |
| 121 // Convert to camelCase | 132 // Convert to camelCase |
| 122 for (var i = property.length - 2; i > 0; --i) { | 133 for (var i = property.length - 2; i > 0; --i) { |
| 123 if (property[i] === '-') { | 134 if (property[i] === '-') { |
| 124 property = property.substring(0, i) + property[i + 1].toUpperCase() +
property.substring(i + 2); | 135 property = property.substring(0, i) + property[i + 1].toUpperCase() +
property.substring(i + 2); |
| 125 } | 136 } |
| 126 } | 137 } |
| 127 this.interpolateKeyframes([ | 138 var keyframes = []; |
| 128 {offset: 0, [property]: from}, | 139 if (!isNeutralKeyframe(from)) { |
| 129 {offset: 1, [property]: to}, | 140 keyframes.push({ |
| 130 ], at, target); | 141 offset: 0, |
| 131 }, | 142 composite: fromComposite, |
| 132 interpolateKeyframes: function(keyframes, at, target) { | 143 [property]: from, |
| 144 }); |
| 145 } |
| 146 if (!isNeutralKeyframe(to)) { |
| 147 keyframes.push({ |
| 148 offset: 1, |
| 149 composite: toComposite, |
| 150 [property]: to, |
| 151 }); |
| 152 } |
| 133 target.animate(keyframes, { | 153 target.animate(keyframes, { |
| 134 fill: 'forwards', | 154 fill: 'forwards', |
| 135 duration: 1, | 155 duration: 1, |
| 136 easing: createEasing(at), | 156 easing: createEasing(at), |
| 137 delay: -0.5, | 157 delay: -0.5, |
| 138 iterations: 0.5, | 158 iterations: 0.5, |
| 139 }); | 159 }); |
| 140 }, | 160 }, |
| 141 rebaseline: false, | 161 rebaseline: false, |
| 142 }; | 162 }; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 if (options.to) { | 271 if (options.to) { |
| 252 console.assert(CSS.supports(options.property, options.to)); | 272 console.assert(CSS.supports(options.property, options.to)); |
| 253 } | 273 } |
| 254 interpolationTests.push({options, expectations}); | 274 interpolationTests.push({options, expectations}); |
| 255 } | 275 } |
| 256 | 276 |
| 257 function assertComposition(options, expectations) { | 277 function assertComposition(options, expectations) { |
| 258 compositionTests.push({options, expectations}); | 278 compositionTests.push({options, expectations}); |
| 259 } | 279 } |
| 260 | 280 |
| 281 function keyframeText(keyframe) { |
| 282 return isNeutralKeyframe(keyframe) ? 'neutral' : `[${keyframe}]`; |
| 283 } |
| 284 |
| 285 function keyframeCode(keyframe) { |
| 286 return isNeutralKeyframe(keyframe) ? 'neutralKeyframe' : `'${keyframe}'`; |
| 287 } |
| 288 |
| 261 function createInterpolationTestTargets(interpolationMethod, interpolationMeth
odContainer, interpolationTest, rebaselineContainer) { | 289 function createInterpolationTestTargets(interpolationMethod, interpolationMeth
odContainer, interpolationTest, rebaselineContainer) { |
| 262 var property = interpolationTest.options.property; | 290 var property = interpolationTest.options.property; |
| 263 var from = interpolationTest.options.from; | 291 var from = interpolationTest.options.from; |
| 264 var to = interpolationTest.options.to; | 292 var to = interpolationTest.options.to; |
| 265 if ((interpolationTest.options.method && interpolationTest.options.method !=
interpolationMethod.name) | 293 if ((interpolationTest.options.method && interpolationTest.options.method !=
interpolationMethod.name) |
| 266 || !interpolationMethod.supportsProperty(property) | 294 || !interpolationMethod.supportsProperty(property) |
| 267 || !interpolationMethod.supportsValue(from) | 295 || !interpolationMethod.supportsValue(from) |
| 268 || !interpolationMethod.supportsValue(to)) { | 296 || !interpolationMethod.supportsValue(to)) { |
| 269 return; | 297 return; |
| 270 } | 298 } |
| 271 if (interpolationMethod.rebaseline) { | 299 if (interpolationMethod.rebaseline) { |
| 272 var rebaseline = createElement(rebaselineContainer, 'pre'); | 300 var rebaseline = createElement(rebaselineContainer, 'pre'); |
| 273 rebaseline.appendChild(document.createTextNode(`\ | 301 rebaseline.appendChild(document.createTextNode(`\ |
| 274 assertInterpolation({ | 302 assertInterpolation({ |
| 275 property: '${property}', | 303 property: '${property}', |
| 276 from: '${from}', | 304 from: ${keyframeCode(from)}, |
| 277 to: '${to}', | 305 to: ${keyframeCode(to)}, |
| 278 }, [\n`)); | 306 }, [\n`)); |
| 279 var rebaselineExpectation; | 307 var rebaselineExpectation; |
| 280 rebaseline.appendChild(rebaselineExpectation = document.createTextNode('')
); | 308 rebaseline.appendChild(rebaselineExpectation = document.createTextNode('')
); |
| 281 rebaseline.appendChild(document.createTextNode(']);\n\n')); | 309 rebaseline.appendChild(document.createTextNode(']);\n\n')); |
| 282 } | 310 } |
| 283 var testText = `${interpolationMethod.name}: property <${property}> from [${
from}] to [${to}]`; | 311 var testText = `${interpolationMethod.name}: property <${property}> from ${k
eyframeText(from)} to ${keyframeText(to)}`; |
| 284 var testContainer = createElement(interpolationMethodContainer, 'div', testT
ext); | 312 var testContainer = createElement(interpolationMethodContainer, 'div', testT
ext); |
| 285 createElement(testContainer, 'br'); | 313 createElement(testContainer, 'br'); |
| 286 var expectations = interpolationTest.expectations; | 314 var expectations = interpolationTest.expectations; |
| 287 if (expectations === expectNoInterpolation) { | 315 if (expectations === expectNoInterpolation) { |
| 288 expectations = interpolationMethod.nonInterpolationExpectations(from, to); | 316 expectations = interpolationMethod.nonInterpolationExpectations(from, to); |
| 289 } | 317 } |
| 290 return expectations.map(function(expectation) { | 318 return expectations.map(function(expectation) { |
| 291 var actualTargetContainer = createTargetContainer(testContainer, 'actual')
; | 319 var actualTargetContainer = createTargetContainer(testContainer, 'actual')
; |
| 292 var expectedTargetContainer = createTargetContainer(testContainer, 'expect
ed'); | 320 var expectedTargetContainer = createTargetContainer(testContainer, 'expect
ed'); |
| 293 expectedTargetContainer.target.style[property] = expectation.is; | 321 expectedTargetContainer.target.style[property] = expectation.is; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 var testText = `Compositing: property <${property}> underlying [${underlying
}] from ${fromComposite} [${from}] to ${toComposite} [${to}]`; | 365 var testText = `Compositing: property <${property}> underlying [${underlying
}] from ${fromComposite} [${from}] to ${toComposite} [${to}]`; |
| 338 var testContainer = createElement(compositionContainer, 'div', testText); | 366 var testContainer = createElement(compositionContainer, 'div', testText); |
| 339 createElement(testContainer, 'br'); | 367 createElement(testContainer, 'br'); |
| 340 return compositionTest.expectations.map(function(expectation) { | 368 return compositionTest.expectations.map(function(expectation) { |
| 341 var actualTargetContainer = createTargetContainer(testContainer, 'actual')
; | 369 var actualTargetContainer = createTargetContainer(testContainer, 'actual')
; |
| 342 var expectedTargetContainer = createTargetContainer(testContainer, 'expect
ed'); | 370 var expectedTargetContainer = createTargetContainer(testContainer, 'expect
ed'); |
| 343 expectedTargetContainer.target.style[property] = expectation.is; | 371 expectedTargetContainer.target.style[property] = expectation.is; |
| 344 var target = actualTargetContainer.target; | 372 var target = actualTargetContainer.target; |
| 345 target.style[property] = underlying; | 373 target.style[property] = underlying; |
| 346 target.interpolate = function() { | 374 target.interpolate = function() { |
| 347 webAnimationsInterpolation.interpolateKeyframes([{ | 375 webAnimationsInterpolation.interpolateComposite(property, from, fromComp
osite, to, toComposite, expectation.at, target); |
| 348 offset: 0, | |
| 349 composite: fromComposite, | |
| 350 [toCamelCase(property)]: from, | |
| 351 }, { | |
| 352 offset: 1, | |
| 353 composite: toComposite, | |
| 354 [toCamelCase(property)]: to, | |
| 355 }], expectation.at, target); | |
| 356 }; | 376 }; |
| 357 target.measure = function() { | 377 target.measure = function() { |
| 358 var actualValue = getComputedStyle(target)[property]; | 378 var actualValue = getComputedStyle(target)[property]; |
| 359 test(function() { | 379 test(function() { |
| 360 assert_equals( | 380 assert_equals( |
| 361 normalizeValue(actualValue), | 381 normalizeValue(actualValue), |
| 362 normalizeValue(getComputedStyle(expectedTargetContainer.target)[prop
erty])); | 382 normalizeValue(getComputedStyle(expectedTargetContainer.target)[prop
erty])); |
| 363 }, `${testText} at (${expectation.at}) is [${sanitizeUrls(actualValue)}]
`); | 383 }, `${testText} at (${expectation.at}) is [${sanitizeUrls(actualValue)}]
`); |
| 364 if (rebaselineExpectation) { | 384 if (rebaselineExpectation) { |
| 365 rebaselineExpectation.textContent += ` {at: ${expectation.at}, is: '$
{actualValue}'},\n`; | 385 rebaselineExpectation.textContent += ` {at: ${expectation.at}, is: '$
{actualValue}'},\n`; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 if (window.testRunner) { | 426 if (window.testRunner) { |
| 407 container.remove(); | 427 container.remove(); |
| 408 } | 428 } |
| 409 afterTestHook(); | 429 afterTestHook(); |
| 410 } | 430 } |
| 411 | 431 |
| 412 function afterTest(f) { | 432 function afterTest(f) { |
| 413 afterTestHook = f; | 433 afterTestHook = f; |
| 414 } | 434 } |
| 415 | 435 |
| 416 window.assertInterpolation = assertInterpolation; | |
| 417 window.assertNoInterpolation = assertNoInterpolation; | |
| 418 window.assertComposition = assertComposition; | |
| 419 window.afterTest = afterTest; | |
| 420 | |
| 421 loadScript('../../resources/testharness.js').then(function() { | 436 loadScript('../../resources/testharness.js').then(function() { |
| 422 return loadScript('../../resources/testharnessreport.js'); | 437 return loadScript('../../resources/testharnessreport.js'); |
| 423 }).then(function() { | 438 }).then(function() { |
| 424 var asyncHandle = async_test('This test uses interpolation-test.js.') | 439 var asyncHandle = async_test('This test uses interpolation-test.js.') |
| 425 requestAnimationFrame(function() { | 440 requestAnimationFrame(function() { |
| 426 runTests(); | 441 runTests(); |
| 427 asyncHandle.done() | 442 asyncHandle.done() |
| 428 }); | 443 }); |
| 429 }); | 444 }); |
| 445 |
| 446 window.assertInterpolation = assertInterpolation; |
| 447 window.assertNoInterpolation = assertNoInterpolation; |
| 448 window.assertComposition = assertComposition; |
| 449 window.afterTest = afterTest; |
| 450 window.neutralKeyframe = neutralKeyframe; |
| 430 })(); | 451 })(); |
| OLD | NEW |