forked from mirrors/gecko-dev
Automatic update from web-platform-tests
Fix getComputedTiming tests
Problem 1: Exact equals on floating point values when comparing values
for currentTime on a running animation. Setting currentTime
actually updates startTime in order to match the desired
value for currentTime, but there may be quantization errors
with the floating point calculations. Animations times are
only required to have microsecond precision.
Problem 2: Composited animations do not spin main frame updates. They
only need to trigger a main frame update at each phase
transition boundary. Thus the localTime value stored in
calculated timing during the last main frame update may be
stale.
Bug: 1197285
Change-Id: I5df4054552899bee29bb2b02bc214f447e1e026d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4080535
Reviewed-by: Mustaq Ahmed <mustaq@chromium.org>
Commit-Queue: Kevin Ellis <kevers@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1082708}
--
wpt-commits: bfb0ced452de30a133edcaead44898acbacffa3f
wpt-pr: 37361
612 lines
22 KiB
HTML
612 lines
22 KiB
HTML
<!doctype html>
|
|
<meta charset=utf-8>
|
|
<title>AnimationEffect.getComputedTiming() for CSS animations</title>
|
|
<!-- TODO: Add a more specific link for this once it is specified. -->
|
|
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#cssanimation">
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script src="support/testcommon.js"></script>
|
|
<style>
|
|
@keyframes moveAnimation {
|
|
from { margin-left: 100px }
|
|
to { margin-left: 200px }
|
|
}
|
|
</style>
|
|
<body>
|
|
<div id="log"></div>
|
|
<script>
|
|
|
|
'use strict';
|
|
|
|
// --------------------
|
|
// delay
|
|
// --------------------
|
|
|
|
test(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s' });
|
|
const effect = div.getAnimations()[0].effect;
|
|
assert_equals(effect.getComputedTiming().delay, 0, 'Initial value of delay');
|
|
}, 'delay of a new animation');
|
|
|
|
test(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s -10s' });
|
|
const 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s 10s' });
|
|
const 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s' });
|
|
const effect = div.getAnimations()[0].effect;
|
|
assert_equals(effect.getComputedTiming().endDelay, 0,
|
|
'Initial value of endDelay');
|
|
}, 'endDelay of a new animation');
|
|
|
|
|
|
// --------------------
|
|
// fill
|
|
// --------------------
|
|
|
|
test(t => {
|
|
const getEffectWithFill = fill => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s ' + fill });
|
|
return div.getAnimations()[0].effect;
|
|
};
|
|
|
|
let 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s' });
|
|
const effect = div.getAnimations()[0].effect;
|
|
assert_equals(effect.getComputedTiming().iterationStart, 0,
|
|
'Initial value of iterationStart');
|
|
}, 'iterationStart of a new animation');
|
|
|
|
|
|
// --------------------
|
|
// iterations
|
|
// --------------------
|
|
|
|
test(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s' });
|
|
const effect = div.getAnimations()[0].effect;
|
|
assert_equals(effect.getComputedTiming().iterations, 1,
|
|
'Initial value of iterations');
|
|
}, 'iterations of a new animation');
|
|
|
|
test(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s 2016.5' });
|
|
const effect = div.getAnimations()[0].effect;
|
|
assert_equals(effect.getComputedTiming().iterations, 2016.5,
|
|
'Initial value of iterations');
|
|
}, 'iterations of a finitely repeating animation');
|
|
|
|
test(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s infinite' });
|
|
const effect = div.getAnimations()[0].effect;
|
|
assert_equals(effect.getComputedTiming().iterations, Infinity,
|
|
'Initial value of iterations');
|
|
}, 'iterations of an infinitely repeating animation');
|
|
|
|
|
|
// --------------------
|
|
// duration
|
|
// --------------------
|
|
|
|
test(t => {
|
|
const div = addDiv(t, {
|
|
style: 'animation: moveAnimation 100s -10s infinite'
|
|
});
|
|
const 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(t => {
|
|
const getEffectWithDir = dir => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s ' + dir });
|
|
return div.getAnimations()[0].effect;
|
|
};
|
|
|
|
let 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s' });
|
|
const 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s' });
|
|
const effect = div.getAnimations()[0].effect;
|
|
assert_equals(effect.getComputedTiming().endTime, 100 * MS_PER_SEC,
|
|
'Initial value of endTime');
|
|
}, 'endTime of an new animation');
|
|
|
|
test(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s -5s' });
|
|
const effect = div.getAnimations()[0].effect;
|
|
const 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(t => {
|
|
const div = addDiv(t, {
|
|
style: 'animation: moveAnimation 10s -100s infinite'
|
|
});
|
|
const effect = div.getAnimations()[0].effect;
|
|
assert_equals(effect.getComputedTiming().endTime, Infinity,
|
|
'Initial value of endTime');
|
|
}, 'endTime of an infinitely repeating animation');
|
|
|
|
test(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 0s 100s infinite' });
|
|
const 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(t => {
|
|
// Fill forwards so div.getAnimations()[0] won't return an
|
|
// undefined value.
|
|
const div = addDiv(t, {
|
|
style: 'animation: moveAnimation 10s -100s forwards'
|
|
});
|
|
const 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s 5' });
|
|
const effect = div.getAnimations()[0].effect;
|
|
const answer = 100 * MS_PER_SEC * 5;
|
|
assert_equals(effect.getComputedTiming().activeDuration, answer,
|
|
'Initial value of activeDuration');
|
|
}, 'activeDuration of a new animation');
|
|
|
|
test(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s infinite' });
|
|
const effect = div.getAnimations()[0].effect;
|
|
assert_equals(effect.getComputedTiming().activeDuration, Infinity,
|
|
'Initial value of activeDuration');
|
|
}, 'activeDuration of an infinitely repeating animation');
|
|
|
|
test(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 0s 1s infinite' });
|
|
const 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s 1s 0' });
|
|
const 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s' });
|
|
const effect = div.getAnimations()[0].effect;
|
|
assert_equals(effect.getComputedTiming().localTime, 0,
|
|
'Initial value of localTime');
|
|
}, 'localTime of a new animation');
|
|
|
|
test(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s' });
|
|
const anim = div.getAnimations()[0];
|
|
anim.currentTime = 5 * MS_PER_SEC;
|
|
assert_times_equal(anim.effect.getComputedTiming().localTime,
|
|
anim.currentTime,
|
|
'current localTime after setting currentTime');
|
|
}, 'localTime of an animation is always equal to currentTime');
|
|
|
|
promise_test(async t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s' });
|
|
|
|
const anim = div.getAnimations()[0];
|
|
anim.playbackRate = 2; // 2 times faster
|
|
|
|
await anim.ready;
|
|
|
|
assert_times_equal(anim.effect.getComputedTiming().localTime,
|
|
anim.currentTime,
|
|
'localTime is equal to currentTime');
|
|
|
|
await waitForFrame();
|
|
|
|
assert_times_equal(anim.effect.getComputedTiming().localTime,
|
|
anim.currentTime,
|
|
'localTime is equal to currentTime');
|
|
}, 'localTime reflects playbackRate immediately');
|
|
|
|
test(t => {
|
|
const div = addDiv(t);
|
|
const effect = new KeyframeEffect(div, {left: ["0px", "100px"]});
|
|
|
|
assert_equals(effect.getComputedTiming().localTime, null,
|
|
'localTime for orphaned effect');
|
|
}, 'localTime of an AnimationEffect without an Animation');
|
|
|
|
|
|
// --------------------
|
|
// progress
|
|
//
|
|
// Note: Even though CSS animations have a default animation-timing-function of
|
|
// "ease", this only applies between keyframes (often referred to as the
|
|
// keyframe-level easing). The progress value returned by getComputedTiming(),
|
|
// however, only reflects effect-level easing and this defaults to "linear",
|
|
// even for CSS animations.
|
|
// --------------------
|
|
|
|
test(t => {
|
|
const tests = [
|
|
{ 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] },
|
|
];
|
|
for (const test of tests) {
|
|
const div = addDiv(t, {
|
|
style: 'animation: moveAnimation 100s 10s ' + test.fill
|
|
});
|
|
const 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],
|
|
`Initial progress with "${test.fill}" fill`);
|
|
}
|
|
}, 'progress of an animation with different fill modes');
|
|
|
|
test(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 10s 10 both' });
|
|
const 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(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).
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 0s infinite both' });
|
|
const 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(t => {
|
|
// Default iterations = 1
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 0s both' });
|
|
const 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 0s 5s 10.25 both' });
|
|
const 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(t => {
|
|
const div = addDiv(t, {
|
|
style: 'animation: moveAnimation 0s 5s 10.25 both reverse',
|
|
});
|
|
const 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(t => {
|
|
const div = addDiv(t, {
|
|
style: 'animation: moveAnimation 10s 10.25 both alternate',
|
|
});
|
|
const 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(t => {
|
|
const div = addDiv(t, {
|
|
style: 'animation: moveAnimation 10s 10.25 both alternate-reverse',
|
|
});
|
|
const 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(t => {
|
|
const div = addDiv(t, {
|
|
style: 'animation: moveAnimation 0s 10.25 both alternate',
|
|
});
|
|
const 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(t => {
|
|
const div = addDiv(t, {
|
|
style: 'animation: moveAnimation 0s 10.25 both alternate-reverse',
|
|
});
|
|
const 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s 2s' });
|
|
const 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s' });
|
|
const anim = div.getAnimations()[0];
|
|
assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
|
|
'Initial value of currentIteration');
|
|
}, 'currentIteration of a new animation is zero');
|
|
|
|
test(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).
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 0s infinite both' });
|
|
const 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 0s 10.5 both' });
|
|
const 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(t => {
|
|
const div = addDiv(t, {
|
|
style: 'animation: moveAnimation 100s 5.5 forwards'
|
|
});
|
|
const 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s 2 forwards' });
|
|
const 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(t => {
|
|
const div = addDiv(t, { style: 'animation: moveAnimation 100s forwards' });
|
|
const 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(t => {
|
|
const div = addDiv(t);
|
|
const effect = new KeyframeEffect(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.
|
|
|
|
</script>
|
|
</body>
|