--- a/dom/animation/test/css-animations/file_animation-currenttime.html
+++ b/dom/animation/test/css-animations/file_animation-currenttime.html
@@ -20,436 +20,225 @@
</style>
<script src="../testcommon.js"></script>
</head>
<body>
<script type="text/javascript">
'use strict';
-// TODO: add equivalent tests without an animation-delay, but first we need to
-// change the timing of animationstart dispatch. (Right now the animationstart
-// event will fire before the ready Promise is resolved if there is no
-// animation-delay.)
-// See https://bugzilla.mozilla.org/show_bug.cgi?id=1134163
+// TODO: We should separate this test(Testing for CSS Animation events /
+// Testing for currentTime of Web Animation).
+// e.g:
+// CSS Animation events test :
+// - check the firing an event using Animation.currentTime
+// The current Time of Web Animation test :
+// - check an current time value on several situation(init / processing..)
+// - Based on W3C Spec, check the behavior of setting current time.
// TODO: Once the computedTiming property is implemented, add checks to the
// checker helpers to ensure that computedTiming's properties are updated as
// expected.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1108055
-
const CSS_ANIM_EVENTS =
['animationstart', 'animationiteration', 'animationend'];
-const ANIM_DELAY_MS = 1000 * MS_PER_SEC;
-const ANIM_DUR_MS = 1000 * MS_PER_SEC;
-const ANIM_PROPERTY_VAL = 'anim ' + ANIM_DUR_MS + 'ms ' + ANIM_DELAY_MS + 'ms';
-
-/**
- * These helpers get the value that the currentTime needs to be set to, to put
- * an animation that uses the above ANIM_DELAY_MS and ANIM_DUR_MS values into
- * the middle of various phases or points through the active duration.
- */
-function currentTimeForBeforePhase(timeline) {
- return ANIM_DELAY_MS / 2;
-}
-function currentTimeForActivePhase(timeline) {
- return ANIM_DELAY_MS + ANIM_DUR_MS / 2;
-}
-function currentTimeForAfterPhase(timeline) {
- return ANIM_DELAY_MS + ANIM_DUR_MS + ANIM_DELAY_MS / 2;
-}
-function currentTimeForStartOfActiveInterval(timeline) {
- return ANIM_DELAY_MS;
-}
-function currentTimeForFiftyPercentThroughActiveInterval(timeline) {
- return ANIM_DELAY_MS + ANIM_DUR_MS * 0.5;
-}
-function currentTimeForEndOfActiveInterval(timeline) {
- return ANIM_DELAY_MS + ANIM_DUR_MS;
-}
-
-
-// Expected computed 'margin-left' values at points during the active interval:
-// When we assert_between_inclusive using these values we could in theory cause
-// intermittent failure due to very long delays between paints, but since the
-// active duration is 1000s long, a delay would need to be around 100s to cause
-// that. If that's happening then there are likely other issues that should be
-// fixed, so a failure to make us look into that seems like a good thing.
-const UNANIMATED_POSITION = 10;
-const INITIAL_POSITION = 100;
-const TEN_PCT_POSITION = 110;
-const FIFTY_PCT_POSITION = 150;
-const END_POSITION = 200;
-
-// The terms used for the naming of the following helper functions refer to
-// terms used in the Web Animations specification for specific phases of an
-// animation. The terms can be found here:
-//
-// https://w3c.github.io/web-animations/#animation-effect-phases-and-states
-//
-// Note the distinction between the "animation start time" which occurs before
-// the start delay and the start of the active interval which occurs after it.
-
-// Called when currentTime is set to zero (the beginning of the start delay).
-function checkStateOnSettingCurrentTimeToZero(animation)
-{
- // We don't test animation.currentTime since our caller just set it.
-
- assert_equals(animation.playState, 'running',
- 'Animation.playState should be "running" at the start of ' +
- 'the start delay');
-
- assert_equals(animation.effect.target.style.animationPlayState, 'running',
- 'Animation.effect.target.style.animationPlayState should be ' +
- '"running" at the start of the start delay');
-
- var div = animation.effect.target;
- var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
- assert_equals(marginLeft, UNANIMATED_POSITION,
- 'the computed value of margin-left should be unaffected ' +
- 'at the beginning of the start delay');
-}
-
-// Called when the ready Promise's callbacks should happen
-function checkStateOnReadyPromiseResolved(animation)
-{
- // the 0.0001 here is for rounding error
- assert_less_than_equal(animation.currentTime,
- animation.timeline.currentTime - animation.startTime + 0.0001,
- 'Animation.currentTime should be less than the local time ' +
- 'equivalent of the timeline\'s currentTime on the first paint tick ' +
- 'after animation creation');
-
- assert_equals(animation.playState, 'running',
- 'Animation.playState should be "running" on the first paint ' +
- 'tick after animation creation');
-
- assert_equals(animation.effect.target.style.animationPlayState, 'running',
- 'Animation.effect.target.style.animationPlayState should be ' +
- '"running" on the first paint tick after animation creation');
-
- var div = animation.effect.target;
- var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
- assert_equals(marginLeft, UNANIMATED_POSITION,
- 'the computed value of margin-left should be unaffected ' +
- 'by an animation with a delay on ready Promise resolve');
-}
-
-// Called when currentTime is set to the time the active interval starts.
-function checkStateAtActiveIntervalStartTime(animation)
-{
- // We don't test animation.currentTime since our caller just set it.
-
- assert_equals(animation.playState, 'running',
- 'Animation.playState should be "running" at the start of ' +
- 'the active interval');
-
- assert_equals(animation.effect.target.style.animationPlayState, 'running',
- 'Animation.effect.target.style.animationPlayState should be ' +
- '"running" at the start of the active interval');
-
- var div = animation.effect.target;
- var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
- assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION,
- 'the computed value of margin-left should be close to the value at the ' +
- 'beginning of the animation');
-}
-
-function checkStateAtFiftyPctOfActiveInterval(animation)
-{
- // We don't test animation.currentTime since our caller just set it.
-
- var div = animation.effect.target;
- var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
- assert_equals(marginLeft, FIFTY_PCT_POSITION,
- 'the computed value of margin-left should be half way through the ' +
- 'animation at the midpoint of the active interval');
-}
-
-// Called when currentTime is set to the time the active interval ends.
-function checkStateAtActiveIntervalEndTime(animation)
-{
- // We don't test animation.currentTime since our caller just set it.
-
- assert_equals(animation.playState, 'finished',
- 'Animation.playState should be "finished" at the end of ' +
- 'the active interval');
-
- assert_equals(animation.effect.target.style.animationPlayState, "running",
- 'Animation.effect.target.style.animationPlayState should be ' +
- '"finished" at the end of the active interval');
-
- var div = animation.effect.target;
- var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
- assert_equals(marginLeft, UNANIMATED_POSITION,
- 'the computed value of margin-left should be unaffected ' +
- 'by the animation at the end of the active duration when the ' +
- 'animation-fill-mode is none');
-}
test(function(t)
{
var div = addDiv(t, {'class': 'animated-div'});
-
- div.style.animation = ANIM_PROPERTY_VAL;
-
+ div.style.animation = "anim 100s";
var animation = div.getAnimations()[0];
// Animations shouldn't start until the next paint tick, so:
assert_equals(animation.currentTime, 0,
'Animation.currentTime should be zero when an animation ' +
'is initially created');
- assert_equals(animation.playState, "pending",
- 'Animation.playState should be "pending" when an animation ' +
- 'is initially created');
-
- assert_equals(animation.effect.target.style.animationPlayState, 'running',
- 'Animation.effect.target.style.animationPlayState should be ' +
- '"running" when an animation is initially created');
-
- // XXX Ideally we would have a test to check the ready Promise is initially
- // unresolved, but currently there is no Web API to do that. Waiting for the
- // ready Promise with a timeout doesn't work because the resolved callback
- // will be called (async) regardless of whether the Promise was resolved in
- // the past or is resolved in the future.
-
- // So that animation is running instead of paused when we set currentTime:
+ // Make sure the animation is running before we set the current time.
animation.startTime = animation.timeline.currentTime;
- assert_approx_equals(animation.currentTime, 0, 0.0001, // rounding error
+ animation.currentTime = 50 * MS_PER_SEC;
+ assert_times_equal(animation.currentTime, 50 * MS_PER_SEC,
'Check setting of currentTime actually works');
-
- checkStateOnSettingCurrentTimeToZero(animation);
}, 'Sanity test to check round-tripping assigning to new animation\'s ' +
'currentTime');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
-
- div.style.animation = ANIM_PROPERTY_VAL;
-
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
return animation.ready.then(function() {
- checkStateOnReadyPromiseResolved(animation);
+ // the 0.0001 here is for rounding error
+ assert_less_than_equal(animation.currentTime,
+ animation.timeline.currentTime - animation.startTime + 0.0001,
+ 'Animation.currentTime should be less than the local time ' +
+ 'equivalent of the timeline\'s currentTime on the first paint tick ' +
+ 'after animation creation');
- animation.currentTime =
- currentTimeForStartOfActiveInterval(animation.timeline);
+ animation.currentTime = 100 * MS_PER_SEC;
return eventWatcher.wait_for('animationstart');
}).then(function() {
- checkStateAtActiveIntervalStartTime(animation);
-
- animation.currentTime =
- currentTimeForFiftyPercentThroughActiveInterval(animation.timeline);
- checkStateAtFiftyPctOfActiveInterval(animation);
-
- animation.currentTime =
- currentTimeForEndOfActiveInterval(animation.timeline);
+ animation.currentTime = 200 * MS_PER_SEC;
return eventWatcher.wait_for('animationend');
- }).then(function() {
- checkStateAtActiveIntervalEndTime(animation);
});
}, 'Skipping forward through animation');
-
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
-
- div.style.animation = ANIM_PROPERTY_VAL;
-
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
-
- // So that animation is running instead of paused when we set currentTime:
- animation.startTime = animation.timeline.currentTime;
-
- animation.currentTime = currentTimeForEndOfActiveInterval(animation.timeline);
-
+ animation.currentTime = 200 * MS_PER_SEC;
var previousTimelineTime = animation.timeline.currentTime;
- // Skipping over the active interval will dispatch an 'animationstart' then
- // an 'animationend' event. We need to wait for these events before we start
- // testing going backwards since EventWatcher will fail the test if it gets
- // an event that we haven't told it about.
- var retPromise = eventWatcher.wait_for(['animationstart',
- 'animationend']).then(function() {
+ return eventWatcher.wait_for(['animationstart',
+ 'animationend']).then(function() {
assert_true(document.timeline.currentTime - previousTimelineTime <
- ANIM_DUR_MS,
+ 100 * MS_PER_SEC,
'Sanity check that seeking worked rather than the events ' +
'firing after normal playback through the very long ' +
'animation duration');
- // Now we can start the tests for skipping backwards, but first we check
- // that after the events we're still in the same end time state:
- checkStateAtActiveIntervalEndTime(animation);
-
- animation.currentTime =
- currentTimeForFiftyPercentThroughActiveInterval(animation.timeline);
-
- // Despite going backwards from after the end of the animation (to being
- // in the active interval), we now expect an 'animationstart' event
- // because the animation should go from being inactive to active.
- //
- // Calling checkStateAtFiftyPctOfActiveInterval will check computed style,
- // causing computed style to be updated and the 'animationstart' event to
- // be dispatched synchronously. We need to call wait_for first
- // otherwise eventWatcher will assert that the event was unexpected.
- var promise = eventWatcher.wait_for('animationstart');
- checkStateAtFiftyPctOfActiveInterval(animation);
- return promise;
+ animation.currentTime = 150 * MS_PER_SEC;
+ return eventWatcher.wait_for('animationstart');
}).then(function() {
- animation.currentTime =
- currentTimeForStartOfActiveInterval(animation.timeline);
- checkStateAtActiveIntervalStartTime(animation);
-
animation.currentTime = 0;
- // Despite going backwards from just after the active interval starts to
- // the animation start time, we now expect an animationend event
- // because we went from inside to outside the active interval.
return eventWatcher.wait_for('animationend');
- }).then(function() {
- checkStateOnReadyPromiseResolved(animation);
});
-
- // This must come after we've set up the Promise chain, since requesting
- // computed style will force events to be dispatched.
- checkStateAtActiveIntervalEndTime(animation);
-
- return retPromise;
}, 'Skipping backwards through animation');
// Next we have multiple tests to check that redundant currentTime changes do
// NOT dispatch events. It's impossible to distinguish between events not being
// dispatched and events just taking an incredibly long time to dispatch
// without waiting an infinitely long time. Obviously we don't want to do that
// (block this test from finishing forever), so instead we just listen for
// events until two animation frames (i.e. requestAnimationFrame callbacks)
// have happened, then assume that no events will ever be dispatched for the
// redundant changes if no events were detected in that time.
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
- animation.currentTime = currentTimeForActivePhase(animation.timeline);
- animation.currentTime = currentTimeForBeforePhase(animation.timeline);
+ animation.currentTime = 150 * MS_PER_SEC;
+ animation.currentTime = 50 * MS_PER_SEC;
return waitForAnimationFrames(2);
}, 'Redundant change, before -> active, then back');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
- animation.currentTime = currentTimeForAfterPhase(animation.timeline);
- animation.currentTime = currentTimeForBeforePhase(animation.timeline);
+ animation.currentTime = 250 * MS_PER_SEC;
+ animation.currentTime = 50 * MS_PER_SEC;
return waitForAnimationFrames(2);
}, 'Redundant change, before -> after, then back');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
var retPromise = eventWatcher.wait_for('animationstart').then(function() {
- animation.currentTime = currentTimeForBeforePhase(animation.timeline);
- animation.currentTime = currentTimeForActivePhase(animation.timeline);
+ animation.currentTime = 50 * MS_PER_SEC;
+ animation.currentTime = 150 * MS_PER_SEC;
return waitForAnimationFrames(2);
});
// get us into the initial state:
- animation.currentTime = currentTimeForActivePhase(animation.timeline);
+ animation.currentTime = 150 * MS_PER_SEC;
return retPromise;
}, 'Redundant change, active -> before, then back');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
- var retPromise = eventWatcher.wait_for('animationstart').then(function() {
- animation.currentTime = currentTimeForAfterPhase(animation.timeline);
- animation.currentTime = currentTimeForActivePhase(animation.timeline);
+ var retPromise = eventWatcher.wait_for('animationstart').then(function() {
+ animation.currentTime = 250 * MS_PER_SEC;
+ animation.currentTime = 150 * MS_PER_SEC;
return waitForAnimationFrames(2);
});
// get us into the initial state:
- animation.currentTime = currentTimeForActivePhase(animation.timeline);
+ animation.currentTime = 150 * MS_PER_SEC;
return retPromise;
}, 'Redundant change, active -> after, then back');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
var retPromise = eventWatcher.wait_for(['animationstart',
'animationend']).then(function() {
- animation.currentTime = currentTimeForBeforePhase(animation.timeline);
- animation.currentTime = currentTimeForAfterPhase(animation.timeline);
+ animation.currentTime = 50 * MS_PER_SEC;
+ animation.currentTime = 250 * MS_PER_SEC;
return waitForAnimationFrames(2);
});
// get us into the initial state:
- animation.currentTime = currentTimeForAfterPhase(animation.timeline);
+ animation.currentTime = 250 * MS_PER_SEC;
return retPromise;
}, 'Redundant change, after -> before, then back');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
var retPromise = eventWatcher.wait_for(['animationstart',
'animationend']).then(function() {
- animation.currentTime = currentTimeForActivePhase(animation.timeline);
- animation.currentTime = currentTimeForAfterPhase(animation.timeline);
+ animation.currentTime = 150 * MS_PER_SEC;
+ animation.currentTime = 250 * MS_PER_SEC;
return waitForAnimationFrames(2);
});
// get us into the initial state:
- animation.currentTime = currentTimeForAfterPhase(animation.timeline);
+ animation.currentTime = 250 * MS_PER_SEC;
return retPromise;
}, 'Redundant change, after -> active, then back');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s"
var animation = div.getAnimations()[0];
animation.pause();
- animation.currentTime = currentTimeForAfterPhase(animation.timeline);
+ animation.currentTime = 150 * MS_PER_SEC;
return eventWatcher.wait_for(['animationstart',
'animationend']).then(function() {
- animation.currentTime = currentTimeForActivePhase(animation.timeline);
+ animation.currentTime = 50 * MS_PER_SEC;
return eventWatcher.wait_for('animationstart');
});
}, 'Seeking finished -> paused dispatches animationstart');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s";
var animation = div.getAnimations()[0];
return animation.ready.then(function() {
var exception;
try {
animation.currentTime = null;
} catch (e) {
@@ -479,36 +268,33 @@ promise_test(function(t) {
}).then(function() {
assert_equals(animation.currentTime, pauseTime,
'Animation.currentTime is unchanged after pausing');
});
}, 'Animation.currentTime after pausing');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
- div.style.animation = ANIM_PROPERTY_VAL;
-
+ div.style.animation = "anim 100s";
var animation = div.getAnimations()[0];
return animation.ready.then(function() {
// just before animation ends:
- animation.currentTime = ANIM_DELAY_MS + ANIM_DUR_MS - 1;
-
+ animation.currentTime = 100 * MS_PER_SEC - 1;
return waitForAnimationFrames(2);
}).then(function() {
- assert_equals(animation.currentTime, ANIM_DELAY_MS + ANIM_DUR_MS,
+ assert_equals(animation.currentTime, 100 * MS_PER_SEC,
'Animation.currentTime should not continue to increase after the ' +
'animation has finished');
});
}, 'Animation.currentTime clamping');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
- div.style.animation = ANIM_PROPERTY_VAL;
-
+ div.style.animation = "anim 100s";
var animation = div.getAnimations()[0];
return animation.ready.then(function() {
// play backwards:
animation.playbackRate = -1;
// just before animation ends (at the "start"):
animation.currentTime = 1;
@@ -519,28 +305,28 @@ promise_test(function(t) {
'Animation.currentTime should not continue to decrease after an ' +
'animation running in reverse has finished and currentTime is zero');
});
}, 'Animation.currentTime clamping for reversed animation');
test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
div.style.animation = 'anim 100s';
-
var animation = div.getAnimations()[0];
animation.cancel();
+
assert_equals(animation.currentTime, null,
'The currentTime of a cancelled animation should be null');
}, 'Animation.currentTime after cancelling');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
div.style.animation = 'anim 100s';
+ var animation = div.getAnimations()[0];
- var animation = div.getAnimations()[0];
return animation.ready.then(function() {
animation.finish();
// Initiate a pause then abort it
animation.pause();
animation.play();
// Wait to return to running state
--- a/dom/animation/test/css-animations/file_animation-starttime.html
+++ b/dom/animation/test/css-animations/file_animation-starttime.html
@@ -20,228 +20,116 @@
</style>
<script src="../testcommon.js"></script>
</head>
<body>
<script type="text/javascript">
'use strict';
-// TODO: add equivalent tests without an animation-delay, but first we need to
-// change the timing of animationstart dispatch. (Right now the animationstart
-// event will fire before the ready Promise is resolved if there is no
-// animation-delay.)
-// See https://bugzilla.mozilla.org/show_bug.cgi?id=1134163
+// TODO: We should separate this test(Testing for CSS Animation events /
+// Testing for start time of Web Animation).
+// e.g:
+// CSS Animation events test:
+// - check the firing an event after setting an Animation.startTime
+// The start time of Web Animation test:
+// - check an start time value on several situation(init / processing..)
+// - Based on W3C Spec, check the behavior of setting current time.
// TODO: Once the computedTiming property is implemented, add checks to the
// checker helpers to ensure that computedTiming's properties are updated as
// expected.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1108055
-
const CSS_ANIM_EVENTS =
['animationstart', 'animationiteration', 'animationend'];
-const ANIM_DELAY_MS = 1000 * MS_PER_SEC; // 1000s
-const ANIM_DUR_MS = 1000 * MS_PER_SEC; // 1000s
-const ANIM_PROPERTY_VAL = 'anim ' + ANIM_DUR_MS + 'ms ' + ANIM_DELAY_MS + 'ms';
-
-/**
- * These helpers get the value that the startTime needs to be set to, to put an
- * animation that uses the above ANIM_DELAY_MS and ANIM_DUR_MS values into the
- * middle of various phases or points through the active duration.
- */
-function startTimeForBeforePhase(timeline) {
- return timeline.currentTime - ANIM_DELAY_MS / 2;
-}
-function startTimeForActivePhase(timeline) {
- return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS / 2;
-}
-function startTimeForAfterPhase(timeline) {
- return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS - ANIM_DELAY_MS / 2;
-}
-function startTimeForStartOfActiveInterval(timeline) {
- return timeline.currentTime - ANIM_DELAY_MS;
-}
-function startTimeForFiftyPercentThroughActiveInterval(timeline) {
- return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS * 0.5;
-}
-function startTimeForEndOfActiveInterval(timeline) {
- return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS;
-}
-
-
-// Expected computed 'margin-left' values at points during the active interval:
-// When we assert_between_inclusive using these values we could in theory cause
-// intermittent failure due to very long delays between paints, but since the
-// active duration is 1000s long, a delay would need to be around 100s to cause
-// that. If that's happening then there are likely other issues that should be
-// fixed, so a failure to make us look into that seems like a good thing.
-const UNANIMATED_POSITION = 10;
-const INITIAL_POSITION = 100;
-const TEN_PCT_POSITION = 110;
-const FIFTY_PCT_POSITION = 150;
-const END_POSITION = 200;
-
-// The terms used for the naming of the following helper functions refer to
-// terms used in the Web Animations specification for specific phases of an
-// animation. The terms can be found here:
-//
-// https://w3c.github.io/web-animations/#animation-effect-phases-and-states
-//
-// Note the distinction between the "animation start time" which occurs before
-// the start delay and the start of the active interval which occurs after it.
-
-// Called when the ready Promise's callbacks should happen
-function checkStateOnReadyPromiseResolved(animation)
-{
- assert_less_than_equal(animation.startTime, animation.timeline.currentTime,
- 'Animation.startTime should be less than the timeline\'s ' +
- 'currentTime on the first paint tick after animation creation');
-
- assert_equals(animation.playState, 'running',
- 'Animation.playState should be "running" on the first paint ' +
- 'tick after animation creation');
-
- assert_equals(animation.effect.target.style.animationPlayState, 'running',
- 'Animation.effect.target.style.animationPlayState should be ' +
- '"running" on the first paint tick after animation creation');
-
- var div = animation.effect.target;
- var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
- assert_equals(marginLeft, UNANIMATED_POSITION,
- 'the computed value of margin-left should be unaffected ' +
- 'by an animation with a delay on ready Promise resolve');
-}
-
-// Called when startTime is set to the time the active interval starts.
-function checkStateAtActiveIntervalStartTime(animation)
-{
- // We don't test animation.startTime since our caller just set it.
-
- assert_equals(animation.playState, 'running',
- 'Animation.playState should be "running" at the start of ' +
- 'the active interval');
-
- assert_equals(animation.effect.target.style.animationPlayState, 'running',
- 'Animation.effect.target.style.animationPlayState should be ' +
- '"running" at the start of the active interval');
-
- var div = animation.effect.target;
- var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
- assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION,
- 'the computed value of margin-left should be close to the value at the ' +
- 'beginning of the animation');
-}
-
-function checkStateAtFiftyPctOfActiveInterval(animation)
-{
- // We don't test animation.startTime since our caller just set it.
-
- var div = animation.effect.target;
- var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
- assert_equals(marginLeft, FIFTY_PCT_POSITION,
- 'the computed value of margin-left should be half way through the ' +
- 'animation at the midpoint of the active interval');
-}
-
-// Called when startTime is set to the time the active interval ends.
-function checkStateAtActiveIntervalEndTime(animation)
-{
- // We don't test animation.startTime since our caller just set it.
-
- assert_equals(animation.playState, 'finished',
- 'Animation.playState should be "finished" at the end of ' +
- 'the active interval');
-
- assert_equals(animation.effect.target.style.animationPlayState, "running",
- 'Animation.effect.target.style.animationPlayState should be ' +
- '"finished" at the end of the active interval');
-
- var div = animation.effect.target;
- var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
- assert_equals(marginLeft, UNANIMATED_POSITION,
- 'the computed value of margin-left should be unaffected ' +
- 'by the animation at the end of the active duration when the ' +
- 'animation-fill-mode is none');
-}
test(function(t)
{
var div = addDiv(t, { 'style': 'animation: anim 100s' });
var animation = div.getAnimations()[0];
+
assert_equals(animation.startTime, null, 'startTime is unresolved');
}, 'startTime of a newly created (play-pending) animation is unresolved');
test(function(t)
{
var div = addDiv(t, { 'style': 'animation: anim 100s paused' });
var animation = div.getAnimations()[0];
assert_equals(animation.startTime, null, 'startTime is unresolved');
}, 'startTime of a newly created (pause-pending) animation is unresolved');
promise_test(function(t)
{
var div = addDiv(t, { 'style': 'animation: anim 100s' });
var animation = div.getAnimations()[0];
+
return animation.ready.then(function() {
assert_true(animation.startTime > 0,
'startTime is resolved when running');
});
}, 'startTime is resolved when running');
promise_test(function(t)
{
var div = addDiv(t, { 'style': 'animation: anim 100s paused' });
var animation = div.getAnimations()[0];
+
return animation.ready.then(function() {
assert_equals(animation.startTime, null,
'startTime is unresolved when paused');
});
}, 'startTime is unresolved when paused');
promise_test(function(t)
{
var div = addDiv(t, { 'style': 'animation: anim 100s' });
var animation = div.getAnimations()[0];
+
return animation.ready.then(function() {
div.style.animationPlayState = 'paused';
getComputedStyle(div).animationPlayState;
+
assert_not_equals(animation.startTime, null,
'startTime is resolved when pause-pending');
div.style.animationPlayState = 'running';
getComputedStyle(div).animationPlayState;
+
assert_not_equals(animation.startTime, null,
'startTime is preserved when a pause is aborted');
});
}, 'startTime while pause-pending and play-pending');
promise_test(function(t) {
var div = addDiv(t, { 'style': 'animation: anim 100s' });
var animation = div.getAnimations()[0];
// Seek to end to put us in the finished state
animation.currentTime = 100 * MS_PER_SEC;
+
return animation.ready.then(function() {
// Call play() which puts us back in the running state
animation.play();
+
assert_equals(animation.startTime, null, 'startTime is unresolved');
});
}, 'startTime while play-pending from finished state');
test(function(t) {
var div = addDiv(t, { 'style': 'animation: anim 100s' });
var animation = div.getAnimations()[0];
animation.finish();
// Call play() which puts us back in the running state
animation.play();
+
assert_equals(animation.startTime, null, 'startTime is unresolved');
}, 'startTime while play-pending from finished state using finish()');
promise_test(function(t) {
- var div = addDiv(t, { style: 'animation: anim 1000s' });
+ var div = addDiv(t, { style: 'animation: anim 100s' });
var animation = div.getAnimations()[0];
assert_equals(animation.startTime, null, 'The initial startTime is null');
var initialTimelineTime = document.timeline.currentTime;
return animation.ready.then(function() {
assert_true(animation.startTime > initialTimelineTime,
'After the animation has started, startTime is greater than ' +
@@ -262,243 +150,208 @@ promise_test(function(t) {
'After actually pausing, the startTime of an animation ' +
'is null');
});
}, 'Pausing should make the startTime become null');
test(function(t)
{
var div = addDiv(t, {'class': 'animated-div'});
- div.style.animation = ANIM_PROPERTY_VAL;
-
+ div.style.animation = 'anim 100s 100s';
var animation = div.getAnimations()[0];
var currentTime = animation.timeline.currentTime;
animation.startTime = currentTime;
- assert_approx_equals(animation.startTime, currentTime, 0.0001, // rounding error
+
+ assert_times_equal(animation.startTime, currentTime,
'Check setting of startTime actually works');
}, 'Sanity test to check round-tripping assigning to a new animation\'s ' +
'startTime');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
-
- div.style.animation = ANIM_PROPERTY_VAL;
-
+ div.style.animation = 'anim 100s 100s';
var animation = div.getAnimations()[0];
return animation.ready.then(function() {
- checkStateOnReadyPromiseResolved(animation);
+ assert_less_than_equal(animation.startTime, animation.timeline.currentTime,
+ 'Animation.startTime should be less than the timeline\'s ' +
+ 'currentTime on the first paint tick after animation creation');
- animation.startTime = startTimeForStartOfActiveInterval(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 100 * MS_PER_SEC;
return eventWatcher.wait_for('animationstart');
}).then(function() {
- checkStateAtActiveIntervalStartTime(animation);
-
- animation.startTime =
- startTimeForFiftyPercentThroughActiveInterval(animation.timeline);
- checkStateAtFiftyPctOfActiveInterval(animation);
-
- animation.startTime = startTimeForEndOfActiveInterval(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 200 * MS_PER_SEC;
return eventWatcher.wait_for('animationend');
- }).then(function() {
- checkStateAtActiveIntervalEndTime(animation);
});
}, 'Skipping forward through animation');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
-
- div.style.animation = ANIM_PROPERTY_VAL;
-
+ div.style.animation = 'anim 100s 100s';
var animation = div.getAnimations()[0];
-
- animation.startTime = startTimeForEndOfActiveInterval(animation.timeline);
-
+ animation.startTime = animation.timeline.currentTime - 200 * MS_PER_SEC;
var previousTimelineTime = animation.timeline.currentTime;
- // Skipping over the active interval will dispatch an 'animationstart' then
- // an 'animationend' event. We need to wait for these events before we start
- // testing going backwards since EventWatcher will fail the test if it gets
- // an event that we haven't told it about.
return eventWatcher.wait_for(['animationstart',
'animationend']).then(function() {
assert_true(document.timeline.currentTime - previousTimelineTime <
- ANIM_DUR_MS,
+ 100 * MS_PER_SEC,
'Sanity check that seeking worked rather than the events ' +
'firing after normal playback through the very long ' +
'animation duration');
- // Now we can start the tests for skipping backwards, but first we check
- // that after the events we're still in the same end time state:
- checkStateAtActiveIntervalEndTime(animation);
-
- animation.startTime =
- startTimeForFiftyPercentThroughActiveInterval(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
// Despite going backwards from after the end of the animation (to being
// in the active interval), we now expect an 'animationstart' event
// because the animation should go from being inactive to active.
- //
- // Calling checkStateAtFiftyPctOfActiveInterval will check computed style,
- // causing computed style to be updated and the 'animationstart' event to
- // be dispatched synchronously. We need to call wait_for first
- // otherwise eventWatcher will assert that the event was unexpected.
- var promise = eventWatcher.wait_for('animationstart');
- checkStateAtFiftyPctOfActiveInterval(animation);
- return promise;
+ return eventWatcher.wait_for('animationstart');
}).then(function() {
- animation.startTime = startTimeForStartOfActiveInterval(animation.timeline);
- checkStateAtActiveIntervalStartTime(animation);
+ animation.startTime = animation.timeline.currentTime;
- animation.startTime = animation.timeline.currentTime;
// Despite going backwards from just after the active interval starts to
// the animation start time, we now expect an animationend event
// because we went from inside to outside the active interval.
return eventWatcher.wait_for('animationend');
}).then(function() {
- checkStateOnReadyPromiseResolved(animation);
- })
-
- // This must come after we've set up the Promise chain, since requesting
- // computed style will force events to be dispatched.
- checkStateAtActiveIntervalEndTime(animation);
+ assert_less_than_equal(animation.startTime, animation.timeline.currentTime,
+ 'Animation.startTime should be less than the timeline\'s ' +
+ 'currentTime on the first paint tick after animation creation');
+ });
}, 'Skipping backwards through animation');
-
// Next we have multiple tests to check that redundant startTime changes do NOT
// dispatch events. It's impossible to distinguish between events not being
// dispatched and events just taking an incredibly long time to dispatch
// without waiting an infinitely long time. Obviously we don't want to do that
// (block this test from finishing forever), so instead we just listen for
// events until two animation frames (i.e. requestAnimationFrame callbacks)
// have happened, then assume that no events will ever be dispatched for the
// redundant changes if no events were detected in that time.
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
- animation.startTime = startTimeForActivePhase(animation.timeline);
- animation.startTime = startTimeForBeforePhase(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
+ animation.startTime = animation.timeline.currentTime - 50 * MS_PER_SEC;
return waitForAnimationFrames(2);
}, 'Redundant change, before -> active, then back');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
- animation.startTime = startTimeForAfterPhase(animation.timeline);
- animation.startTime = startTimeForBeforePhase(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 250 * MS_PER_SEC;
+ animation.startTime = animation.timeline.currentTime - 50 * MS_PER_SEC;
return waitForAnimationFrames(2);
}, 'Redundant change, before -> after, then back');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
var retPromise = eventWatcher.wait_for('animationstart').then(function() {
- animation.startTime = startTimeForBeforePhase(animation.timeline);
- animation.startTime = startTimeForActivePhase(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 50 * MS_PER_SEC;
+ animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
return waitForAnimationFrames(2);
});
// get us into the initial state:
- animation.startTime = startTimeForActivePhase(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
return retPromise;
}, 'Redundant change, active -> before, then back');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
var retPromise = eventWatcher.wait_for('animationstart').then(function() {
- animation.startTime = startTimeForAfterPhase(animation.timeline);
- animation.startTime = startTimeForActivePhase(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 250 * MS_PER_SEC;
+ animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
return waitForAnimationFrames(2);
});
// get us into the initial state:
- animation.startTime = startTimeForActivePhase(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
return retPromise;
}, 'Redundant change, active -> after, then back');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
var retPromise = eventWatcher.wait_for(['animationstart',
'animationend']).then(function() {
- animation.startTime = startTimeForBeforePhase(animation.timeline);
- animation.startTime = startTimeForAfterPhase(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 50 * MS_PER_SEC;
+ animation.startTime = animation.timeline.currentTime - 250 * MS_PER_SEC;
return waitForAnimationFrames(2);
});
// get us into the initial state:
- animation.startTime = startTimeForAfterPhase(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 250 * MS_PER_SEC;
return retPromise;
}, 'Redundant change, after -> before, then back');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
- div.style.animation = ANIM_PROPERTY_VAL;
+ div.style.animation = "anim 100s 100s";
var animation = div.getAnimations()[0];
var retPromise = eventWatcher.wait_for(['animationstart',
'animationend']).then(function() {
- animation.startTime = startTimeForActivePhase(animation.timeline);
- animation.startTime = startTimeForAfterPhase(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
+ animation.startTime = animation.timeline.currentTime - 250 * MS_PER_SEC;
return waitForAnimationFrames(2);
+
});
// get us into the initial state:
- animation.startTime = startTimeForAfterPhase(animation.timeline);
+ animation.startTime = animation.timeline.currentTime - 250 * MS_PER_SEC;
return retPromise;
}, 'Redundant change, after -> active, then back');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
- div.style.animation = ANIM_PROPERTY_VAL;
-
+ div.style.animation = 'anim 100s 100s';
var animation = div.getAnimations()[0];
-
var storedCurrentTime;
return animation.ready.then(function() {
storedCurrentTime = animation.currentTime;
animation.startTime = null;
return animation.ready;
}).then(function() {
assert_equals(animation.currentTime, storedCurrentTime,
'Test that hold time is correct');
});
}, 'Setting startTime to null');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
div.style.animation = 'anim 100s';
-
var animation = div.getAnimations()[0];
return animation.ready.then(function() {
var savedStartTime = animation.startTime;
assert_not_equals(animation.startTime, null,
'Animation.startTime not null on ready Promise resolve');
@@ -510,18 +363,18 @@ promise_test(function(t) {
assert_equals(animation.playState, 'paused',
'Animation.playState is "paused" after pause() call');
});
}, 'Animation.startTime after pausing');
promise_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
div.style.animation = 'anim 100s';
+ var animation = div.getAnimations()[0];
- var animation = div.getAnimations()[0];
return animation.ready.then(function() {
animation.cancel();
assert_equals(animation.startTime, null,
'The startTime of a cancelled animation should be null');
});
}, 'Animation.startTime after cancelling');
done();
--- a/dom/animation/test/css-transitions/file_animation-currenttime.html
+++ b/dom/animation/test/css-transitions/file_animation-currenttime.html
@@ -14,22 +14,16 @@
</style>
<script src="../testcommon.js"></script>
</head>
<body>
<script type="text/javascript">
'use strict';
-// TODO: add equivalent tests without an animation-delay, but first we need to
-// change the timing of animationstart dispatch. (Right now the animationstart
-// event will fire before the ready Promise is resolved if there is no
-// animation-delay.)
-// See https://bugzilla.mozilla.org/show_bug.cgi?id=1134163
-
// TODO: Once the computedTiming property is implemented, add checks to the
// checker helpers to ensure that computedTiming's properties are updated as
// expected.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1108055
const ANIM_DELAY_MS = 1000000; // 1000s
const ANIM_DUR_MS = 1000000; // 1000s
--- a/dom/animation/test/css-transitions/file_animation-starttime.html
+++ b/dom/animation/test/css-transitions/file_animation-starttime.html
@@ -14,22 +14,16 @@
</style>
<script src="../testcommon.js"></script>
</head>
<body>
<script type="text/javascript">
'use strict';
-// TODO: add equivalent tests without an animation-delay, but first we need to
-// change the timing of animationstart dispatch. (Right now the animationstart
-// event will fire before the ready Promise is resolved if there is no
-// animation-delay.)
-// See https://bugzilla.mozilla.org/show_bug.cgi?id=1134163
-
// TODO: Once the computedTiming property is implemented, add checks to the
// checker helpers to ensure that computedTiming's properties are updated as
// expected.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1108055
const ANIM_DELAY_MS = 1000000; // 1000s
const ANIM_DUR_MS = 1000000; // 1000s
--- a/dom/animation/test/testcommon.js
+++ b/dom/animation/test/testcommon.js
@@ -10,16 +10,30 @@
* failures in asynchronous test. For example, the short duration animation
* might be finished when animation.ready has been fulfilled because of slow
* platforms or busyness of the main thread.
* Setting short duration to cancel its animation does not matter but
* if you don't want to cancel the animation, consider using longer duration.
*/
const MS_PER_SEC = 1000;
+/* The recommended minimum precision to use for time values[1].
+ *
+ * [1] https://w3c.github.io/web-animations/#precision-of-time-values
+ */
+var TIME_PRECISION = 0.0005; // ms
+
+/*
+ * Allow implementations to substitute an alternative method for comparing
+ * times based on their precision requirements.
+ */
+function assert_times_equal(actual, expected, description) {
+ assert_approx_equals(actual, expected, TIME_PRECISION, description);
+}
+
/**
* Appends a div to the document body and creates an animation on the div.
* NOTE: This function asserts when trying to create animations with durations
* shorter than 100s because the shorter duration may cause intermittent
* failures. If you are not sure how long it is suitable, use 100s; it's
* long enough but shorter than our test framework timeout (330s).
* If you really need to use shorter durations, use animate() function directly.
*