2015-04-30 21:25:03 +03:00
|
|
|
<!doctype html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<meta charset=utf-8>
|
|
|
|
<title>Tests for the effect of setting a CSS animation's
|
|
|
|
Animation.currentTime</title>
|
|
|
|
<style>
|
|
|
|
|
|
|
|
.animated-div {
|
|
|
|
margin-left: 10px;
|
|
|
|
/* Make it easier to calculate expected values: */
|
|
|
|
animation-timing-function: linear ! important;
|
|
|
|
}
|
|
|
|
|
|
|
|
@keyframes anim {
|
|
|
|
from { margin-left: 100px; }
|
|
|
|
to { margin-left: 200px; }
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|
|
|
|
<script src="../testcommon.js"></script>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<script type="text/javascript">
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
2016-05-16 09:29:09 +03:00
|
|
|
// 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.
|
2015-04-30 21:25:03 +03:00
|
|
|
|
|
|
|
// 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'];
|
|
|
|
|
|
|
|
test(function(t)
|
|
|
|
{
|
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s";
|
2015-04-30 21:25:03 +03:00
|
|
|
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');
|
|
|
|
|
2016-05-16 09:29:09 +03:00
|
|
|
// Make sure the animation is running before we set the current time.
|
2015-04-30 21:25:03 +03:00
|
|
|
animation.startTime = animation.timeline.currentTime;
|
|
|
|
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 50 * MS_PER_SEC;
|
|
|
|
assert_times_equal(animation.currentTime, 50 * MS_PER_SEC,
|
2015-04-30 21:25:03 +03:00
|
|
|
'Check setting of currentTime actually works');
|
|
|
|
}, 'Sanity test to check round-tripping assigning to new animation\'s ' +
|
|
|
|
'currentTime');
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-04-30 21:25:03 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
|
|
|
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s 100s";
|
2015-04-30 21:25:03 +03:00
|
|
|
var animation = div.getAnimations()[0];
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return animation.ready.then(function() {
|
2016-05-16 09:29:09 +03:00
|
|
|
// 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 = 100 * MS_PER_SEC;
|
2015-04-30 21:25:03 +03:00
|
|
|
return eventWatcher.wait_for('animationstart');
|
2016-04-20 02:21:17 +03:00
|
|
|
}).then(function() {
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 200 * MS_PER_SEC;
|
2015-04-30 21:25:03 +03:00
|
|
|
return eventWatcher.wait_for('animationend');
|
|
|
|
});
|
|
|
|
}, 'Skipping forward through animation');
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-04-30 21:25:03 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
|
|
|
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s 100s";
|
2015-04-30 21:25:03 +03:00
|
|
|
var animation = div.getAnimations()[0];
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 200 * MS_PER_SEC;
|
2015-04-30 21:25:03 +03:00
|
|
|
var previousTimelineTime = animation.timeline.currentTime;
|
|
|
|
|
2016-05-16 09:29:09 +03:00
|
|
|
return eventWatcher.wait_for(['animationstart',
|
|
|
|
'animationend']).then(function() {
|
2015-04-30 21:25:03 +03:00
|
|
|
assert_true(document.timeline.currentTime - previousTimelineTime <
|
2016-05-16 09:29:09 +03:00
|
|
|
100 * MS_PER_SEC,
|
2015-04-30 21:25:03 +03:00
|
|
|
'Sanity check that seeking worked rather than the events ' +
|
|
|
|
'firing after normal playback through the very long ' +
|
|
|
|
'animation duration');
|
|
|
|
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 150 * MS_PER_SEC;
|
|
|
|
return eventWatcher.wait_for('animationstart');
|
2016-04-20 02:21:17 +03:00
|
|
|
}).then(function() {
|
2015-04-30 21:25:03 +03:00
|
|
|
animation.currentTime = 0;
|
|
|
|
return eventWatcher.wait_for('animationend');
|
|
|
|
});
|
2016-04-20 02:21:17 +03:00
|
|
|
}, 'Skipping backwards through animation');
|
2016-04-19 13:36:20 +03:00
|
|
|
|
2015-04-30 21:25:03 +03:00
|
|
|
// 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.
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-04-30 21:25:03 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
|
|
|
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s 100s";
|
2015-04-30 21:25:03 +03:00
|
|
|
var animation = div.getAnimations()[0];
|
|
|
|
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 150 * MS_PER_SEC;
|
|
|
|
animation.currentTime = 50 * MS_PER_SEC;
|
2015-04-30 21:25:03 +03:00
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return waitForAnimationFrames(2);
|
2015-04-30 21:25:03 +03:00
|
|
|
}, 'Redundant change, before -> active, then back');
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-04-30 21:25:03 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
|
|
|
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s 100s";
|
2015-04-30 21:25:03 +03:00
|
|
|
var animation = div.getAnimations()[0];
|
|
|
|
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 250 * MS_PER_SEC;
|
|
|
|
animation.currentTime = 50 * MS_PER_SEC;
|
2015-04-30 21:25:03 +03:00
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return waitForAnimationFrames(2);
|
2015-04-30 21:25:03 +03:00
|
|
|
}, 'Redundant change, before -> after, then back');
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-04-30 21:25:03 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
|
|
|
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s 100s";
|
2015-04-30 21:25:03 +03:00
|
|
|
var animation = div.getAnimations()[0];
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
var retPromise = eventWatcher.wait_for('animationstart').then(function() {
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 50 * MS_PER_SEC;
|
|
|
|
animation.currentTime = 150 * MS_PER_SEC;
|
2015-04-30 21:25:03 +03:00
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return waitForAnimationFrames(2);
|
2015-04-30 21:25:03 +03:00
|
|
|
});
|
|
|
|
// get us into the initial state:
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 150 * MS_PER_SEC;
|
2016-04-20 02:21:17 +03:00
|
|
|
|
|
|
|
return retPromise;
|
2015-04-30 21:25:03 +03:00
|
|
|
}, 'Redundant change, active -> before, then back');
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-04-30 21:25:03 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
|
|
|
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s 100s";
|
2015-04-30 21:25:03 +03:00
|
|
|
var animation = div.getAnimations()[0];
|
|
|
|
|
2016-05-16 09:29:09 +03:00
|
|
|
var retPromise = eventWatcher.wait_for('animationstart').then(function() {
|
|
|
|
animation.currentTime = 250 * MS_PER_SEC;
|
|
|
|
animation.currentTime = 150 * MS_PER_SEC;
|
2015-04-30 21:25:03 +03:00
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return waitForAnimationFrames(2);
|
2015-04-30 21:25:03 +03:00
|
|
|
});
|
|
|
|
// get us into the initial state:
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 150 * MS_PER_SEC;
|
2016-04-20 02:21:17 +03:00
|
|
|
|
|
|
|
return retPromise;
|
2015-04-30 21:25:03 +03:00
|
|
|
}, 'Redundant change, active -> after, then back');
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-04-30 21:25:03 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
|
|
|
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s 100s";
|
2015-04-30 21:25:03 +03:00
|
|
|
var animation = div.getAnimations()[0];
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
var retPromise = eventWatcher.wait_for(['animationstart',
|
|
|
|
'animationend']).then(function() {
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 50 * MS_PER_SEC;
|
|
|
|
animation.currentTime = 250 * MS_PER_SEC;
|
2015-04-30 21:25:03 +03:00
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return waitForAnimationFrames(2);
|
2015-04-30 21:25:03 +03:00
|
|
|
});
|
|
|
|
// get us into the initial state:
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 250 * MS_PER_SEC;
|
2016-04-20 02:21:17 +03:00
|
|
|
|
|
|
|
return retPromise;
|
2015-04-30 21:25:03 +03:00
|
|
|
}, 'Redundant change, after -> before, then back');
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-04-30 21:25:03 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
|
|
|
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s 100s";
|
2015-04-30 21:25:03 +03:00
|
|
|
var animation = div.getAnimations()[0];
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
var retPromise = eventWatcher.wait_for(['animationstart',
|
|
|
|
'animationend']).then(function() {
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 150 * MS_PER_SEC;
|
|
|
|
animation.currentTime = 250 * MS_PER_SEC;
|
2015-04-30 21:25:03 +03:00
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return waitForAnimationFrames(2);
|
2015-04-30 21:25:03 +03:00
|
|
|
});
|
|
|
|
// get us into the initial state:
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 250 * MS_PER_SEC;
|
2016-04-20 02:21:17 +03:00
|
|
|
|
|
|
|
return retPromise;
|
2015-04-30 21:25:03 +03:00
|
|
|
}, 'Redundant change, after -> active, then back');
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-09-28 06:38:41 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
|
|
|
var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s"
|
2015-09-28 06:38:41 +03:00
|
|
|
var animation = div.getAnimations()[0];
|
|
|
|
|
|
|
|
animation.pause();
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 150 * MS_PER_SEC;
|
2015-09-28 06:38:41 +03:00
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return eventWatcher.wait_for(['animationstart',
|
|
|
|
'animationend']).then(function() {
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 50 * MS_PER_SEC;
|
2015-09-28 06:38:41 +03:00
|
|
|
return eventWatcher.wait_for('animationstart');
|
2016-04-20 02:21:17 +03:00
|
|
|
});
|
2015-09-28 06:38:41 +03:00
|
|
|
}, 'Seeking finished -> paused dispatches animationstart');
|
2015-04-30 21:25:03 +03:00
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-04-30 21:25:03 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s";
|
2015-04-30 21:25:03 +03:00
|
|
|
|
|
|
|
var animation = div.getAnimations()[0];
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return animation.ready.then(function() {
|
2015-04-30 21:25:03 +03:00
|
|
|
var exception;
|
|
|
|
try {
|
|
|
|
animation.currentTime = null;
|
|
|
|
} catch (e) {
|
|
|
|
exception = e;
|
|
|
|
}
|
|
|
|
assert_equals(exception.name, 'TypeError',
|
|
|
|
'Expect TypeError exception on trying to set ' +
|
|
|
|
'Animation.currentTime to null');
|
|
|
|
});
|
|
|
|
}, 'Setting currentTime to null');
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-04-30 21:25:03 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
|
|
|
div.style.animation = 'anim 100s';
|
|
|
|
|
|
|
|
var animation = div.getAnimations()[0];
|
|
|
|
var pauseTime;
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return animation.ready.then(function() {
|
2015-04-30 21:25:03 +03:00
|
|
|
assert_not_equals(animation.currentTime, null,
|
|
|
|
'Animation.currentTime not null on ready Promise resolve');
|
|
|
|
animation.pause();
|
|
|
|
return animation.ready;
|
2016-04-20 02:21:17 +03:00
|
|
|
}).then(function() {
|
2015-04-30 21:25:03 +03:00
|
|
|
pauseTime = animation.currentTime;
|
|
|
|
return waitForFrame();
|
2016-04-20 02:21:17 +03:00
|
|
|
}).then(function() {
|
2015-04-30 21:25:03 +03:00
|
|
|
assert_equals(animation.currentTime, pauseTime,
|
|
|
|
'Animation.currentTime is unchanged after pausing');
|
|
|
|
});
|
|
|
|
}, 'Animation.currentTime after pausing');
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-04-30 21:25:03 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s";
|
2015-04-30 21:25:03 +03:00
|
|
|
var animation = div.getAnimations()[0];
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return animation.ready.then(function() {
|
2015-04-30 21:25:03 +03:00
|
|
|
// just before animation ends:
|
2016-05-16 09:29:09 +03:00
|
|
|
animation.currentTime = 100 * MS_PER_SEC - 1;
|
2015-04-30 21:25:03 +03:00
|
|
|
return waitForAnimationFrames(2);
|
2016-04-20 02:21:17 +03:00
|
|
|
}).then(function() {
|
2016-05-16 09:29:09 +03:00
|
|
|
assert_equals(animation.currentTime, 100 * MS_PER_SEC,
|
2015-04-30 21:25:03 +03:00
|
|
|
'Animation.currentTime should not continue to increase after the ' +
|
|
|
|
'animation has finished');
|
2016-04-20 02:21:17 +03:00
|
|
|
});
|
2015-04-30 21:25:03 +03:00
|
|
|
}, 'Animation.currentTime clamping');
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-04-30 21:25:03 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
2016-05-16 09:29:09 +03:00
|
|
|
div.style.animation = "anim 100s";
|
2015-04-30 21:25:03 +03:00
|
|
|
var animation = div.getAnimations()[0];
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return animation.ready.then(function() {
|
2015-04-30 21:25:03 +03:00
|
|
|
// play backwards:
|
|
|
|
animation.playbackRate = -1;
|
|
|
|
|
|
|
|
// just before animation ends (at the "start"):
|
|
|
|
animation.currentTime = 1;
|
|
|
|
|
|
|
|
return waitForAnimationFrames(2);
|
2016-04-20 02:21:17 +03:00
|
|
|
}).then(function() {
|
2015-04-30 21:25:03 +03:00
|
|
|
assert_equals(animation.currentTime, 0,
|
|
|
|
'Animation.currentTime should not continue to decrease after an ' +
|
|
|
|
'animation running in reverse has finished and currentTime is zero');
|
2016-04-20 02:21:17 +03:00
|
|
|
});
|
2015-04-30 21:25:03 +03:00
|
|
|
}, '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();
|
2016-05-16 09:29:09 +03:00
|
|
|
|
2015-04-30 21:25:03 +03:00
|
|
|
assert_equals(animation.currentTime, null,
|
|
|
|
'The currentTime of a cancelled animation should be null');
|
|
|
|
}, 'Animation.currentTime after cancelling');
|
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
promise_test(function(t) {
|
2015-05-08 10:17:13 +03:00
|
|
|
var div = addDiv(t, {'class': 'animated-div'});
|
|
|
|
div.style.animation = 'anim 100s';
|
|
|
|
var animation = div.getAnimations()[0];
|
2016-05-16 09:29:09 +03:00
|
|
|
|
2016-04-20 02:21:17 +03:00
|
|
|
return animation.ready.then(function() {
|
2015-05-08 10:17:13 +03:00
|
|
|
animation.finish();
|
|
|
|
|
|
|
|
// Initiate a pause then abort it
|
|
|
|
animation.pause();
|
|
|
|
animation.play();
|
|
|
|
|
|
|
|
// Wait to return to running state
|
|
|
|
return animation.ready;
|
2016-04-20 02:21:17 +03:00
|
|
|
}).then(function() {
|
2015-05-08 10:17:13 +03:00
|
|
|
assert_true(animation.currentTime < 100 * 1000,
|
|
|
|
'After aborting a pause when finished, the currentTime should'
|
|
|
|
+ ' jump back towards the start of the animation');
|
2016-04-20 02:21:17 +03:00
|
|
|
});
|
2015-05-08 10:17:13 +03:00
|
|
|
}, 'After aborting a pause when finished, the call to play() should rewind'
|
|
|
|
+ ' the current time');
|
|
|
|
|
2015-04-30 21:25:03 +03:00
|
|
|
done();
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|