<!doctype html> <meta charset=utf-8> <script src="../testcommon.js"></script> <style> @keyframes moveAnimation { from { margin-left: 100px } to { margin-left: 200px } } </style> <body> <script> 'use strict'; // -------------------- // delay // -------------------- test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().delay, 0, 'Initial value of delay'); }, 'delay of a new animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s -10s'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().delay, -10 * MS_PER_SEC, 'Initial value of delay'); }, 'Negative delay of a new animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s 10s'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().delay, 10 * MS_PER_SEC, 'Initial value of delay'); }, 'Positive delay of a new animation'); // -------------------- // endDelay // -------------------- test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().endDelay, 0, 'Initial value of endDelay'); }, 'endDelay of a new animation'); // -------------------- // fill // -------------------- test(function(t) { var getEffectWithFill = function(fill) { var div = addDiv(t, {style: 'animation: moveAnimation 100s ' + fill}); return div.getAnimations()[0].effect; }; var effect = getEffectWithFill(''); assert_equals(effect.getComputedTiming().fill, 'none', 'Initial value of fill'); effect = getEffectWithFill('forwards'); assert_equals(effect.getComputedTiming().fill, 'forwards', 'Fill forwards'); effect = getEffectWithFill('backwards'); assert_equals(effect.getComputedTiming().fill, 'backwards', 'Fill backwards'); effect = getEffectWithFill('both'); assert_equals(effect.getComputedTiming().fill, 'both', 'Fill forwards and backwards'); }, 'fill of a new animation'); // -------------------- // iterationStart // -------------------- test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().iterationStart, 0, 'Initial value of iterationStart'); }, 'iterationStart of a new animation'); // -------------------- // iterations // -------------------- test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().iterations, 1, 'Initial value of iterations'); }, 'iterations of a new animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s 2016.5'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().iterations, 2016.5, 'Initial value of iterations'); }, 'iterations of a finitely repeating animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s infinite'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().iterations, Infinity, 'Initial value of iterations'); }, 'iterations of an infinitely repeating animation'); // -------------------- // duration // -------------------- test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s -10s infinite'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().duration, 100 * MS_PER_SEC, 'Initial value of duration'); }, 'duration of a new animation'); // -------------------- // direction // -------------------- test(function(t) { var getEffectWithDir = function(dir) { var div = addDiv(t, {style: 'animation: moveAnimation 100s ' + dir}); return div.getAnimations()[0].effect; }; var effect = getEffectWithDir(''); assert_equals(effect.getComputedTiming().direction, 'normal', 'Initial value of normal direction'); effect = getEffectWithDir('reverse'); assert_equals(effect.getComputedTiming().direction, 'reverse', 'Initial value of reverse direction'); effect = getEffectWithDir('alternate'); assert_equals(effect.getComputedTiming().direction, 'alternate', 'Initial value of alternate direction'); effect = getEffectWithDir('alternate-reverse'); assert_equals(effect.getComputedTiming().direction, 'alternate-reverse', 'Initial value of alternate-reverse direction'); }, 'direction of a new animation'); // -------------------- // easing // -------------------- test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().easing, 'linear', 'Initial value of easing'); }, 'easing of a new animation'); // ------------------------------ // endTime // = max(start delay + active duration + end delay, 0) // -------------------- test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().endTime, 100 * MS_PER_SEC, 'Initial value of endTime'); }, 'endTime of an new animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s -5s'}); var effect = div.getAnimations()[0].effect; var answer = (100 - 5) * MS_PER_SEC; assert_equals(effect.getComputedTiming().endTime, answer, 'Initial value of endTime'); }, 'endTime of an animation with a negative delay'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 10s -100s infinite'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().endTime, Infinity, 'Initial value of endTime'); }, 'endTime of an infinitely repeating animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 0s 100s infinite'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().endTime, 100 * MS_PER_SEC, 'Initial value of endTime'); }, 'endTime of an infinitely repeating zero-duration animation'); test(function(t) { // Fill forwards so div.getAnimations()[0] won't return an // undefined value. var div = addDiv(t, {style: 'animation: moveAnimation 10s -100s forwards'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().endTime, 0, 'Initial value of endTime'); }, 'endTime of an animation that finishes before its startTime'); // -------------------- // activeDuration // = iteration duration * iteration count // -------------------- test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s 5'}); var effect = div.getAnimations()[0].effect; var answer = 100 * MS_PER_SEC * 5; assert_equals(effect.getComputedTiming().activeDuration, answer, 'Initial value of activeDuration'); }, 'activeDuration of a new animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s infinite'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().activeDuration, Infinity, 'Initial value of activeDuration'); }, 'activeDuration of an infinitely repeating animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 0s 1s infinite'}); var effect = div.getAnimations()[0].effect; // If either the iteration duration or iteration count are zero, // the active duration is zero. assert_equals(effect.getComputedTiming().activeDuration, 0, 'Initial value of activeDuration'); }, 'activeDuration of an infinitely repeating zero-duration animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s 1s 0'}); var effect = div.getAnimations()[0].effect; // If either the iteration duration or iteration count are zero, // the active duration is zero. assert_equals(effect.getComputedTiming().activeDuration, 0, 'Initial value of activeDuration'); }, 'activeDuration of an animation with zero iterations'); // -------------------- // localTime // -------------------- test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().localTime, 0, 'Initial value of localTime'); }, 'localTime of a new animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s'}); var anim = div.getAnimations()[0]; anim.currentTime = 5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().localTime, anim.currentTime, 'current localTime after setting currentTime'); }, 'localTime of an animation is always equal to currentTime'); promise_test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s'}); var anim = div.getAnimations()[0]; anim.playbackRate = 2; // 2 times faster return anim.ready.then(function() { assert_equals(anim.effect.getComputedTiming().localTime, anim.currentTime, 'localTime is equal to currentTime'); return waitForFrame(); }).then(function() { assert_equals(anim.effect.getComputedTiming().localTime, anim.currentTime, 'localTime is equal to currentTime'); }); }, 'localTime reflects playbackRate immediately'); test(function(t) { var div = addDiv(t); var effect = new KeyframeEffectReadOnly(div, {left: ["0px", "100px"]}); assert_equals(effect.getComputedTiming().localTime, null, 'localTime for orphaned effect'); }, 'localTime of an AnimationEffect without an Animation'); // -------------------- // progress // Note: Default timing function is linear. // -------------------- test(function(t) { [{fill: '', progress: [ null, null ]}, {fill: 'none', progress: [ null, null ]}, {fill: 'forwards', progress: [ null, 1.0 ]}, {fill: 'backwards', progress: [ 0.0, null ]}, {fill: 'both', progress: [ 0.0, 1.0 ]}] .forEach(function(test) { var div = addDiv(t, {style: 'animation: moveAnimation 100s 10s ' + test.fill}); var anim = div.getAnimations()[0]; assert_true(anim.effect.getComputedTiming().progress === test.progress[0], 'initial progress with "' + test.fill + '" fill'); anim.finish(); assert_true(anim.effect.getComputedTiming().progress === test.progress[1], 'finished progress with "' + test.fill + '" fill'); }); }, 'progress of an animation with different fill modes'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 10s 10 both'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().progress, 0.0, 'Initial value of progress'); anim.currentTime += 2.5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.25, 'Value of progress'); anim.currentTime += 5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.75, 'Value of progress'); anim.currentTime += 5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.25, 'Value of progress'); anim.finish() assert_equals(anim.effect.getComputedTiming().progress, 1.0, 'Value of progress'); }, 'progress of an integral repeating animation with normal direction'); test(function(t) { var div = addDiv(t); // Note: FillMode here is "both" because // 1. Since this a zero-duration animation, it will already have finished // so it won't be returned by getAnimations() unless it fills forwards. // 2. Fill backwards, so the progress before phase wouldn't be // unresolved (null value). var div = addDiv(t, {style: 'animation: moveAnimation 0s infinite both'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().progress, 1.0, 'Initial value of progress in after phase'); // Seek backwards anim.currentTime -= 1 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.0, 'Value of progress before phase'); }, 'progress of an infinitely repeating zero-duration animation'); test(function(t) { // Default iterations = 1 var div = addDiv(t, {style: 'animation: moveAnimation 0s both'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().progress, 1.0, 'Initial value of progress in after phase'); // Seek backwards anim.currentTime -= 1 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.0, 'Value of progress before phase'); }, 'progress of a finitely repeating zero-duration animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 0s 5s 10.25 both'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().progress, 0.0, 'Initial value of progress (before phase)'); // Using iteration duration of 1 now. // currentIteration now is floor(10.25) = 10, so progress should be 25%. anim.finish(); assert_equals(anim.effect.getComputedTiming().progress, 0.25, 'Value of progress in after phase'); }, 'progress of a non-integral repeating zero-duration animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 0s 5s 10.25 both reverse'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().progress, 1.0, 'Initial value of progress (before phase)'); // Seek forwards anim.finish(); assert_equals(anim.effect.getComputedTiming().progress, 0.75, 'Value of progress in after phase'); }, 'Progress of a non-integral repeating zero-duration animation ' + 'with reversing direction'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 10s 10.25 both alternate'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().progress, 0.0, 'Initial value of progress'); anim.currentTime += 2.5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.25, 'Value of progress'); anim.currentTime += 5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.75, 'Value of progress'); anim.currentTime += 5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.75, 'Value of progress'); anim.finish() assert_equals(anim.effect.getComputedTiming().progress, 0.25, 'Value of progress'); }, 'progress of a non-integral repeating animation ' + 'with alternate direction'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 10s 10.25 both alternate-reverse'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().progress, 1.0, 'Initial value of progress'); anim.currentTime += 2.5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.75, 'Value of progress'); anim.currentTime += 5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.25, 'Value of progress'); anim.currentTime += 5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.25, 'Value of progress'); anim.finish() assert_equals(anim.effect.getComputedTiming().progress, 0.75, 'Value of progress'); }, 'progress of a non-integral repeating animation ' + 'with alternate-reversing direction'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 0s 10.25 both alternate'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().progress, 0.25, 'Initial value of progress'); anim.currentTime += 2.5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.25, 'Value of progress'); anim.currentTime -= 5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.0, 'Value of progress'); anim.finish() assert_equals(anim.effect.getComputedTiming().progress, 0.25, 'Value of progress'); }, 'progress of a non-integral repeating zero-duration animation ' + 'with alternate direction'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 0s 10.25 both alternate-reverse'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().progress, 0.75, 'Initial value of progress'); anim.currentTime += 2.5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 0.75, 'Value of progress'); anim.currentTime -= 5 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().progress, 1.0, 'Value of progress'); anim.finish() assert_equals(anim.effect.getComputedTiming().progress, 0.75, 'Value of progress'); }, 'progress of a non-integral repeating zero-duration animation ' + 'with alternate-reverse direction'); // -------------------- // currentIteration // -------------------- test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s 2s'}); var effect = div.getAnimations()[0].effect; assert_equals(effect.getComputedTiming().currentIteration, null, 'Initial value of currentIteration before phase'); }, 'currentIteration of a new animation with no backwards fill is unresolved ' + 'in before phase'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().currentIteration, 0, 'Initial value of currentIteration'); }, 'currentIteration of a new animation is zero'); test(function(t) { // Note: FillMode here is "both" because // 1. Since this a zero-duration animation, it will already have finished // so it won't be returned by getAnimations() unless it fills forwards. // 2. Fill backwards, so the currentIteration (before phase) wouldn't be // unresolved (null value). var div = addDiv(t, {style: 'animation: moveAnimation 0s infinite both'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().currentIteration, Infinity, 'Initial value of currentIteration in after phase'); // Seek backwards anim.currentTime -= 2 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().currentIteration, 0, 'Value of currentIteration count during before phase'); }, 'currentIteration of an infinitely repeating zero-duration animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 0s 10.5 both'}); var anim = div.getAnimations()[0]; // Note: currentIteration = ceil(iteration start + iteration count) - 1 assert_equals(anim.effect.getComputedTiming().currentIteration, 10, 'Initial value of currentIteration'); // Seek backwards anim.currentTime -= 2 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().currentIteration, 0, 'Value of currentIteration count during before phase'); }, 'currentIteration of a finitely repeating zero-duration animation'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s 5.5 forwards'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().currentIteration, 0, 'Initial value of currentIteration'); // The 3rd iteration // Note: currentIteration = floor(scaled active time / iteration duration) anim.currentTime = 250 * MS_PER_SEC; assert_equals(anim.effect.getComputedTiming().currentIteration, 2, 'Value of currentIteration during the 3rd iteration'); // Finish anim.finish(); assert_equals(anim.effect.getComputedTiming().currentIteration, 5, 'Value of currentIteration in after phase'); }, 'currentIteration of an animation with a non-integral iteration count'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s 2 forwards'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().currentIteration, 0, 'Initial value of currentIteration'); // Finish anim.finish(); assert_equals(anim.effect.getComputedTiming().currentIteration, 1, 'Value of currentIteration in after phase'); }, 'currentIteration of an animation with an integral iteration count'); test(function(t) { var div = addDiv(t, {style: 'animation: moveAnimation 100s forwards'}); var anim = div.getAnimations()[0]; assert_equals(anim.effect.getComputedTiming().currentIteration, 0, 'Initial value of currentIteration'); // Finish anim.finish(); assert_equals(anim.effect.getComputedTiming().currentIteration, 0, 'Value of currentIteration in after phase'); }, 'currentIteration of an animation with a default iteration count'); test(function(t) { var div = addDiv(t); var effect = new KeyframeEffectReadOnly(div, {left: ["0px", "100px"]}); assert_equals(effect.getComputedTiming().currentIteration, null, 'currentIteration for orphaned effect'); }, 'currentIteration of an AnimationEffect without an Animation'); // TODO: If iteration duration is Infinity, currentIteration is 0. // However, we cannot set iteration duration to Infinity in CSS Animation now. done(); </script> </body>