Merge inbound to mozilla-central. a=merge FIREFOX_NIGHTLY_60_END
authorBogdan Tara <btara@mozilla.com>
Mon, 12 Mar 2018 11:55:11 +0200
changeset 766174 fdd1a0082c71673239fc2f3a6a93de889c07a1be
parent 766173 e29b542016965349d12ed6c2c52b2f08e513d9cf (current diff)
parent 766162 d6ccaacd9692853a006461e883b4b9284c0e2964 (diff)
child 766175 e7b736c64e87afa0cf39066f6956f11fadb1ce42
child 766177 7ff7076a25c4044e1e228f2fa1c05104a6986557
child 766189 95bc2c3c88701384ec67adfe23283a85420509ba
child 766191 7ee4af16446f0bb17e346d0d54c9724d6f8bb868
child 766203 28e0fd3bb4afac764585481c89047b6ca99768ae
child 766205 07d8b04d06d6d16ee7e26c98208e5aaba6ae3803
child 766208 d0abc82219b85eaf1e5f5baef6e258bfb1503483
child 766209 e677364f32493959749db65477dcae8cd778c5e9
child 766210 0d7b23b03e251050bbae501ccc47d02099ba0626
child 766211 a1171de0b81e5a7fad690439475bf031ed612ed8
child 766230 5da1576179c9f67a7c88f43fbbd5c5a0d7d52345
child 766241 3782a7b5b5d4a4fb49849240bcb1df38124e94a3
child 766309 c8d997beec2c6880bc825b0fdd5fa134666915de
child 766326 f6cddc3fff0ee1bd5ed4d306170c0ae820626c4b
child 766455 11b3db8b3ea21907bcc8dcb16b7020797820e0cc
child 766456 f31c313a4351a4cc5768f58979e58c31d70e8ead
child 766463 ba49fafd4e53105c0409c8815f24dccd9395fa2f
child 766624 330c5631c89fb1b19c34e62e7327b691bc73b29e
child 768009 572d96d428b3647692c46e9da92b3835c666a4cc
child 774071 8d9daab95d68cfa398cdf951e4371d3a299f5906
push id102243
push userbmo:hsivonen@hsivonen.fi
push dateMon, 12 Mar 2018 10:44:05 +0000
reviewersmerge
milestone60.0a1
Merge inbound to mozilla-central. a=merge
dom/animation/test/css-animations/file_animation-cancel.html
dom/animation/test/css-animations/file_animation-computed-timing.html
dom/animation/test/css-animations/file_animation-currenttime.html
dom/animation/test/css-animations/file_animation-finish.html
dom/animation/test/css-animations/file_animation-finished.html
dom/animation/test/css-animations/file_animation-id.html
dom/animation/test/css-animations/file_animation-pausing.html
dom/animation/test/css-animations/file_animation-playstate.html
dom/animation/test/css-animations/file_animation-ready.html
dom/animation/test/css-animations/file_animation-reverse.html
dom/animation/test/css-animations/file_animation-starttime.html
dom/animation/test/css-animations/file_animations-dynamic-changes.html
dom/animation/test/css-animations/file_cssanimation-animationname.html
dom/animation/test/css-animations/file_document-get-animations.html
dom/animation/test/css-animations/file_effect-target.html
dom/animation/test/css-animations/file_element-get-animations.html
dom/animation/test/css-animations/file_event-dispatch.html
dom/animation/test/css-animations/file_event-order.html
dom/animation/test/css-animations/file_keyframeeffect-getkeyframes.html
dom/animation/test/css-animations/file_pseudoElement-get-animations.html
dom/animation/test/css-animations/file_setting-effect.html
dom/animation/test/css-animations/test_animation-cancel.html
dom/animation/test/css-animations/test_animation-computed-timing.html
dom/animation/test/css-animations/test_animation-currenttime.html
dom/animation/test/css-animations/test_animation-finish.html
dom/animation/test/css-animations/test_animation-finished.html
dom/animation/test/css-animations/test_animation-id.html
dom/animation/test/css-animations/test_animation-pausing.html
dom/animation/test/css-animations/test_animation-playstate.html
dom/animation/test/css-animations/test_animation-ready.html
dom/animation/test/css-animations/test_animation-reverse.html
dom/animation/test/css-animations/test_animation-starttime.html
dom/animation/test/css-animations/test_animations-dynamic-changes.html
dom/animation/test/css-animations/test_cssanimation-animationname.html
dom/animation/test/css-animations/test_document-get-animations.html
dom/animation/test/css-animations/test_effect-target.html
dom/animation/test/css-animations/test_element-get-animations.html
dom/animation/test/css-animations/test_event-dispatch.html
dom/animation/test/css-animations/test_event-order.html
dom/animation/test/css-animations/test_keyframeeffect-getkeyframes.html
dom/animation/test/css-animations/test_pseudoElement-get-animations.html
dom/animation/test/css-animations/test_setting-effect.html
dom/animation/test/css-transitions/file_animation-cancel.html
dom/animation/test/css-transitions/file_animation-computed-timing.html
dom/animation/test/css-transitions/file_animation-currenttime.html
dom/animation/test/css-transitions/file_animation-finished.html
dom/animation/test/css-transitions/file_animation-pausing.html
dom/animation/test/css-transitions/file_animation-ready.html
dom/animation/test/css-transitions/file_animation-starttime.html
dom/animation/test/css-transitions/file_csstransition-transitionproperty.html
dom/animation/test/css-transitions/file_document-get-animations.html
dom/animation/test/css-transitions/file_effect-target.html
dom/animation/test/css-transitions/file_element-get-animations.html
dom/animation/test/css-transitions/file_event-dispatch.html
dom/animation/test/css-transitions/file_keyframeeffect-getkeyframes.html
dom/animation/test/css-transitions/file_pseudoElement-get-animations.html
dom/animation/test/css-transitions/file_setting-effect.html
dom/animation/test/css-transitions/test_animation-cancel.html
dom/animation/test/css-transitions/test_animation-computed-timing.html
dom/animation/test/css-transitions/test_animation-currenttime.html
dom/animation/test/css-transitions/test_animation-finished.html
dom/animation/test/css-transitions/test_animation-pausing.html
dom/animation/test/css-transitions/test_animation-ready.html
dom/animation/test/css-transitions/test_animation-starttime.html
dom/animation/test/css-transitions/test_csstransition-transitionproperty.html
dom/animation/test/css-transitions/test_document-get-animations.html
dom/animation/test/css-transitions/test_effect-target.html
dom/animation/test/css-transitions/test_element-get-animations.html
dom/animation/test/css-transitions/test_event-dispatch.html
dom/animation/test/css-transitions/test_keyframeeffect-getkeyframes.html
dom/animation/test/css-transitions/test_pseudoElement-get-animations.html
dom/animation/test/css-transitions/test_setting-effect.html
dom/animation/test/document-timeline/file_document-timeline.html
dom/animation/test/document-timeline/test_document-timeline.html
dom/animation/test/mozilla/file_cubic_bezier_limits.html
dom/animation/test/mozilla/file_disabled_properties.html
dom/animation/test/mozilla/file_discrete-animations.html
dom/animation/test/mozilla/file_document-timeline-origin-time-range.html
dom/animation/test/mozilla/file_hide_and_show.html
dom/animation/test/mozilla/file_restyling_xhr_doc.html
dom/animation/test/mozilla/file_set-easing.html
dom/animation/test/mozilla/file_transform_limits.html
dom/animation/test/mozilla/file_underlying-discrete-value.html
dom/animation/test/mozilla/test_cubic_bezier_limits.html
dom/animation/test/mozilla/test_disabled_properties.html
dom/animation/test/mozilla/test_discrete-animations.html
dom/animation/test/mozilla/test_document-timeline-origin-time-range.html
dom/animation/test/mozilla/test_hide_and_show.html
dom/animation/test/mozilla/test_moz-prefixed-properties.html
dom/animation/test/mozilla/test_restyling_xhr_doc.html
dom/animation/test/mozilla/test_set-easing.html
dom/animation/test/mozilla/test_transform_limits.html
dom/animation/test/mozilla/test_underlying-discrete-value.html
dom/animation/test/style/file_animation-seeking-with-current-time.html
dom/animation/test/style/file_animation-seeking-with-start-time.html
dom/animation/test/style/file_animation-setting-effect.html
dom/animation/test/style/file_composite.html
dom/animation/test/style/file_missing-keyframe-on-compositor.html
dom/animation/test/style/file_missing-keyframe.html
dom/animation/test/style/test_animation-seeking-with-current-time.html
dom/animation/test/style/test_animation-seeking-with-start-time.html
dom/animation/test/style/test_animation-setting-effect.html
dom/animation/test/style/test_composite.html
dom/animation/test/style/test_missing-keyframe-on-compositor.html
dom/animation/test/style/test_missing-keyframe.html
layout/style/test/file_animations_effect_timing_duration.html
layout/style/test/file_animations_effect_timing_enddelay.html
layout/style/test/file_animations_effect_timing_iterations.html
layout/style/test/file_animations_iterationstart.html
layout/style/test/file_animations_pausing.html
layout/style/test/file_animations_playbackrate.html
layout/style/test/file_animations_reverse.html
layout/style/test/file_animations_styles_on_event.html
layout/style/test/file_transitions_replacement_on_busy_frame.html
layout/style/test/test_animations_effect_timing_duration.html
layout/style/test/test_animations_effect_timing_enddelay.html
layout/style/test/test_animations_effect_timing_iterations.html
layout/style/test/test_animations_iterationstart.html
layout/style/test/test_animations_pausing.html
layout/style/test/test_animations_playbackrate.html
layout/style/test/test_animations_reverse.html
layout/style/test/test_animations_styles_on_event.html
layout/style/test/test_transitions_replacement_on_busy_frame.html
--- a/accessible/base/TextAttrs.h
+++ b/accessible/base/TextAttrs.h
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsTextAttrs_h_
 #define nsTextAttrs_h_
 
 #include "nsCOMPtr.h"
 #include "nsColor.h"
+#include "nsString.h"
 #include "nsStyleConsts.h"
 
 class nsIFrame;
 class nsIPersistentProperties;
 class nsIContent;
 class nsDeviceContext;
 
 namespace mozilla {
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animation-cancel.html
+++ /dev/null
@@ -1,191 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes translateAnim {
-  to { transform: translate(100px) }
-}
-@keyframes marginLeftAnim {
-  to { margin-left: 100px }
-}
-@keyframes marginLeftAnim100To200 {
-  from { margin-left: 100px }
-  to { margin-left: 200px }
-}
-</style>
-<body>
-<script>
-'use strict';
-
-promise_test(function(t) {
-  var div = addDiv(t, { style: 'animation: translateAnim 100s' });
-  var animation = div.getAnimations()[0];
-
-  return animation.ready.then(function() {
-    assert_not_equals(getComputedStyle(div).transform, 'none',
-                      'transform style is animated before cancelling');
-    animation.cancel();
-    assert_equals(getComputedStyle(div).transform, 'none',
-                  'transform style is no longer animated after cancelling');
-  });
-}, 'Animated style is cleared after cancelling a running CSS animation');
-
-promise_test(function(t) {
-  var div = addDiv(t, { style: 'animation: translateAnim 100s forwards' });
-  var animation = div.getAnimations()[0];
-  animation.finish();
-
-  return animation.ready.then(function() {
-    assert_not_equals(getComputedStyle(div).transform, 'none',
-                      'transform style is filling before cancelling');
-    animation.cancel();
-    assert_equals(getComputedStyle(div).transform, 'none',
-                  'fill style is cleared after cancelling');
-  });
-}, 'Animated style is cleared after cancelling a filling CSS animation');
-
-test(function(t) {
-  var div = addDiv(t, { style: 'animation: marginLeftAnim 100s linear' });
-  var animation = div.getAnimations()[0];
-  animation.cancel();
-
-  assert_equals(getComputedStyle(div).marginLeft, '0px',
-                'margin-left style is not animated after cancelling');
-
-  animation.currentTime = 50 * 1000;
-  assert_equals(getComputedStyle(div).marginLeft, '50px',
-                'margin-left style is updated when cancelled animation is'
-                + ' seeked');
-}, 'After canceling an animation, it can still be seeked');
-
-promise_test(function(t) {
-  var div =
-    addDiv(t, { style: 'animation: marginLeftAnim100To200 100s linear' });
-  var animation = div.getAnimations()[0];
-
-  return animation.ready.then(function() {
-    animation.cancel();
-    assert_equals(getComputedStyle(div).marginLeft, '0px',
-                  'margin-left style is not animated after cancelling');
-    animation.play();
-    assert_equals(getComputedStyle(div).marginLeft, '100px',
-                  'margin-left style is animated after re-starting animation');
-    return animation.ready;
-  }).then(function() {
-    assert_equals(animation.playState, 'running',
-                  'Animation succeeds in running after being re-started');
-  });
-}, 'After cancelling an animation, it can still be re-used');
-
-test(function(t) {
-  var div =
-    addDiv(t, { style: 'animation: marginLeftAnim100To200 100s linear' });
-  var animation = div.getAnimations()[0];
-  animation.cancel();
-  assert_equals(getComputedStyle(div).marginLeft, '0px',
-                'margin-left style is not animated after cancelling');
-
-  // Trigger a change to some animation properties and check that this
-  // doesn't cause the animation to become live again
-  div.style.animationDuration = '200s';
-  assert_equals(getComputedStyle(div).marginLeft, '0px',
-                'margin-left style is still not animated after updating'
-                + ' animation-duration');
-  assert_equals(animation.playState, 'idle',
-                'Animation is still idle after updating animation-duration');
-}, 'After cancelling an animation, updating animation properties doesn\'t make'
-   + ' it live again');
-
-test(function(t) {
-  var div =
-    addDiv(t, { style: 'animation: marginLeftAnim100To200 100s linear' });
-  var animation = div.getAnimations()[0];
-  animation.cancel();
-  assert_equals(getComputedStyle(div).marginLeft, '0px',
-                'margin-left style is not animated after cancelling');
-
-  // Make some changes to animation-play-state and check that the
-  // animation doesn't become live again. This is because it should be
-  // possible to cancel an animation from script such that all future
-  // changes to style are ignored.
-
-  // Redundant change
-  div.style.animationPlayState = 'running';
-  assert_equals(animation.playState, 'idle',
-                'Animation is still idle after a redundant change to'
-                + ' animation-play-state');
-
-  // Pause
-  div.style.animationPlayState = 'paused';
-  assert_equals(animation.playState, 'idle',
-                'Animation is still idle after setting'
-                + ' animation-play-state: paused');
-
-  // Play
-  div.style.animationPlayState = 'running';
-  assert_equals(animation.playState, 'idle',
-                'Animation is still idle after re-setting'
-                + ' animation-play-state: running');
-
-}, 'After cancelling an animation, updating animation-play-state doesn\'t'
-   + ' make it live again');
-
-promise_test(function(t) {
-  var div = addDiv(t, { style: 'animation: translateAnim 10s both' });
-  div.style.marginLeft = '0px';
-
-  var animation = div.getAnimations()[0];
-
-  return animation.ready.then(function() {
-    assert_equals(animation.playState, 'running');
-
-    div.style.animationName = 'none';
-    flushComputedStyle(div);
-    return waitForFrame();
-  }).then(function() {
-    assert_equals(animation.playState, 'idle');
-    assert_equals(getComputedStyle(div).marginLeft, '0px');
-  });
-}, 'Setting animation-name to \'none\' cancels the animation');
-
-promise_test(function(t) {
-  var div = addDiv(t, { style: 'animation: translateAnim 10s both' });
-  var animation = div.getAnimations()[0];
-
-  return animation.ready.then(function() {
-    assert_equals(animation.playState, 'running');
-
-    div.style.display = 'none';
-    return waitForFrame();
-  }).then(function() {
-    assert_equals(animation.playState, 'idle');
-    assert_equals(getComputedStyle(div).marginLeft, '0px');
-  });
-}, 'Setting display:none on an element cancel its animations');
-
-promise_test(function(t) {
-  var parentDiv = addDiv(t);
-  var childDiv  = document.createElement('div');
-  parentDiv.appendChild(childDiv);
-
-  childDiv.setAttribute('style', 'animation: translateAnim 10s both');
-  flushComputedStyle(childDiv);
-
-  var animation = childDiv.getAnimations()[0];
-
-  return animation.ready.then(function() {
-    assert_equals(animation.playState, 'running');
-
-    parentDiv.style.display = 'none';
-    return waitForFrame();
-  }).then(function() {
-    assert_equals(animation.playState, 'idle');
-    assert_equals(getComputedStyle(childDiv).marginLeft, '0px');
-  });
-}, 'Setting display:none on an ancestor element cancels animations on ' +
-   'descendants');
-
-done();
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animation-computed-timing.html
+++ /dev/null
@@ -1,566 +0,0 @@
-<!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>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animation-currenttime.html
+++ /dev/null
@@ -1,345 +0,0 @@
-<!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';
-
-// 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'];
-
-test(function(t)
-{
-  var div = addDiv(t, {'class': 'animated-div'});
-  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');
-
-  // Make sure the animation is running before we set the current time.
-  animation.startTime = animation.timeline.currentTime;
-
-  animation.currentTime = 50 * MS_PER_SEC;
-  assert_time_equals_literal(animation.currentTime, 50 * MS_PER_SEC,
-    'Check setting of currentTime actually works');
-}, '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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  return animation.ready.then(function() {
-    // 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;
-    return eventWatcher.wait_for('animationstart');
-  }).then(function() {
-    animation.currentTime = 200 * MS_PER_SEC;
-    return eventWatcher.wait_for('animationend');
-  });
-}, '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 100s 100s";
-  var animation = div.getAnimations()[0];
-  animation.currentTime = 200 * MS_PER_SEC;
-  var previousTimelineTime = animation.timeline.currentTime;
-
-  return eventWatcher.wait_for(['animationstart',
-                                'animationend']).then(function() {
-    assert_true(document.timeline.currentTime - previousTimelineTime <
-                100 * MS_PER_SEC,
-                'Sanity check that seeking worked rather than the events ' +
-                'firing after normal playback through the very long ' +
-                'animation duration');
-
-    animation.currentTime = 150 * MS_PER_SEC;
-    return eventWatcher.wait_for('animationstart');
-  }).then(function() {
-    animation.currentTime = 0;
-    return eventWatcher.wait_for('animationend');
-  });
-}, '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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  var retPromise = eventWatcher.wait_for('animationstart').then(function() {
-    animation.currentTime = 50 * MS_PER_SEC;
-    animation.currentTime = 150 * MS_PER_SEC;
-
-    return waitForAnimationFrames(2);
-  });
-  // get us into the initial state:
-  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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  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 = 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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  var retPromise =  eventWatcher.wait_for(['animationstart',
-                                           'animationend']).then(function() {
-    animation.currentTime = 50 * MS_PER_SEC;
-    animation.currentTime = 250 * MS_PER_SEC;
-
-    return waitForAnimationFrames(2);
-  });
-  // get us into the initial state:
-  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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  var retPromise =  eventWatcher.wait_for(['animationstart',
-                                           'animationend']).then(function() {
-    animation.currentTime = 150 * MS_PER_SEC;
-    animation.currentTime = 250 * MS_PER_SEC;
-
-    return waitForAnimationFrames(2);
-  });
-  // get us into the initial state:
-  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 100s"
-  var animation = div.getAnimations()[0];
-
-  animation.pause();
-  animation.currentTime = 150 * MS_PER_SEC;
-
-  return eventWatcher.wait_for(['animationstart',
-                                'animationend']).then(function() {
-    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 100s";
-
-  var animation = div.getAnimations()[0];
-
-  return animation.ready.then(function() {
-    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');
-
-promise_test(function(t) {
-  var div = addDiv(t, {'class': 'animated-div'});
-  div.style.animation = 'anim 100s';
-
-  var animation = div.getAnimations()[0];
-  var pauseTime;
-
-  return animation.ready.then(function() {
-    assert_not_equals(animation.currentTime, null,
-      'Animation.currentTime not null on ready Promise resolve');
-    animation.pause();
-    return animation.ready;
-  }).then(function() {
-    pauseTime = animation.currentTime;
-    return waitForFrame();
-  }).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 100s";
-  var animation = div.getAnimations()[0];
-
-  return animation.ready.then(function() {
-    // just before animation ends:
-    animation.currentTime = 100 * MS_PER_SEC - 1;
-    return waitForAnimationFrames(2);
-  }).then(function() {
-    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 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;
-
-    return waitForAnimationFrames(2);
-  }).then(function() {
-    assert_equals(animation.currentTime, 0,
-      '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];
-
-  return animation.ready.then(function() {
-    animation.finish();
-
-    // Initiate a pause then abort it
-    animation.pause();
-    animation.play();
-
-    // Wait to return to running state
-    return animation.ready;
-  }).then(function() {
-    assert_true(animation.currentTime < 100 * 1000,
-                'After aborting a pause when finished, the currentTime should'
-                + ' jump back towards the start of the animation');
-  });
-}, 'After aborting a pause when finished, the call to play() should rewind'
-   + ' the current time');
-
-done();
-    </script>
-  </body>
-</html>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animation-finish.html
+++ /dev/null
@@ -1,95 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes anim {
-  from { margin-left: 100px; }
-  to { margin-left: 200px; }
-}
-</style>
-<body>
-<script>
-
-'use strict';
-
-const ANIM_PROP_VAL = 'anim 100s';
-const ANIM_DURATION = 100000; // ms
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = ANIM_PROP_VAL;
-  div.style.animationIterationCount = 'infinite';
-  var animation = div.getAnimations()[0];
-
-  var threw = false;
-  try {
-    animation.finish();
-  } catch (e) {
-    threw = true;
-    assert_equals(e.name, 'InvalidStateError',
-                  'Exception should be an InvalidStateError exception when ' +
-                  'trying to finish an infinite animation');
-  }
-  assert_true(threw,
-              'Expect InvalidStateError exception trying to finish an ' +
-              'infinite animation');
-}, 'Test exceptions when finishing infinite animation');
-
-async_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = ANIM_PROP_VAL + ' paused';
-  var animation = div.getAnimations()[0];
-
-  animation.ready.then(t.step_func(function() {
-    animation.finish();
-    assert_equals(animation.playState, 'finished',
-                  'The play state of a paused animation should become ' +
-                  '"finished" after finish() is called');
-    assert_times_equal(animation.startTime,
-                       animation.timeline.currentTime - ANIM_DURATION,
-                       'The start time of a paused animation should be set ' +
-                       'after calling finish()');
-    t.done();
-  }));
-}, 'Test finish() while paused');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = ANIM_PROP_VAL + ' paused';
-  var animation = div.getAnimations()[0];
-
-  // Update playbackRate so we can test that the calculated startTime
-  // respects it
-  animation.playbackRate = 2;
-
-  // While animation is still pause-pending call finish()
-  animation.finish();
-
-  assert_equals(animation.playState, 'finished',
-                'The play state of a pause-pending animation should become ' +
-                '"finished" after finish() is called');
-  assert_times_equal(animation.startTime,
-                     animation.timeline.currentTime - ANIM_DURATION / 2,
-                     'The start time of a pause-pending animation should ' +
-                     'be set after calling finish()');
-}, 'Test finish() while pause-pending with positive playbackRate');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = ANIM_PROP_VAL + ' paused';
-  var animation = div.getAnimations()[0];
-
-  animation.playbackRate = -2;
-  animation.finish();
-
-  assert_equals(animation.playState, 'finished',
-                'The play state of a pause-pending animation should become ' +
-                '"finished" after finish() is called');
-  assert_equals(animation.startTime, animation.timeline.currentTime,
-                'The start time of a pause-pending animation should be ' +
-                'set after calling finish()');
-}, 'Test finish() while pause-pending with negative playbackRate');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animation-finished.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes abc {
-  to { transform: translate(10px) }
-}
-@keyframes def {}
-</style>
-<body>
-<script>
-'use strict';
-
-const ANIM_PROP_VAL = 'abc 100s';
-const ANIM_DURATION = 100 * MS_PER_SEC;
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  // Set up pending animation
-  div.style.animation = ANIM_PROP_VAL;
-  var animation = div.getAnimations()[0];
-  var previousFinishedPromise = animation.finished;
-  // Set up listeners on finished promise
-  var retPromise = animation.finished.then(function() {
-    assert_unreached('finished promise is fulfilled');
-  }).catch(function(err) {
-    assert_equals(err.name, 'AbortError',
-                  'finished promise is rejected with AbortError');
-    assert_not_equals(animation.finished, previousFinishedPromise,
-                      'Finished promise should change after the original is ' +
-                      'rejected');
-  });
-
-  // Now cancel the animation and flush styles
-  div.style.animation = '';
-  getComputedStyle(div).animation;
-
-  return retPromise;
-}, 'finished promise is rejected when an animation is cancelled by resetting ' +
-   'the animation property');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  // As before, but this time instead of removing all animations, simply update
-  // the list of animations. At least for Firefox, updating is a different
-  // code path.
-
-  // Set up pending animation
-  div.style.animation = ANIM_PROP_VAL;
-  var animation = div.getAnimations()[0];
-  var previousFinishedPromise = animation.finished;
-
-  // Set up listeners on finished promise
-  var retPromise = animation.finished.then(function() {
-    assert_unreached('finished promise was fulfilled');
-  }).catch(function(err) {
-    assert_equals(err.name, 'AbortError',
-                  'finished promise is rejected with AbortError');
-    assert_not_equals(animation.finished, previousFinishedPromise,
-                      'Finished promise should change after the original is ' +
-                      'rejected');
-  });
-
-  // Now update the animation and flush styles
-  div.style.animation = 'def 100s';
-  getComputedStyle(div).animation;
-
-  return retPromise;
-}, 'finished promise is rejected when an animation is cancelled by changing ' +
-   'the animation property');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = ANIM_PROP_VAL;
-  var animation = div.getAnimations()[0];
-  var previousFinishedPromise = animation.finished;
-  animation.currentTime = ANIM_DURATION;
-  return animation.finished.then(function() {
-    div.style.animationPlayState = 'running';
-    return waitForAnimationFrames(2);
-  }).then(function() {
-    assert_equals(animation.finished, previousFinishedPromise,
-                  'Should not replay when animation-play-state changes to ' +
-                  '"running" on finished animation');
-    assert_equals(animation.currentTime, ANIM_DURATION,
-                  'currentTime should not change when animation-play-state ' +
-                  'changes to "running" on finished animation');
-  });
-}, 'Test finished promise changes when animationPlayState set to running');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animation-id.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes abc { }
-</style>
-<body>
-<script>
-'use strict';
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'abc 100s';
-  var animation = div.getAnimations()[0];
-  assert_equals(animation.id, '', 'id for CSS Animation is initially empty');
-  animation.id = 'anim'
-
-  assert_equals(animation.id, 'anim', 'animation.id reflects the value set');
-}, 'Animation.id for CSS Animations');
-
-done();
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animation-pausing.html
+++ /dev/null
@@ -1,166 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes anim { 
-  0% { margin-left: 0px }
-  100% { margin-left: 10000px }
-}
-</style>
-<body>
-<script>
-'use strict';
-
-function getMarginLeft(cs) {
-  return parseFloat(cs.marginLeft);
-}
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  var cs = getComputedStyle(div);
-  div.style.animation = 'anim 1000s paused';
-  var animation = div.getAnimations()[0];
-  assert_equals(getMarginLeft(cs), 0,
-                'Initial value of margin-left is zero');
-  animation.play();
-
-  return animation.ready.then(waitForNextFrame).then(function() {
-    assert_greater_than(getMarginLeft(cs), 0,
-                        'Playing value of margin-left is greater than zero');
-  });
-}, 'play() overrides animation-play-state');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  var cs = getComputedStyle(div);
-  div.style.animation = 'anim 1000s paused';
-  var animation = div.getAnimations()[0];
-  assert_equals(getMarginLeft(cs), 0,
-                'Initial value of margin-left is zero');
-
-  animation.pause();
-  div.style.animationPlayState = 'running';
-
-  return animation.ready.then(waitForNextFrame).then(function() {
-    assert_equals(cs.animationPlayState, 'running',
-                  'animation-play-state is running');
-    assert_equals(getMarginLeft(cs), 0,
-                  'Paused value of margin-left is zero');
-  });
-}, 'pause() overrides animation-play-state');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  var cs = getComputedStyle(div);
-  div.style.animation = 'anim 1000s paused';
-  var animation = div.getAnimations()[0];
-  assert_equals(getMarginLeft(cs), 0,
-                'Initial value of margin-left is zero');
-  animation.play();
-  var previousAnimVal;
-
-  return animation.ready.then(function() {
-    div.style.animationPlayState = 'running';
-    cs.animationPlayState; // Trigger style resolution
-    return waitForNextFrame();
-  }).then(function() {
-    assert_equals(cs.animationPlayState, 'running',
-                  'animation-play-state is running');
-    div.style.animationPlayState = 'paused';
-    return animation.ready;
-  }).then(function() {
-    assert_equals(cs.animationPlayState, 'paused',
-                  'animation-play-state is paused');
-    previousAnimVal = getMarginLeft(cs);
-    return waitForNextFrame();
-  }).then(function() {
-    assert_equals(getMarginLeft(cs), previousAnimVal,
-                  'Animated value of margin-left does not change when'
-                  + ' paused by style');
-  });
-}, 'play() is overridden by later setting "animation-play-state: paused"');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  var cs = getComputedStyle(div);
-  div.style.animation = 'anim 1000s';
-  var animation = div.getAnimations()[0];
-  assert_equals(getMarginLeft(cs), 0,
-                'Initial value of margin-left is zero');
-
-  // Set the specified style first. If implementations fail to
-  // apply the style changes first, they will ignore the redundant
-  // call to play() and fail to correctly override the pause style.
-  div.style.animationPlayState = 'paused';
-  animation.play();
-  var previousAnimVal = getMarginLeft(cs);
-
-  return animation.ready.then(waitForNextFrame).then(function() {
-    assert_equals(cs.animationPlayState, 'paused',
-                  'animation-play-state is paused');
-    assert_greater_than(getMarginLeft(cs), previousAnimVal,
-                        'Playing value of margin-left is increasing');
-  });
-}, 'play() flushes pending changes to animation-play-state first');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  var cs = getComputedStyle(div);
-  div.style.animation = 'anim 1000s paused';
-  var animation = div.getAnimations()[0];
-  assert_equals(getMarginLeft(cs), 0,
-                'Initial value of margin-left is zero');
-
-  // Unlike the previous test for play(), since calling pause() is sticky,
-  // we'll apply it even if the underlying style also says we're paused.
-  //
-  // We would like to test that implementations flush styles before running
-  // pause() but actually there's no style we can currently set that will
-  // change the behavior of pause(). That may change in the future
-  // (e.g. if we introduce animation-timeline or animation-playback-rate etc.).
-  //
-  // For now this just serves as a sanity check that we do the same thing
-  // even if we set style before calling the API.
-  div.style.animationPlayState = 'running';
-  animation.pause();
-  var previousAnimVal = getMarginLeft(cs);
-
-  return animation.ready.then(waitForNextFrame).then(function() {
-    assert_equals(cs.animationPlayState, 'running',
-                  'animation-play-state is running');
-    assert_equals(getMarginLeft(cs), previousAnimVal,
-                  'Paused value of margin-left does not change');
-  });
-}, 'pause() applies pending changes to animation-play-state first');
-// (Note that we can't actually test for this; see comment above, in test-body.)
-
-promise_test(function(t) {
-  var div = addDiv(t, { style: 'animation: anim 1000s' });
-  var animation = div.getAnimations()[0];
-  var readyPromiseRun = false;
-
-  return animation.ready.then(function() {
-    div.style.animationPlayState = 'paused';
-    assert_true(animation.pending && animation.playState === 'paused',
-                'Animation is pause-pending');
-
-    // Set current time
-    animation.currentTime = 5 * MS_PER_SEC;
-    assert_equals(animation.playState, 'paused',
-                  'Animation is paused immediately after setting currentTime');
-    assert_equals(animation.startTime, null,
-                  'Animation startTime is unresolved immediately after ' +
-                  'setting currentTime');
-    assert_equals(animation.currentTime, 5 * MS_PER_SEC,
-                  'Animation currentTime does not change when forcing a ' +
-                  'pause operation to complete');
-
-    // The ready promise should now be resolved. If it's not then test will
-    // probably time out before anything else happens that causes it to resolve.
-    return animation.ready;
-  });
-}, 'Setting the current time completes a pending pause');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animation-playstate.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes anim { }
-</style>
-<body>
-<script>
-'use strict';
-
-test(function(t) {
-  var div = addDiv(t);
-  var cs = getComputedStyle(div);
-  div.style.animation = 'anim 1000s';
-  var animation = div.getAnimations()[0];
-  assert_equals(animation.playState, 'running');
-}, 'Animation returns correct playState when running');
-
-test(function(t) {
-  var div = addDiv(t);
-  var cs = getComputedStyle(div);
-  div.style.animation = 'anim 1000s paused';
-  var animation = div.getAnimations()[0];
-  assert_equals(animation.playState, 'paused');
-}, 'Animation returns correct playState when paused');
-
-test(function(t) {
-  var div = addDiv(t);
-  var cs = getComputedStyle(div);
-  div.style.animation = 'anim 1000s';
-  var animation = div.getAnimations()[0];
-  animation.pause();
-  assert_equals(animation.playState, 'paused');
-}, 'Animation.playState updates when paused by script');
-
-test(function(t) {
-  var div = addDiv(t);
-  var cs = getComputedStyle(div);
-  div.style.animation = 'anim 1000s paused';
-  var animation = div.getAnimations()[0];
-  div.style.animationPlayState = 'running';
-
-  // This test also checks that calling playState flushes style
-  assert_equals(animation.playState, 'running',
-                'Animation.playState reports running after updating'
-                + ' animation-play-state (got: ' + animation.playState + ')');
-}, 'Animation.playState updates when resumed by setting style');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim 1000s';
-  var animation = div.getAnimations()[0];
-  animation.cancel();
-  assert_equals(animation.playState, 'idle');
-}, 'Animation returns correct playState when cancelled');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animation-ready.html
+++ /dev/null
@@ -1,147 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes abc {
-  to { transform: translate(10px) }
-}
-</style>
-<body>
-<script>
-'use strict';
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'abc 100s paused';
-  var animation = div.getAnimations()[0];
-  var originalReadyPromise = animation.ready;
-
-  return animation.ready.then(function() {
-    div.style.animationPlayState = 'running';
-    assert_not_equals(animation.ready, originalReadyPromise,
-                      'After updating animation-play-state a new ready promise'
-                      + ' object is created');
-  });
-}, 'A new ready promise is created when setting animation-play-state: running');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-
-  // Set up pending animation
-  div.style.animation = 'abc 100s';
-  var animation = div.getAnimations()[0];
-  assert_true(animation.pending, 'Animation is initially pending');
-
-  // Set up listeners on ready promise
-  var retPromise = animation.ready.then(function() {
-    assert_unreached('ready promise is fulfilled');
-  }).catch(function(err) {
-    assert_equals(err.name, 'AbortError',
-                  'ready promise is rejected with AbortError');
-  });
-
-  // Now cancel the animation and flush styles
-  div.style.animation = '';
-  getComputedStyle(div).animation;
-
-  return retPromise;
-}, 'ready promise is rejected when an animation is canceled by resetting'
-   + ' the animation property');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-
-  // As before, but this time instead of removing all animations, simply update
-  // the list of animations. At least for Firefox, updating is a different
-  // code path.
-
-  // Set up pending animation
-  div.style.animation = 'abc 100s';
-  var animation = div.getAnimations()[0];
-  assert_true(animation.pending, 'Animation is initially pending');
-
-  // Set up listeners on ready promise
-  var retPromise = animation.ready.then(function() {
-    assert_unreached('ready promise was fulfilled');
-  }).catch(function(err) {
-    assert_equals(err.name, 'AbortError',
-                  'ready promise is rejected with AbortError');
-  });
-
-  // Now update the animation and flush styles
-  div.style.animation = 'def 100s';
-  getComputedStyle(div).animation;
-
-  return retPromise;
-}, 'ready promise is rejected when an animation is cancelled by updating'
-   + ' the animation property');
-
-promise_test(function(t) {
-  var div = addDiv(t, { style: 'animation: abc 100s' });
-  var animation = div.getAnimations()[0];
-  var originalReadyPromise = animation.ready;
-
-  return animation.ready.then(function() {
-    div.style.animationPlayState = 'paused';
-    assert_not_equals(animation.ready, originalReadyPromise,
-                      'A new Promise object is generated when setting'
-                      + ' animation-play-state: paused');
-  });
-}, 'A new ready promise is created when setting animation-play-state: paused');
-
-promise_test(function(t) {
-  var div = addDiv(t, { style: 'animation: abc 100s' });
-  var animation = div.getAnimations()[0];
-
-  return animation.ready.then(function() {
-    div.style.animationPlayState = 'paused';
-    var firstReadyPromise = animation.ready;
-    animation.pause();
-    assert_equals(animation.ready, firstReadyPromise,
-                  'Ready promise objects are identical after redundant pause');
-  });
-}, 'Pausing twice re-uses the same Promise');
-
-promise_test(function(t) {
-  var div = addDiv(t, { style: 'animation: abc 100s' });
-  var animation = div.getAnimations()[0];
-
-  return animation.ready.then(function() {
-    div.style.animationPlayState = 'paused';
-
-    // Flush style and verify we're pending at the same time
-    assert_true(animation.pending, 'Animation is pending');
-    var pauseReadyPromise = animation.ready;
-
-    // Now play again immediately
-    div.style.animationPlayState = 'running';
-    assert_true(animation.pending, 'Animation is still pending');
-    assert_equals(animation.ready, pauseReadyPromise,
-                  'The pause Promise is re-used when playing while waiting'
-                  + ' to pause');
-
-    return animation.ready;
-  }).then(function() {
-    assert_true(!animation.pending && animation.playState === 'running',
-                'Animation is running after aborting a pause');
-  });
-}, 'If a pause operation is interrupted, the ready promise is reused');
-
-promise_test(function(t) {
-  var div = addDiv(t, { style: 'animation: abc 100s' });
-  var animation = div.getAnimations()[0];
-
-  return animation.ready.then(function() {
-    div.style.animationPlayState = 'paused';
-    return animation.ready;
-  }).then(function(resolvedAnimation) {
-    assert_equals(resolvedAnimation, animation,
-                  'Promise received when ready Promise for a pause operation'
-                  + ' is completed is the animation on which the pause was'
-                  + ' performed');
-  });
-}, 'When a pause is complete the Promise callback gets the correct animation');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animation-reverse.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes anim {
-  to { transform: translate(100px) }
-}
-</style>
-<body>
-<script>
-'use strict';
-
-test(function(t) {
-  var div = addDiv(t, { style: 'animation: anim 100s' });
-  var animation = div.getAnimations()[0];
-  div.style.animation = "";
-  flushComputedStyle(div);
-
-  assert_equals(animation.currentTime, null);
-  animation.reverse();
-
-  assert_equals(animation.currentTime, 100 * MS_PER_SEC,
-    'animation.currentTime should be its effect end');
-}, 'reverse() from idle state starts playing the animation');
-
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animation-starttime.html
+++ /dev/null
@@ -1,383 +0,0 @@
-<!doctype html>
-<html>
-  <head>
-    <meta charset=utf-8>
-    <title>Tests for the effect of setting a CSS animation's
-           Animation.startTime</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';
-
-// 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'];
-
-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 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 ' +
-                'the time when it was started');
-    var startTimeBeforePausing = animation.startTime;
-
-    div.style.animationPlayState = 'paused';
-    // Flush styles just in case querying animation.startTime doesn't flush
-    // styles (which would be a bug in of itself and could mask a further bug
-    // by causing startTime to appear to not change).
-    getComputedStyle(div).animationPlayState;
-
-    assert_equals(animation.startTime, startTimeBeforePausing,
-                  'The startTime does not change when pausing-pending');
-    return animation.ready;
-  }).then(function() {
-    assert_equals(animation.startTime, null,
-                  '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 100s 100s';
-  var animation = div.getAnimations()[0];
-  var currentTime = animation.timeline.currentTime;
-  animation.startTime = currentTime;
-
-  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 100s 100s';
-  var animation = div.getAnimations()[0];
-
-  return animation.ready.then(function() {
-    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 = animation.timeline.currentTime - 100 * MS_PER_SEC;
-    return eventWatcher.wait_for('animationstart');
-  }).then(function() {
-    animation.startTime = animation.timeline.currentTime - 200 * MS_PER_SEC;
-    return eventWatcher.wait_for('animationend');
-  });
-}, '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 100s 100s';
-  var animation = div.getAnimations()[0];
-  animation.startTime = animation.timeline.currentTime - 200 * MS_PER_SEC;
-  var previousTimelineTime = animation.timeline.currentTime;
-
-  return eventWatcher.wait_for(['animationstart',
-                                'animationend']).then(function() {
-    assert_true(document.timeline.currentTime - previousTimelineTime <
-                  100 * MS_PER_SEC,
-                'Sanity check that seeking worked rather than the events ' +
-                'firing after normal playback through the very long ' +
-                'animation duration');
-
-    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.
-    return eventWatcher.wait_for('animationstart');
-  }).then(function() {
-    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() {
-    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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  var retPromise =  eventWatcher.wait_for('animationstart').then(function() {
-    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 = 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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  var retPromise = eventWatcher.wait_for('animationstart').then(function() {
-    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 = 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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  var retPromise = eventWatcher.wait_for(['animationstart',
-                                          'animationend']).then(function() {
-    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 = 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 100s 100s";
-  var animation = div.getAnimations()[0];
-
-  var retPromise = eventWatcher.wait_for(['animationstart',
-                                          'animationend']).then(function() {
-    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 = 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 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');
-
-    animation.pause();
-    return animation.ready;
-  }).then(function() {
-    assert_equals(animation.startTime, null,
-      'Animation.startTime is null after paused');
-    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];
-
-  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();
-    </script>
-  </body>
-</html>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animations-dynamic-changes.html
+++ /dev/null
@@ -1,156 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes anim1 {
-  to { left: 100px }
-}
-@keyframes anim2 { }
-</style>
-<body>
-<script>
-'use strict';
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim1 100s';
-  var originalAnimation = div.getAnimations()[0];
-  var originalStartTime;
-  var originalCurrentTime;
-
-  // Wait a moment so we can confirm the startTime doesn't change (and doesn't
-  // simply reflect the current time).
-  return originalAnimation.ready.then(function() {
-    originalStartTime = originalAnimation.startTime;
-    originalCurrentTime = originalAnimation.currentTime;
-
-    // Wait a moment so we can confirm the startTime doesn't change (and
-    // doesn't simply reflect the current time).
-    return waitForNextFrame();
-  }).then(function() {
-    div.style.animationDuration = '200s';
-    var animation = div.getAnimations()[0];
-    assert_equals(animation, originalAnimation,
-                  'The same Animation is returned after updating'
-                  + ' animation duration');
-    assert_equals(animation.startTime, originalStartTime,
-                  'Animations returned by getAnimations preserve'
-                  + ' their startTime even when they are updated');
-    // Sanity check
-    assert_not_equals(animation.currentTime, originalCurrentTime,
-                      'Animation.currentTime has updated in next'
-                      + ' requestAnimationFrame callback');
-  });
-}, 'Animations preserve their startTime when changed');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim1 100s, anim1 100s';
-
-  // Store original state
-  var animations = div.getAnimations();
-  var animation1 = animations[0];
-  var animation2 = animations[1];
-
-  // Update first in list
-  div.style.animationDuration = '200s, 100s';
-  animations = div.getAnimations();
-  assert_equals(animations[0], animation1,
-                'First Animation is in same position after update');
-  assert_equals(animations[1], animation2,
-                'Second Animation is in same position after update');
-}, 'Updated Animations maintain their order in the list');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim1 200s, anim1 100s';
-
-  // Store original state
-  var animations = div.getAnimations();
-  var animation1 = animations[0];
-  var animation2 = animations[1];
-
-  // Wait before continuing so we can compare start times (otherwise the
-  // new Animation objects and existing Animation objects will all have the same
-  // start time).
-  return waitForAllAnimations(animations).then(waitForFrame).then(function() {
-    // Swap duration of first and second in list and prepend animation at the
-    // same time
-    div.style.animation = 'anim1 100s, anim1 100s, anim1 200s';
-    animations = div.getAnimations();
-    assert_true(animations[0] !== animation1 && animations[0] !== animation2,
-                'New Animation is prepended to start of list');
-    assert_equals(animations[1], animation1,
-                  'First Animation is in second position after update');
-    assert_equals(animations[2], animation2,
-                  'Second Animation is in third position after update');
-    assert_equals(animations[1].startTime, animations[2].startTime,
-                  'Old Animations have the same start time');
-    // TODO: Check that animations[0].startTime === null
-    return animations[0].ready;
-  }).then(function() {
-    assert_greater_than(animations[0].startTime, animations[1].startTime,
-                        'New Animation has later start time');
-  });
-}, 'Only the startTimes of existing animations are preserved');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim1 100s, anim1 100s';
-  var secondAnimation = div.getAnimations()[1];
-
-  // Wait before continuing so we can compare start times
-  return secondAnimation.ready.then(waitForNextFrame).then(function() {
-    // Trim list of animations
-    div.style.animationName = 'anim1';
-    var animations = div.getAnimations();
-    assert_equals(animations.length, 1, 'List of Animations was trimmed');
-    assert_equals(animations[0], secondAnimation,
-                  'Remaining Animation is the second one in the list');
-    assert_equals(typeof(animations[0].startTime), 'number',
-                  'Remaining Animation has resolved startTime');
-    assert_less_than(animations[0].startTime,
-                     animations[0].timeline.currentTime,
-                     'Remaining Animation preserves startTime');
-  });
-}, 'Animations are removed from the start of the list while preserving'
-   + ' the state of existing Animations');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim1 100s';
-  var firstAddedAnimation = div.getAnimations()[0],
-      secondAddedAnimation,
-      animations;
-
-  // Wait and add second Animation
-  return firstAddedAnimation.ready.then(waitForFrame).then(function() {
-    div.style.animation = 'anim1 100s, anim1 100s';
-    secondAddedAnimation = div.getAnimations()[0];
-
-    // Wait again and add another Animation
-    return secondAddedAnimation.ready.then(waitForFrame);
-  }).then(function() {
-    div.style.animation = 'anim1 100s, anim2 100s, anim1 100s';
-    animations = div.getAnimations();
-    assert_not_equals(firstAddedAnimation, secondAddedAnimation,
-                      'New Animations are added to start of the list');
-    assert_equals(animations[0], secondAddedAnimation,
-                  'Second Animation remains in same position after'
-                  + ' interleaving');
-    assert_equals(animations[2], firstAddedAnimation,
-                  'First Animation remains in same position after'
-                  + ' interleaving');
-    return animations[1].ready;
-  }).then(function() {
-    assert_greater_than(animations[1].startTime, animations[0].startTime,
-                        'Interleaved animation starts later than existing ' +
-                        'animations');
-    assert_greater_than(animations[0].startTime, animations[2].startTime,
-                        'Original animations retain their start time');
-  });
-}, 'Animation state is preserved when interleaving animations in list');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_cssanimation-animationname.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes xyz {
-  to { left: 100px }
-}
-</style>
-<body>
-<script>
-'use strict';
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'xyz 100s';
-  assert_equals(div.getAnimations()[0].animationName, 'xyz',
-                'Animation name matches keyframes rule name');
-}, 'Animation name makes keyframe rule');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'x\\yz 100s';
-  assert_equals(div.getAnimations()[0].animationName, 'xyz',
-                'Escaped animation name matches keyframes rule name');
-}, 'Escaped animation name');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'x\\79 z 100s';
-  assert_equals(div.getAnimations()[0].animationName, 'xyz',
-                'Hex-escaped animation name matches keyframes rule'
-                + ' name');
-}, 'Animation name with hex-escape');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_document-get-animations.html
+++ /dev/null
@@ -1,282 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes animLeft {
-  to { left: 100px }
-}
-@keyframes animTop {
-  to { top: 100px }
-}
-@keyframes animBottom {
-  to { bottom: 100px }
-}
-@keyframes animRight {
-  to { right: 100px }
-}
-::before {
-  content: ''
-}
-::after {
-  content: ''
-}
-</style>
-<body>
-<script>
-'use strict';
-
-test(function(t) {
-  assert_equals(document.getAnimations().length, 0,
-    'getAnimations returns an empty sequence for a document'
-    + ' with no animations');
-}, 'getAnimations for non-animated content');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  // Add an animation
-  div.style.animation = 'animLeft 100s';
-  assert_equals(document.getAnimations().length, 1,
-                'getAnimations returns a running CSS Animation');
-
-  // Add another animation
-  div.style.animation = 'animLeft 100s, animTop 100s';
-  assert_equals(document.getAnimations().length, 2,
-                'getAnimations returns two running CSS Animations');
-
-  // Remove both
-  div.style.animation = '';
-  assert_equals(document.getAnimations().length, 0,
-                'getAnimations returns no running CSS Animations');
-}, 'getAnimations for CSS Animations');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'animLeft 100s, animTop 100s, animRight 100s, ' +
-                        'animBottom 100s';
-
-  var animations = document.getAnimations();
-  assert_equals(animations.length, 4,
-                'getAnimations returns all running CSS Animations');
-  assert_equals(animations[0].animationName, 'animLeft',
-                'Order of first animation returned');
-  assert_equals(animations[1].animationName, 'animTop',
-                'Order of second animation returned');
-  assert_equals(animations[2].animationName, 'animRight',
-                'Order of third animation returned');
-  assert_equals(animations[3].animationName, 'animBottom',
-                'Order of fourth animation returned');
-}, 'Order of CSS Animations - within an element');
-
-test(function(t) {
-  var div1 = addDiv(t, { style: 'animation: animLeft 100s' });
-  var div2 = addDiv(t, { style: 'animation: animLeft 100s' });
-  var div3 = addDiv(t, { style: 'animation: animLeft 100s' });
-  var div4 = addDiv(t, { style: 'animation: animLeft 100s' });
-
-  var animations = document.getAnimations();
-  assert_equals(animations.length, 4,
-                'getAnimations returns all running CSS Animations');
-  assert_equals(animations[0].effect.target, div1,
-                'Order of first animation returned');
-  assert_equals(animations[1].effect.target, div2,
-                'Order of second animation returned');
-  assert_equals(animations[2].effect.target, div3,
-                'Order of third animation returned');
-  assert_equals(animations[3].effect.target, div4,
-                'Order of fourth animation returned');
-
-  // Order should be depth-first pre-order so add some depth as follows:
-  //
-  //      <parent>
-  //       /  |
-  //      2   3
-  //    /  \
-  //   1   4
-  //
-  // Which should give: 2, 1, 4, 3
-  div2.appendChild(div1);
-  div2.appendChild(div4);
-  animations = document.getAnimations();
-  assert_equals(animations[0].effect.target, div2,
-                'Order of first animation returned after tree surgery');
-  assert_equals(animations[1].effect.target, div1,
-                'Order of second animation returned after tree surgery');
-  assert_equals(animations[2].effect.target, div4,
-                'Order of third animation returned after tree surgery');
-  assert_equals(animations[3].effect.target, div3,
-                'Order of fourth animation returned after tree surgery');
-
-}, 'Order of CSS Animations - across elements');
-
-test(function(t) {
-  var div1 = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
-  var div2 = addDiv(t, { style: 'animation: animBottom 100s' });
-
-  var expectedResults = [ [ div1, 'animLeft' ],
-                          [ div1, 'animTop' ],
-                          [ div2, 'animBottom' ] ];
-  var animations = document.getAnimations();
-  assert_equals(animations.length, expectedResults.length,
-                'getAnimations returns all running CSS Animations');
-  animations.forEach(function(anim, i) {
-    assert_equals(anim.effect.target, expectedResults[i][0],
-                  'Target of animation in position ' + i);
-    assert_equals(anim.animationName, expectedResults[i][1],
-                  'Name of animation in position ' + i);
-  });
-
-  // Modify tree structure and animation list
-  div2.appendChild(div1);
-  div1.style.animation = 'animLeft 100s, animRight 100s, animTop 100s';
-
-  expectedResults = [ [ div2, 'animBottom' ],
-                      [ div1, 'animLeft' ],
-                      [ div1, 'animRight' ],
-                      [ div1, 'animTop' ] ];
-  animations = document.getAnimations();
-  assert_equals(animations.length, expectedResults.length,
-                'getAnimations returns all running CSS Animations after ' +
-                'making changes');
-  animations.forEach(function(anim, i) {
-    assert_equals(anim.effect.target, expectedResults[i][0],
-                  'Target of animation in position ' + i + ' after changes');
-    assert_equals(anim.animationName, expectedResults[i][1],
-                  'Name of animation in position ' + i + ' after changes');
-  });
-}, 'Order of CSS Animations - across and within elements');
-
-test(function(t) {
-  var div = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
-  var animLeft = document.getAnimations()[0];
-  assert_equals(animLeft.animationName, 'animLeft',
-                'Originally, animLeft animation comes first');
-
-  // Disassociate animLeft from markup and restart
-  div.style.animation = 'animTop 100s';
-  animLeft.play();
-
-  var animations = document.getAnimations();
-  assert_equals(animations.length, 2,
-                'getAnimations returns markup-bound and free animations');
-  assert_equals(animations[0].animationName, 'animTop',
-                'Markup-bound animations come first');
-  assert_equals(animations[1], animLeft, 'Free animations come last');
-}, 'Order of CSS Animations - markup-bound vs free animations');
-
-test(function(t) {
-  var div = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
-  var animLeft = document.getAnimations()[0];
-  var animTop  = document.getAnimations()[1];
-
-  // Disassociate both animations from markup and restart in opposite order
-  div.style.animation = '';
-  animTop.play();
-  animLeft.play();
-
-  var animations = document.getAnimations();
-  assert_equals(animations.length, 2,
-                'getAnimations returns free animations');
-  assert_equals(animations[0], animTop,
-                'Free animations are returned in the order they are started');
-  assert_equals(animations[1], animLeft,
-                'Animations started later are returned later');
-
-  // Restarting an animation should have no effect
-  animTop.cancel();
-  animTop.play();
-  assert_equals(document.getAnimations()[0], animTop,
-                'After restarting, the ordering of free animations' +
-                ' does not change');
-}, 'Order of CSS Animations - free animations');
-
-test(function(t) {
-  // Add an animation first
-  var div = addDiv(t, { style: 'animation: animLeft 100s' });
-  div.style.top = '0px';
-  div.style.transition = 'all 100s';
-  flushComputedStyle(div);
-
-  // *Then* add a transition
-  div.style.top = '100px';
-  flushComputedStyle(div);
-
-  // Although the transition was added later, it should come first in the list
-  var animations = document.getAnimations();
-  assert_equals(animations.length, 2,
-                'Both CSS animations and transitions are returned');
-  assert_class_string(animations[0], 'CSSTransition', 'Transition comes first');
-  assert_class_string(animations[1], 'CSSAnimation', 'Animation comes second');
-}, 'Order of CSS Animations and CSS Transitions');
-
-test(function(t) {
-  var div = addDiv(t, { style: 'animation: animLeft 100s forwards' });
-  div.getAnimations()[0].finish();
-  assert_equals(document.getAnimations().length, 1,
-                'Forwards-filling CSS animations are returned');
-}, 'Finished but filling CSS Animations are returned');
-
-test(function(t) {
-  var div = addDiv(t, { style: 'animation: animLeft 100s' });
-  div.getAnimations()[0].finish();
-  assert_equals(document.getAnimations().length, 0,
-                'Non-filling finished CSS animations are not returned');
-}, 'Finished but not filling CSS Animations are not returned');
-
-test(function(t) {
-  var div = addDiv(t, { style: 'animation: animLeft 100s 100s' });
-  assert_equals(document.getAnimations().length, 1,
-                'Yet-to-start CSS animations are returned');
-}, 'Yet-to-start CSS Animations are returned');
-
-test(function(t) {
-  var div = addDiv(t, { style: 'animation: animLeft 100s' });
-  div.getAnimations()[0].cancel();
-  assert_equals(document.getAnimations().length, 0,
-                'CSS animations cancelled by the API are not returned');
-}, 'CSS Animations cancelled via the API are not returned');
-
-test(function(t) {
-  var div = addDiv(t, { style: 'animation: animLeft 100s' });
-  var anim = div.getAnimations()[0];
-  anim.cancel();
-  anim.play();
-  assert_equals(document.getAnimations().length, 1,
-                'CSS animations cancelled and restarted by the API are ' +
-                'returned');
-}, 'CSS Animations cancelled and restarted via the API are returned');
-
-test(function(t) {
-  addStyle(t, { '#parent::after': 'animation: animLeft 10s;',
-                '#parent::before': 'animation: animRight 10s;' });
-  // create two divs with these arrangement:
-  //       parent
-  //     ::before,
-  //     ::after
-  //        |
-  //       child
-  var parent = addDiv(t, { 'id': 'parent' });
-  var child = addDiv(t);
-  parent.appendChild(child);
-  [parent, child].forEach((div) => {
-    div.setAttribute('style', 'animation: animBottom 10s');
-  });
-
-  var anims = document.getAnimations();
-  assert_equals(anims.length, 4,
-                'CSS animations on both pseudo-elements and elements ' +
-                'are returned');
-  assert_equals(anims[0].effect.target, parent,
-                'The animation targeting the parent element comes first');
-  assert_equals(anims[1].effect.target.type, '::before',
-                'The animation targeting the ::before element comes second');
-  assert_equals(anims[2].effect.target.type, '::after',
-                'The animation targeting the ::after element comes third');
-  assert_equals(anims[3].effect.target, child,
-                'The animation targeting the child element comes last');
-}, 'CSS Animations targetting (pseudo-)elements should have correct order ' +
-   'after sorting');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_effect-target.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes anim { }
-::before {
-  content: ''
-}
-::after {
-  content: ''
-}
-</style>
-<body>
-<script>
-'use strict';
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim 100s';
-  var animation = div.getAnimations()[0];
-  assert_equals(animation.effect.target, div,
-    'Animation.target is the animatable div');
-}, 'Returned CSS animations have the correct effect target');
-
-test(function(t) {
-  addStyle(t, { '.after::after': 'animation: anim 10s, anim 100s;' });
-  var div = addDiv(t, { class: 'after' });
-  var anims = document.getAnimations();
-  assert_equals(anims.length, 2,
-                'Got animations running on ::after pseudo element');
-  assert_equals(anims[0].effect.target, anims[1].effect.target,
-                'Both animations return the same target object');
-}, 'effect.target should return the same CSSPseudoElement object each time');
-
-test(function(t) {
-  addStyle(t, { '.after::after': 'animation: anim 10s;' });
-  var div = addDiv(t, { class: 'after' });
-  var pseudoTarget = document.getAnimations()[0].effect.target;
-  var effect = new KeyframeEffectReadOnly(pseudoTarget,
-                                          { background: ["blue", "red"] },
-                                          3 * MS_PER_SEC);
-  var newAnim = new Animation(effect, document.timeline);
-  newAnim.play();
-  var anims = document.getAnimations();
-  assert_equals(anims.length, 2,
-                'Got animations running on ::after pseudo element');
-  assert_not_equals(anims[0], newAnim,
-                    'The scriped-generated animation appears last');
-  assert_equals(newAnim.effect.target, pseudoTarget,
-                'The effect.target of the scripted-generated animation is ' +
-                'the same as the one from the argument of ' +
-                'KeyframeEffectReadOnly constructor');
-  assert_equals(anims[0].effect.target, newAnim.effect.target,
-                'Both animations return the same target object');
-}, 'effect.target from the script-generated animation should return the same ' +
-   'CSSPseudoElement object as that from the CSS generated animation');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_element-get-animations.html
+++ /dev/null
@@ -1,451 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes anim1 {
-  to { left: 100px }
-}
-@keyframes anim2 {
-  to { top: 100px }
-}
-@keyframes multiPropAnim {
-  to { background: green, opacity: 0.5, left: 100px, top: 100px }
-}
-::before {
-  content: ''
-}
-::after {
-  content: ''
-}
-@keyframes empty { }
-</style>
-<body>
-<script>
-'use strict';
-
-test(function(t) {
-  var div = addDiv(t);
-  assert_equals(div.getAnimations().length, 0,
-    'getAnimations returns an empty sequence for an element'
-    + ' with no animations');
-}, 'getAnimations for non-animated content');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-
-  // FIXME: This test does too many things. It should be split up.
-
-  // Add an animation
-  div.style.animation = 'anim1 100s';
-  var animations = div.getAnimations();
-  assert_equals(animations.length, 1,
-    'getAnimations returns an Animation running CSS Animations');
-  return animations[0].ready.then(function() {
-    var startTime = animations[0].startTime;
-    assert_true(startTime > 0 && startTime <= document.timeline.currentTime,
-      'CSS animation has a sensible start time');
-
-    // Wait a moment then add a second animation.
-    //
-    // We wait for the next frame so that we can test that the start times of
-    // the animations differ.
-    return waitForFrame();
-  }).then(function() {
-    div.style.animation = 'anim1 100s, anim2 100s';
-    animations = div.getAnimations();
-    assert_equals(animations.length, 2,
-      'getAnimations returns one Animation for each value of'
-      + ' animation-name');
-    // Wait until both Animations are ready
-    // (We don't make any assumptions about the order of the Animations since
-    //  that is the purpose of the following test.)
-    return waitForAllAnimations(animations);
-  }).then(function() {
-    assert_true(animations[0].startTime < animations[1].startTime,
-      'Additional Animations for CSS animations start after the original'
-      + ' animation and appear later in the list');
-  });
-}, 'getAnimations for CSS Animations');
-
-test(function(t) {
-  var div = addDiv(t, { style: 'animation: anim1 100s' });
-  assert_class_string(div.getAnimations()[0], 'CSSAnimation',
-                      'Interface of returned animation is CSSAnimation');
-}, 'getAnimations returns CSSAnimation objects for CSS Animations');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  // Add an animation that targets multiple properties
-  div.style.animation = 'multiPropAnim 100s';
-  assert_equals(div.getAnimations().length, 1,
-    'getAnimations returns only one Animation for a CSS Animation'
-    + ' that targets multiple properties');
-}, 'getAnimations for multi-property animations');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-
-  // Add an animation
-  div.style.backgroundColor = 'red';
-  div.style.animation = 'anim1 100s';
-  getComputedStyle(div).backgroundColor;
-
-  // Wait until a frame after the animation starts, then add a transition
-  var animations = div.getAnimations();
-  return animations[0].ready.then(waitForFrame).then(function() {
-    div.style.transition = 'all 100s';
-    div.style.backgroundColor = 'green';
-
-    animations = div.getAnimations();
-    assert_equals(animations.length, 2,
-      'getAnimations returns Animations for both animations and'
-      + ' transitions that run simultaneously');
-    assert_class_string(animations[0], 'CSSTransition',
-                        'First-returned animation is the CSS Transition');
-    assert_class_string(animations[1], 'CSSAnimation',
-                        'Second-returned animation is the CSS Animation');
-  });
-}, 'getAnimations for both CSS Animations and CSS Transitions at once');
-
-async_test(function(t) {
-  var div = addDiv(t);
-
-  // Set up event listener
-  div.addEventListener('animationend', t.step_func(function() {
-    assert_equals(div.getAnimations().length, 0,
-      'getAnimations does not return Animations for finished '
-      + ' (and non-forwards-filling) CSS Animations');
-    t.done();
-  }));
-
-  // Add a very short animation
-  div.style.animation = 'anim1 0.01s';
-}, 'getAnimations for CSS Animations that have finished');
-
-async_test(function(t) {
-  var div = addDiv(t);
-
-  // Set up event listener
-  div.addEventListener('animationend', t.step_func(function() {
-    assert_equals(div.getAnimations().length, 1,
-      'getAnimations returns Animations for CSS Animations that have'
-      + ' finished but are filling forwards');
-    t.done();
-  }));
-
-  // Add a very short animation
-  div.style.animation = 'anim1 0.01s forwards';
-}, 'getAnimations for CSS Animations that have finished but are'
-   + ' forwards filling');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'none 100s';
-
-  var animations = div.getAnimations();
-  assert_equals(animations.length, 0,
-    'getAnimations returns an empty sequence for an element'
-    + ' with animation-name: none');
-
-  div.style.animation = 'none 100s, anim1 100s';
-  animations = div.getAnimations();
-  assert_equals(animations.length, 1,
-    'getAnimations returns Animations only for those CSS Animations whose'
-    + ' animation-name is not none');
-}, 'getAnimations for CSS Animations with animation-name: none');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'missing 100s';
-  var animations = div.getAnimations();
-  assert_equals(animations.length, 0,
-    'getAnimations returns an empty sequence for an element'
-    + ' with animation-name: missing');
-
-  div.style.animation = 'anim1 100s, missing 100s';
-  animations = div.getAnimations();
-  assert_equals(animations.length, 1,
-    'getAnimations returns Animations only for those CSS Animations whose'
-    + ' animation-name is found');
-}, 'getAnimations for CSS Animations with animation-name: missing');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim1 100s, notyet 100s';
-  var animations = div.getAnimations();
-  assert_equals(animations.length, 1,
-    'getAnimations initally only returns Animations for CSS Animations whose'
-    + ' animation-name is found');
-
-  return animations[0].ready.then(waitForFrame).then(function() {
-    var keyframes = '@keyframes notyet { to { left: 100px; } }';
-    document.styleSheets[0].insertRule(keyframes, 0);
-    animations = div.getAnimations();
-    assert_equals(animations.length, 2,
-      'getAnimations includes Animation when @keyframes rule is added'
-      + ' later');
-    return waitForAllAnimations(animations);
-  }).then(function() {
-    assert_true(animations[0].startTime < animations[1].startTime,
-      'Newly added animation has a later start time');
-    document.styleSheets[0].deleteRule(0);
-  });
-}, 'getAnimations for CSS Animations where the @keyframes rule is added'
-   + ' later');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim1 100s, anim1 100s';
-  assert_equals(div.getAnimations().length, 2,
-    'getAnimations returns one Animation for each CSS animation-name'
-    + ' even if the names are duplicated');
-}, 'getAnimations for CSS Animations with duplicated animation-name');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'empty 100s';
-  assert_equals(div.getAnimations().length, 1,
-    'getAnimations returns Animations for CSS animations with an'
-    + ' empty keyframes rule');
-}, 'getAnimations for CSS Animations with empty keyframes rule');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim1 100s 100s';
-  var animations = div.getAnimations();
-  assert_equals(animations.length, 1,
-    'getAnimations returns animations for CSS animations whose'
-    + ' delay makes them start later');
-  return animations[0].ready.then(waitForFrame).then(function() {
-    assert_true(animations[0].startTime <= document.timeline.currentTime,
-      'For CSS Animations in delay phase, the start time of the Animation is'
-      + ' not in the future');
-  });
-}, 'getAnimations for CSS animations in delay phase');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim1 0s 100s';
-  assert_equals(div.getAnimations().length, 1,
-    'getAnimations returns animations for CSS animations whose'
-    + ' duration is zero');
-  div.remove();
-}, 'getAnimations for zero-duration CSS Animations');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim1 100s';
-  var originalAnimation = div.getAnimations()[0];
-
-  // Update pause state (an Animation change)
-  div.style.animationPlayState = 'paused';
-  var pendingAnimation = div.getAnimations()[0];
-  assert_equals(pendingAnimation.playState, 'paused',
-                'animation\'s play state is updated');
-  assert_equals(originalAnimation, pendingAnimation,
-                'getAnimations returns the same objects even when their'
-                + ' play state changes');
-
-  // Update duration (an Animation change)
-  div.style.animationDuration = '200s';
-  var extendedAnimation = div.getAnimations()[0];
-  // FIXME: Check extendedAnimation.effect.timing.duration has changed once the
-  // API is available
-  assert_equals(originalAnimation, extendedAnimation,
-                'getAnimations returns the same objects even when their'
-                + ' duration changes');
-}, 'getAnimations returns objects with the same identity');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim1 100s';
-
-  assert_equals(div.getAnimations().length, 1,
-    'getAnimations returns an animation before cancelling');
-
-  var animation = div.getAnimations()[0];
-
-  animation.cancel();
-  assert_equals(div.getAnimations().length, 0,
-    'getAnimations does not return cancelled animations');
-
-  animation.play();
-  assert_equals(div.getAnimations().length, 1,
-    'getAnimations returns cancelled animations that have been re-started');
-
-}, 'getAnimations for CSS Animations that are cancelled');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim2 100s';
-
-  return div.getAnimations()[0].ready.then(function() {
-    // Prepend to the list and test that even though anim1 was triggered
-    // *after* anim2, it should come first because it appears first
-    // in the animation-name property.
-    div.style.animation = 'anim1 100s, anim2 100s';
-    var anims = div.getAnimations();
-    assert_equals(anims[0].animationName, 'anim1',
-                  'animation order after prepending to list');
-    assert_equals(anims[1].animationName, 'anim2',
-                  'animation order after prepending to list');
-
-    // Normally calling cancel and play would this push anim1 to the top of
-    // the stack but it shouldn't for CSS animations that map an the
-    // animation-name property.
-    var anim1 = anims[0];
-    anim1.cancel();
-    anim1.play();
-    anims = div.getAnimations();
-    assert_equals(anims[0].animationName, 'anim1',
-                  'animation order after cancelling and restarting');
-    assert_equals(anims[1].animationName, 'anim2',
-                  'animation order after cancelling and restarting');
-  });
-}, 'getAnimations for CSS Animations follows animation-name order');
-
-test(function(t) {
-  addStyle(t, { '#target::after': 'animation: anim1 10s;',
-                '#target::before': 'animation: anim1 10s;' });
-  var target = addDiv(t, { 'id': 'target' });
-  target.style.animation = 'anim1 100s';
-
-  var animations = target.getAnimations({ subtree: false });
-  assert_equals(animations.length, 1,
-                'Should find only the element');
-  assert_equals(animations[0].effect.target, target,
-                'Effect target should be the element');
-}, 'Test AnimationFilter{ subtree: false } with single element');
-
-test(function(t) {
-  addStyle(t, { '#target::after': 'animation: anim1 10s;',
-                '#target::before': 'animation: anim1 10s;' });
-  var target = addDiv(t, { 'id': 'target' });
-  target.style.animation = 'anim1 100s';
-
-  var animations = target.getAnimations({ subtree: true });
-  assert_equals(animations.length, 3,
-                'getAnimations({ subtree: true }) ' +
-                'should return animations on pseudo-elements');
-  assert_equals(animations[0].effect.target, target,
-                'The animation targeting the parent element ' +
-                'should be returned first');
-  assert_equals(animations[1].effect.target.type, '::before',
-                'The animation targeting the ::before pseudo-element ' +
-                'should be returned second');
-  assert_equals(animations[2].effect.target.type, '::after',
-                'The animation targeting the ::after pesudo-element ' +
-                'should be returned last');
-}, 'Test AnimationFilter{ subtree: true } with single element');
-
-test(function(t) {
-  addStyle(t, { '#parent::after': 'animation: anim1 10s;',
-                '#parent::before': 'animation: anim1 10s;',
-                '#child::after': 'animation: anim1 10s;',
-                '#child::before': 'animation: anim1 10s;' });
-  var parent = addDiv(t, { 'id': 'parent' });
-  parent.style.animation = 'anim1 100s';
-  var child = addDiv(t, { 'id': 'child' });
-  child.style.animation = 'anim1 100s';
-  parent.appendChild(child);
-
-  var animations = parent.getAnimations({ subtree: false });
-  assert_equals(animations.length, 1,
-                'Should find only the element even if it has a child');
-  assert_equals(animations[0].effect.target, parent,
-                'Effect target shuld be the element');
-}, 'Test AnimationFilter{ subtree: false } with element that has a child');
-
-test(function(t) {
-  addStyle(t, { '#parent::after': 'animation: anim1 10s;',
-                '#parent::before': 'animation: anim1 10s;',
-                '#child::after': 'animation: anim1 10s;',
-                '#child::before': 'animation: anim1 10s;' });
-  var parent = addDiv(t, { 'id': 'parent' });
-  var child = addDiv(t, { 'id': 'child' });
-  parent.style.animation = 'anim1 100s';
-  child.style.animation = 'anim1 100s';
-  parent.appendChild(child);
-
-  var animations = parent.getAnimations({ subtree: true });
-  assert_equals(animations.length, 6,
-                'Should find all elements, pesudo-elements that parent has');
-
-  assert_equals(animations[0].effect.target, parent,
-                'The animation targeting the parent element ' +
-                'should be returned first');
-  assert_equals(animations[1].effect.target.type, '::before',
-                'The animation targeting the ::before pseudo-element ' +
-                'should be returned second');
-  assert_equals(animations[1].effect.target.parentElement, parent,
-                'This ::before element should be child of parent element');
-  assert_equals(animations[2].effect.target.type, '::after',
-                'The animation targeting the ::after pesudo-element ' +
-                'should be returned third');
-  assert_equals(animations[2].effect.target.parentElement, parent,
-                'This ::after element should be child of parent element');
-
-  assert_equals(animations[3].effect.target, child,
-                'The animation targeting the child element ' +
-                'should be returned fourth');
-  assert_equals(animations[4].effect.target.type, '::before',
-                'The animation targeting the ::before pseudo-element ' +
-                'should be returned fifth');
-  assert_equals(animations[4].effect.target.parentElement, child,
-                'This ::before element should be child of child element');
-  assert_equals(animations[5].effect.target.type, '::after',
-                'The animation targeting the ::after pesudo-element ' +
-                'should be returned last');
-  assert_equals(animations[5].effect.target.parentElement, child,
-                'This ::after element should be child of child element');
-}, 'Test AnimationFilter{ subtree: true } with element that has a child');
-
-test(function(t) {
-  var parent = addDiv(t, { 'id': 'parent' });
-  var child1 = addDiv(t, { 'id': 'child1' });
-  var grandchild1 = addDiv(t, { 'id': 'grandchild1' });
-  var grandchild2 = addDiv(t, { 'id': 'grandchild2' });
-  var child2 = addDiv(t, { 'id': 'child2' });
-
-  parent.style.animation = 'anim1 100s';
-  child1.style.animation = 'anim1 100s';
-  grandchild1.style.animation = 'anim1 100s';
-  grandchild2.style.animation = 'anim1 100s';
-  child2.style.animation = 'anim1 100s';
-
-  parent.appendChild(child1);
-  child1.appendChild(grandchild1);
-  child1.appendChild(grandchild2);
-  parent.appendChild(child2);
-
-  var animations = parent.getAnimations({ subtree: true });
-  assert_equals(
-    parent.getAnimations({ subtree: true }).length, 5,
-                         'Should find all descendants of the element');
-
-  assert_equals(animations[0].effect.target, parent,
-                'The animation targeting the parent element ' +
-                'should be returned first');
-
-  assert_equals(animations[1].effect.target, child1,
-                'The animation targeting the child1 element ' +
-                'should be returned second');
-
-  assert_equals(animations[2].effect.target, grandchild1,
-                'The animation targeting the grandchild1 element ' +
-                'should be returned third');
-
-  assert_equals(animations[3].effect.target, grandchild2,
-                'The animation targeting the grandchild2 element ' +
-                'should be returned fourth');
-
-  assert_equals(animations[4].effect.target, child2,
-                'The animation targeting the child2 element ' +
-                'should be returned last');
-
-}, 'Test AnimationFilter{ subtree: true } with element that has many descendant');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_event-dispatch.html
+++ /dev/null
@@ -1,378 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<title>Tests for CSS animation event dispatch</title>
-<link rel="help" href="https://drafts.csswg.org/css-animations-2/#event-dispatch"/>
-<script src="../testcommon.js"></script>
-<style>
-  @keyframes anim {
-    from { margin-left: 0px; }
-    to { margin-left: 100px; }
-  }
-</style>
-<body>
-<script>
-'use strict';
-
-/**
- * Helper class to record the elapsedTime member of each event.
- * The EventWatcher class in testharness.js allows us to wait on
- * multiple events in a certain order but only records the event
- * parameters of the most recent event.
- */
-function AnimationEventHandler(target) {
-  this.target = target;
-  this.target.onanimationstart = evt => {
-   this.animationstart = evt.elapsedTime;
-  };
-  this.target.onanimationiteration = evt => {
-    this.animationiteration = evt.elapsedTime;
-  };
-  this.target.onanimationend = evt => {
-    this.animationend = evt.elapsedTime;
-  };
-  this.target.onanimationcancel = evt => {
-    this.animationcancel = evt.elapsedTime;
-  };
-}
-AnimationEventHandler.prototype.clear = () => {
-  this.animationstart     = undefined;
-  this.animationiteration = undefined;
-  this.animationend       = undefined;
-  this.animationcancel    = undefined;
-}
-
-function setupAnimation(t, animationStyle) {
-  const div = addDiv(t, { style: 'animation: ' + animationStyle });
-  // Note that this AnimationEventHandler should be created before EventWatcher
-  // to capture all events in the handler prior to the EventWatcher since
-  // testharness.js proceeds when the EventWatcher received watching events.
-  const handler = new AnimationEventHandler(div);
-  const watcher = new EventWatcher(t, div, [ 'animationstart',
-                                           'animationiteration',
-                                           'animationend',
-                                           'animationcancel' ]);
-  const animation = div.getAnimations()[0];
-
-  return { animation, watcher, div, handler };
-}
-
-promise_test(t => {
-  // Add 1ms delay to ensure that the delay is not included in the elapsedTime.
-  const { animation, watcher } = setupAnimation(t, 'anim 100s 1ms');
-
-  return watcher.wait_for('animationstart').then(evt => {
-    assert_equals(evt.elapsedTime, 0.0);
-  });
-}, 'Idle -> Active');
-
-promise_test(t => {
-  const { animation, watcher, div, handler } = setupAnimation(t, 'anim 100s');
-
-  // Seek to After phase.
-  animation.finish();
-  return watcher.wait_for([ 'animationstart',
-                            'animationend' ]).then(() => {
-    assert_equals(handler.animationstart, 0.0);
-    assert_equals(handler.animationend, 100);
-  });
-}, 'Idle -> After');
-
-promise_test(t => {
-  const { animation, watcher } =
-    setupAnimation(t, 'anim 100s 100s paused');
-
-  return animation.ready.then(() => {
-    // Seek to Active phase.
-    animation.currentTime = 100 * MS_PER_SEC;
-    return watcher.wait_for('animationstart');
-  }).then(evt => {
-    assert_equals(evt.elapsedTime, 0.0);
-  });
-}, 'Before -> Active');
-
-promise_test(t => {
-  const { animation, watcher, div, handler } =
-    setupAnimation(t, 'anim 100s 100s paused');
-
-  return animation.ready.then(() => {
-    // Seek to After phase.
-    animation.finish();
-    return watcher.wait_for([ 'animationstart', 'animationend' ]);
-  }).then(evt => {
-    assert_equals(handler.animationstart, 0.0);
-    assert_equals(handler.animationend, 100.0);
-  });
-}, 'Before -> After');
-
-promise_test(t => {
-  const { animation, watcher, div } = setupAnimation(t, 'anim 100s paused');
-
-  return watcher.wait_for('animationstart').then(evt => {
-    // Make idle
-    div.style.display = 'none';
-    return watcher.wait_for('animationcancel');
-  }).then(evt => {
-    assert_equals(evt.elapsedTime, 0.0);
-  });
-}, 'Active -> Idle, display: none');
-
-promise_test(t => {
-  const { animation, watcher, div } = setupAnimation(t, 'anim 100s');
-
-  return watcher.wait_for('animationstart').then(evt => {
-    animation.currentTime = 100.0;
-    // Make idle
-    animation.timeline = null;
-    return watcher.wait_for('animationcancel');
-  }).then(evt => {
-    assert_time_equals_literal(evt.elapsedTime, 0.1);
-  });
-}, 'Active -> Idle, setting Animation.timeline = null');
-
-promise_test(t => {
-  // we should NOT pause animation since calling cancel synchronously.
-  const { animation, watcher, div } = setupAnimation(t, 'anim 100s');
-
-  return watcher.wait_for('animationstart').then(evt => {
-    animation.currentTime = 50.0;
-    animation.cancel();
-    return watcher.wait_for('animationcancel');
-  }).then(evt => {
-    assert_time_equals_literal(evt.elapsedTime, 0.05);
-  });
-}, 'Active -> Idle, calling Animation.cancel()');
-
-promise_test(t => {
-  const { animation, watcher } =
-    setupAnimation(t, 'anim 100s 100s paused');
-
-  // Seek to Active phase.
-  animation.currentTime = 100 * MS_PER_SEC;
-  return watcher.wait_for('animationstart').then(() => {
-    // Seek to Before phase.
-    animation.currentTime = 0;
-    return watcher.wait_for('animationend');
-  }).then(evt => {
-    assert_equals(evt.elapsedTime, 0.0);
-  });
-}, 'Active -> Before');
-
-promise_test(t => {
-  const { animation, watcher } = setupAnimation(t, 'anim 100s paused');
-
-  return watcher.wait_for('animationstart').then(evt => {
-    // Seek to After phase.
-    animation.finish();
-    return watcher.wait_for('animationend');
-  }).then(evt => {
-    assert_equals(evt.elapsedTime, 100.0);
-  });
-}, 'Active -> After');
-
-promise_test(t => {
-  const { animation, watcher, div, handler } =
-    setupAnimation(t, 'anim 100s 100s paused');
-
-  // Seek to After phase.
-  animation.finish();
-  return watcher.wait_for([ 'animationstart',
-                            'animationend' ]).then(() => {
-    // Seek to Before phase.
-    animation.currentTime = 0;
-    handler.clear();
-    return watcher.wait_for([ 'animationstart', 'animationend' ]);
-  }).then(() => {
-    assert_equals(handler.animationstart, 100.0);
-    assert_equals(handler.animationend, 0.0);
-  });
-}, 'After -> Before');
-
-promise_test(t => {
-  const { animation, watcher, div } =
-    setupAnimation(t, 'anim 100s 100s paused');
-
-  // Seek to After phase.
-  animation.finish();
-  return watcher.wait_for([ 'animationstart',
-                            'animationend' ]).then(() => {
-    // Seek to Active phase.
-    animation.currentTime = 100 * MS_PER_SEC;
-    return watcher.wait_for('animationstart');
-  }).then(evt => {
-    assert_equals(evt.elapsedTime, 100.0);
-  });
-}, 'After -> Active');
-
-promise_test(t => {
-  const { animation, watcher, div }
-    = setupAnimation(t, 'anim 100s 100s 3 paused');
-
-  return animation.ready.then(() => {
-    // Seek to iteration 0 (no animationiteration event should be dispatched)
-    animation.currentTime = 100 * MS_PER_SEC;
-    return watcher.wait_for('animationstart');
-  }).then(evt => {
-    // Seek to iteration 2
-    animation.currentTime = 300 * MS_PER_SEC;
-    return watcher.wait_for('animationiteration');
-  }).then(evt => {
-    assert_equals(evt.elapsedTime, 200);
-    // Seek to After phase (no animationiteration event should be dispatched)
-    animation.currentTime = 400 * MS_PER_SEC;
-    return watcher.wait_for('animationend');
-  }).then(evt => {
-    assert_equals(evt.elapsedTime, 300);
-  });
-}, 'Active -> Active (forwards)');
-
-promise_test(t => {
-  const { animation, watcher } = setupAnimation(t, 'anim 100s 100s 3');
-
-  // Seek to After phase.
-  animation.finish();
-  return watcher.wait_for([ 'animationstart',
-                            'animationend' ]).then(() => {
-    // Seek to iteration 2 (no animationiteration event should be dispatched)
-    animation.pause();
-    animation.currentTime = 300 * MS_PER_SEC;
-    return watcher.wait_for('animationstart');
-  }).then(() => {
-    // Seek to mid of iteration 0 phase.
-    animation.currentTime = 200 * MS_PER_SEC;
-    return watcher.wait_for('animationiteration');
-  }).then(evt => {
-    assert_equals(evt.elapsedTime, 200.0);
-    // Seek to before phase (no animationiteration event should be dispatched)
-    animation.currentTime = 0;
-    return watcher.wait_for('animationend');
-  });
-}, 'Active -> Active (backwards)');
-
-promise_test(t => {
-  const { animation, watcher, div } =
-    setupAnimation(t, 'anim 100s paused');
-  return watcher.wait_for('animationstart').then(evt => {
-    // Seek to Idle phase.
-    div.style.display = 'none';
-    flushComputedStyle(div);
-
-    return watcher.wait_for('animationcancel');
-  }).then(() => {
-    // Restart this animation.
-    div.style.display = '';
-    return watcher.wait_for('animationstart');
-  });
-}, 'Active -> Idle -> Active: animationstart is fired by restarting animation');
-
-promise_test(t => {
-  const { animation, watcher } =
-    setupAnimation(t, 'anim 100s 100s 2 paused');
-
-  // Make After.
-  animation.finish();
-  return watcher.wait_for([ 'animationstart',
-                            'animationend' ]).then(evt => {
-    animation.playbackRate = -1;
-    return watcher.wait_for('animationstart');
-  }).then(evt => {
-    assert_equals(evt.elapsedTime, 200);
-    // Seek to 1st iteration
-    animation.currentTime = 200 * MS_PER_SEC - 1;
-    return watcher.wait_for('animationiteration');
-  }).then(evt => {
-    assert_equals(evt.elapsedTime, 100);
-    // Seek to before
-    animation.currentTime = 100 * MS_PER_SEC - 1;
-    return watcher.wait_for('animationend');
-  }).then(evt => {
-    assert_equals(evt.elapsedTime, 0);
-    assert_equals(animation.playState, 'running'); // delay
-  });
-}, 'Negative playbackRate sanity test(Before -> Active -> Before)');
-
-promise_test(t => {
-  const { animation, watcher } = setupAnimation(t, 'anim 100s');
-
-  return watcher.wait_for('animationstart').then(evt => {
-    // Make idle
-    animation.cancel();
-    return watcher.wait_for('animationcancel');
-  }).then(evt => {
-    animation.cancel();
-    // Then wait a couple of frames and check that no event was dispatched.
-    return waitForAnimationFrames(2);
-  });
-}, 'Call Animation.cancel after cancelling animation.');
-
-promise_test(t => {
-  const { animation, watcher } = setupAnimation(t, 'anim 100s');
-
-  return watcher.wait_for('animationstart').then(evt => {
-    // Make idle
-    animation.cancel();
-    animation.play();
-    return watcher.wait_for([ 'animationcancel',
-                              'animationstart' ]);
-  });
-}, 'Restart animation after cancelling animation immediately.');
-
-promise_test(t => {
-  const { animation, watcher } = setupAnimation(t, 'anim 100s');
-
-  return watcher.wait_for('animationstart').then(evt => {
-    // Make idle
-    animation.cancel();
-    animation.play();
-    animation.cancel();
-    return watcher.wait_for('animationcancel');
-  }).then(evt => {
-    // Then wait a couple of frames and check that no event was dispatched.
-    return waitForAnimationFrames(2);
-  });
-}, 'Call Animation.cancel after restarting animation immediately.');
-
-promise_test(t => {
-  const { animation, watcher } = setupAnimation(t, 'anim 100s');
-
-  return watcher.wait_for('animationstart').then(evt => {
-    // Make idle
-    animation.timeline = null;
-    return watcher.wait_for('animationcancel');
-  }).then(evt => {
-    animation.timeline = document.timeline;
-    animation.play();
-    return watcher.wait_for('animationstart');
-  });
-}, 'Set timeline and play transition after clearing the timeline.');
-
-promise_test(t => {
-  const { animation, watcher } = setupAnimation(t, 'anim 100s');
-
-  return watcher.wait_for('animationstart').then(evt => {
-    // Make idle
-    animation.cancel();
-    return watcher.wait_for('animationcancel');
-  }).then(evt => {
-    animation.effect = null;
-    // Then wait a couple of frames and check that no event was dispatched.
-    return waitForAnimationFrames(2);
-  });
-}, 'Set null target effect after cancelling the animation.');
-
-promise_test(t => {
-  const { animation, watcher } = setupAnimation(t, 'anim 100s');
-
-  return watcher.wait_for('animationstart').then(evt => {
-    animation.effect = null;
-    return watcher.wait_for('animationend');
-  }).then(evt => {
-    animation.cancel();
-    // Then wait a couple of frames and check that no event was dispatched.
-    return waitForAnimationFrames(2);
-  });
-}, 'Cancel the animation after clearing the target effect.');
-
-done();
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_event-order.html
+++ /dev/null
@@ -1,161 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<title>Tests for CSS animation event order</title>
-<link rel="help" href="https://drafts.csswg.org/css-animations-2/#event-dispatch"/>
-<script src="../testcommon.js"></script>
-<style>
-  @keyframes anim {
-    from { margin-left: 0px; }
-    to { margin-left: 100px; }
-  }
-</style>
-<body>
-<script type='text/javascript'>
-'use strict';
-
-/**
- * Asserts that the set of actual and received events match.
- * @param actualEvents   An array of the received AnimationEvent objects.
- * @param expectedEvents A series of array objects representing the expected
- *        events, each having the form:
- *          [ event type, target element, elapsed time ]
- */
-function checkEvents(actualEvents, ...expectedEvents) {
-  assert_equals(actualEvents.length, expectedEvents.length,
-                `Number of actual events (${actualEvents.length}: \
-${actualEvents.map(event => event.type).join(', ')}) should match expected \
-events (${expectedEvents.map(event => event.type).join(', ')})`);
-
-  actualEvents.forEach((actualEvent, i) => {
-    assert_equals(expectedEvents[i][0], actualEvent.type,
-                  'Event type should match');
-    assert_equals(expectedEvents[i][1], actualEvent.target,
-                  'Event target should match');
-    assert_equals(expectedEvents[i][2], actualEvent.elapsedTime,
-                  'Event\'s elapsed time should match');
-  });
-}
-
-function setupAnimation(t, animationStyle, receiveEvents) {
-  const div = addDiv(t, { style: "animation: " + animationStyle });
-
-  ['start', 'iteration', 'end'].forEach(name => {
-    div['onanimation' + name] = evt => {
-    receiveEvents.push({ type:        evt.type,
-                         target:      evt.target,
-                         elapsedTime: evt.elapsedTime });
-    };
-  });
-
-  const watcher = new EventWatcher(t, div, [ 'animationstart',
-                                             'animationiteration',
-                                             'animationend' ]);
-
-  const animation = div.getAnimations()[0];
-
-  return [animation, watcher, div];
-}
-
-promise_test(t => {
-  let events = [];
-  const [animation1, watcher1, div1] =
-    setupAnimation(t, 'anim 100s 2 paused', events);
-  const [animation2, watcher2, div2] =
-    setupAnimation(t, 'anim 100s 2 paused', events);
-
-  return Promise.all([ watcher1.wait_for('animationstart'),
-                       watcher2.wait_for('animationstart') ]).then(() => {
-    checkEvents(events, ['animationstart', div1, 0],
-                        ['animationstart', div2, 0]);
-
-    events.length = 0;  // Clear received event array
-
-    animation1.currentTime = 100 * MS_PER_SEC;
-    animation2.currentTime = 100 * MS_PER_SEC;
-    return Promise.all([ watcher1.wait_for('animationiteration'),
-                         watcher2.wait_for('animationiteration') ]);
-  }).then(() => {
-    checkEvents(events, ['animationiteration', div1, 100],
-                        ['animationiteration', div2, 100]);
-
-    events.length = 0;  // Clear received event array
-
-    animation1.finish();
-    animation2.finish();
-
-    return Promise.all([ watcher1.wait_for('animationend'),
-                         watcher2.wait_for('animationend') ]);
-  }).then(() => {
-    checkEvents(events, ['animationend', div1, 200],
-                        ['animationend', div2, 200]);
-  });
-}, 'Test same events are ordered by elements.');
-
-promise_test(t => {
-  let events = [];
-  const [animation1, watcher1, div1] =
-    setupAnimation(t, 'anim 200s 400s', events);
-  const [animation2, watcher2, div2] =
-    setupAnimation(t, 'anim 300s 2', events);
-
-  return watcher2.wait_for('animationstart').then(evt => {
-    animation1.currentTime = 400 * MS_PER_SEC;
-    animation2.currentTime = 400 * MS_PER_SEC;
-
-    events.length = 0;  // Clear received event array
-
-    return Promise.all([ watcher1.wait_for('animationstart'),
-                         watcher2.wait_for('animationiteration') ]);
-  }).then(() => {
-    checkEvents(events, ['animationiteration', div2, 300],
-                        ['animationstart',     div1, 0]);
-  });
-}, 'Test start and iteration events are ordered by time.');
-
-promise_test(t => {
-  let events = [];
-  const [animation1, watcher1, div1] =
-    setupAnimation(t, 'anim 150s', events);
-  const [animation2, watcher2, div2] =
-    setupAnimation(t, 'anim 100s 2', events);
-
-  return Promise.all([ watcher1.wait_for('animationstart'),
-                       watcher2.wait_for('animationstart') ]).then(() => {
-    animation1.currentTime = 150 * MS_PER_SEC;
-    animation2.currentTime = 150 * MS_PER_SEC;
-
-    events.length = 0;  // Clear received event array
-
-    return Promise.all([ watcher1.wait_for('animationend'),
-                         watcher2.wait_for('animationiteration') ]);
-  }).then(() => {
-    checkEvents(events, ['animationiteration', div2, 100],
-                        ['animationend',       div1, 150]);
-  });
-}, 'Test iteration and end events are ordered by time.');
-
-promise_test(t => {
-  let events = [];
-  const [animation1, watcher1, div1] =
-    setupAnimation(t, 'anim 100s 100s', events);
-  const [animation2, watcher2, div2] =
-    setupAnimation(t, 'anim 100s 2', events);
-
-  animation1.finish();
-  animation2.finish();
-
-  return Promise.all([ watcher1.wait_for([ 'animationstart',
-                                           'animationend' ]),
-                       watcher2.wait_for([ 'animationstart',
-                                           'animationend' ]) ]).then(() => {
-    checkEvents(events, ['animationstart', div2, 0],
-                        ['animationstart', div1, 0],
-                        ['animationend',   div1, 100],
-                        ['animationend',   div2, 200]);
-  });
-}, 'Test start and end events are sorted correctly when fired simultaneously');
-
-done();
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_keyframeeffect-getkeyframes.html
+++ /dev/null
@@ -1,754 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes anim-empty { }
-
-@keyframes anim-empty-frames {
-  from { }
-  to   { }
-}
-
-@keyframes anim-only-timing {
-  from { animation-timing-function: linear; }
-  to   { }
-}
-
-@keyframes anim-only-non-animatable {
-  from { animation-duration: 3s; }
-  to   { animation-duration: 5s; }
-}
-
-@keyframes anim-simple {
-  from { color: rgb(0, 0, 0); }
-  to   { color: rgb(255, 255, 255); }
-}
-
-@keyframes anim-simple-three {
-  from { color: rgb(0, 0, 0); }
-  50%  { color: rgb(0, 0, 255); }
-  to   { color: rgb(255, 255, 255); }
-}
-
-@keyframes anim-simple-timing {
-  from { color: rgb(0, 0, 0); animation-timing-function: linear; }
-  50%  { color: rgb(0, 0, 255);  animation-timing-function: ease-in-out; }
-  to   { color: rgb(255, 255, 255); animation-timing-function: step-end; }
-}
-
-@keyframes anim-simple-timing-some {
-  from { color: rgb(0, 0, 0); animation-timing-function: linear; }
-  50%  { color: rgb(0, 0, 255); }
-  to   { color: rgb(255, 255, 255); }
-}
-
-@keyframes anim-simple-shorthand {
-  from { margin: 8px; }
-  to   { margin: 16px; }
-}
-
-@keyframes anim-omit-to {
-  from { color: rgb(0, 0, 255); }
-}
-
-@keyframes anim-omit-from {
-  to   { color: rgb(0, 0, 255); }
-}
-
-@keyframes anim-omit-from-to {
-  50%  { color: rgb(0, 0, 255); }
-}
-
-@keyframes anim-partially-omit-to {
-  from { margin-top: 50px;
-         margin-bottom: 100px; }
-  to   { margin-top: 150px !important; /* ignored */
-         margin-bottom: 200px; }
-}
-
-@keyframes anim-different-props {
-  from { color: rgb(0, 0, 0); margin-top: 8px; }
-  25%  { color: rgb(0, 0, 255); }
-  75%  { margin-top: 12px; }
-  to   { color: rgb(255, 255, 255); margin-top: 16px }
-}
-
-@keyframes anim-different-props-and-easing {
-  from { color: rgb(0, 0, 0); margin-top: 8px; animation-timing-function: linear; }
-  25%  { color: rgb(0, 0, 255); animation-timing-function: step-end; }
-  75%  { margin-top: 12px; animation-timing-function: ease-in; }
-  to   { color: rgb(255, 255, 255); margin-top: 16px }
-}
-
-@keyframes anim-merge-offset {
-  from { color: rgb(0, 0, 0); }
-  to   { color: rgb(255, 255, 255); }
-  from { margin-top: 8px; }
-  to   { margin-top: 16px; }
-}
-
-@keyframes anim-merge-offset-and-easing {
-  from { color: rgb(0, 0, 0); animation-timing-function: step-end; }
-  to   { color: rgb(255, 255, 255); }
-  from { margin-top: 8px; animation-timing-function: linear; }
-  to   { margin-top: 16px; }
-  from { font-size: 16px; animation-timing-function: step-end; }
-  to   { font-size: 32px; }
-  from { padding-left: 2px; animation-timing-function: linear; }
-  to   { padding-left: 4px; }
-}
-
-@keyframes anim-no-merge-equiv-easing {
-  from { margin-top: 0px; animation-timing-function: steps(1, end); }
-  from { margin-right: 0px; animation-timing-function: step-end; }
-  from { margin-bottom: 0px; animation-timing-function: steps(1); }
-  50%  { margin-top: 10px; animation-timing-function: step-end; }
-  50%  { margin-right: 10px; animation-timing-function: step-end; }
-  50%  { margin-bottom: 10px; animation-timing-function: step-end; }
-  to   { margin-top: 20px; margin-right: 20px; margin-bottom: 20px; }
-}
-
-@keyframes anim-overriding {
-  from          { padding-top: 50px }
-  50%, from     { padding-top: 30px } /* wins: 0% */
-  75%, 85%, 50% { padding-top: 20px } /* wins: 75%, 50% */
-  100%, 85%     { padding-top: 70px } /* wins: 100% */
-  85.1%         { padding-top: 60px } /* wins: 85.1% */
-  85%           { padding-top: 30px } /* wins: 85% */
-}
-
-@keyframes anim-filter {
-  to { filter: blur(5px) sepia(60%) saturate(30%); }
-}
-
-@keyframes anim-filter-drop-shadow {
-  from { filter: drop-shadow(10px 10px 10px rgb(0, 255, 0)); }
-  to { filter: drop-shadow(50px 30px 10px rgb(255, 0, 0)); }
-}
-
-@keyframes anim-text-shadow {
-  to { text-shadow: none; }
-}
-
-@keyframes anim-background-size {
-  to { background-size: 50%, 6px, contain }
-}
-
-:root {
-  --var-100px: 100px;
-  --end-color: rgb(255, 0, 0);
-}
-@keyframes anim-variables {
-  to { transform: translate(var(--var-100px), 0) }
-}
-@keyframes anim-variables-shorthand {
-  to { margin: var(--var-100px) }
-}
-@keyframes anim-custom-property-in-keyframe {
-  to { --end-color: rgb(0, 255, 0); color: var(--end-color) }
-}
-@keyframes anim-only-custom-property-in-keyframe {
-  from { transform: translate(100px, 0) }
-  to { --not-used: 200px }
-}
-</style>
-<body>
-<script>
-"use strict";
-
-function getKeyframes(e) {
-  return e.getAnimations()[0].effect.getKeyframes();
-}
-
-function assert_frames_equal(a, b, name) {
-  assert_equals(Object.keys(a).sort().toString(),
-                Object.keys(b).sort().toString(),
-                "properties on " + name);
-  for (var p in a) {
-    if (p === 'offset' || p === 'computedOffset') {
-      assert_approx_equals(a[p], b[p], 0.00001,
-                           "value for '" + p + "' on " + name);
-    } else {
-      assert_equals(a[p], b[p], "value for '" + p + "' on " + name);
-    }
-  }
-}
-
-// animation-timing-function values to test with, where the value
-// is exactly the same as its serialization, sorted by the order
-// getKeyframes() will group frames with the same easing function
-// together (by nsTimingFunction::Compare).
-const kTimingFunctionValues = [
-  "ease",
-  "linear",
-  "ease-in",
-  "ease-out",
-  "ease-in-out",
-  "steps(1, start)",
-  "steps(2, start)",
-  "steps(1)",
-  "steps(2)",
-  "cubic-bezier(0, 0, 1, 1)",
-  "cubic-bezier(0, 0.25, 0.75, 1)"
-];
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-empty 100s';
-  assert_equals(getKeyframes(div).length, 0,
-                "number of frames with empty @keyframes");
-
-  div.style.animation = 'anim-empty-frames 100s';
-  assert_equals(getKeyframes(div).length, 0,
-                "number of frames when @keyframes has empty keyframes");
-
-  div.style.animation = 'anim-only-timing 100s';
-  assert_equals(getKeyframes(div).length, 0,
-                "number of frames when @keyframes only has keyframes with " +
-                "animation-timing-function");
-
-  div.style.animation = 'anim-only-non-animatable 100s';
-  assert_equals(getKeyframes(div).length, 0,
-                "number of frames when @keyframes only has frames with " +
-                "non-animatable properties");
-}, 'KeyframeEffectReadOnly.getKeyframes() returns no frames for various kinds'
-   + ' of empty enimations');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-simple 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease",
-      color: "rgb(0, 0, 0)", composite: null },
-    { offset: 1, computedOffset: 1, easing: "ease",
-      color: "rgb(255, 255, 255)", composite: null },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for a simple'
-   + ' animation');
-
-test(function(t) {
-  kTimingFunctionValues.forEach(function(easing) {
-    var div = addDiv(t);
-
-    div.style.animation = 'anim-simple-three 100s ' + easing;
-    var frames = getKeyframes(div);
-
-    assert_equals(frames.length, 3, "number of frames");
-
-    for (var i = 0; i < frames.length; i++) {
-      assert_equals(frames[i].easing, easing,
-                    "value for 'easing' on ComputedKeyframe #" + i);
-    }
-  });
-}, 'KeyframeEffectReadOnly.getKeyframes() returns frames with expected easing'
-   + ' values, when the easing comes from animation-timing-function on the'
-   + ' element');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-simple-timing 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 3, "number of frames");
-  assert_equals(frames[0].easing, "linear",
-                "value of 'easing' on ComputedKeyframe #0");
-  assert_equals(frames[1].easing, "ease-in-out",
-                "value of 'easing' on ComputedKeyframe #1");
-  assert_equals(frames[2].easing, "steps(1)",
-                "value of 'easing' on ComputedKeyframe #2");
-}, 'KeyframeEffectReadOnly.getKeyframes() returns frames with expected easing'
-   + ' values, when the easing is specified on each keyframe');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-simple-timing-some 100s step-start';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 3, "number of frames");
-  assert_equals(frames[0].easing, "linear",
-                "value of 'easing' on ComputedKeyframe #0");
-  assert_equals(frames[1].easing, "steps(1, start)",
-                "value of 'easing' on ComputedKeyframe #1");
-  assert_equals(frames[2].easing, "steps(1, start)",
-                "value of 'easing' on ComputedKeyframe #2");
-}, 'KeyframeEffectReadOnly.getKeyframes() returns frames with expected easing'
-   + ' values, when the easing is specified on some keyframes');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-simple-shorthand 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      marginBottom: "8px", marginLeft: "8px",
-      marginRight: "8px", marginTop: "8px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      marginBottom: "16px", marginLeft: "16px",
-      marginRight: "16px", marginTop: "16px" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for a simple'
-   + ' animation that specifies a single shorthand property');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-omit-to 100s';
-  div.style.color = 'rgb(255, 255, 255)';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      color: "rgb(0, 0, 255)" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      color: "rgb(255, 255, 255)" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
-   'animation with a 0% keyframe and no 100% keyframe');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-omit-from 100s';
-  div.style.color = 'rgb(255, 255, 255)';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      color: "rgb(255, 255, 255)" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      color: "rgb(0, 0, 255)" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
-   'animation with a 100% keyframe and no 0% keyframe');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-omit-from-to 100s';
-  div.style.color = 'rgb(255, 255, 255)';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 3, "number of frames");
-
-  var expected = [
-    { offset: 0,   computedOffset: 0,   easing: "ease", composite: null,
-      color: "rgb(255, 255, 255)" },
-    { offset: 0.5, computedOffset: 0.5, easing: "ease", composite: null,
-      color: "rgb(0, 0, 255)" },
-    { offset: 1,   computedOffset: 1,   easing: "ease", composite: null,
-      color: "rgb(255, 255, 255)" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
-   'animation with no 0% or 100% keyframe but with a 50% keyframe');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-partially-omit-to 100s';
-  div.style.marginTop = '250px';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      marginTop: '50px', marginBottom: '100px' },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      marginTop: '250px', marginBottom: '200px' },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
-   'animation with a partially complete 100% keyframe (because the ' +
-   '!important rule is ignored)');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-different-props 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 4, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      color: "rgb(0, 0, 0)", marginTop: "8px" },
-    { offset: 0.25, computedOffset: 0.25, easing: "ease", composite: null,
-      color: "rgb(0, 0, 255)" },
-    { offset: 0.75, computedOffset: 0.75, easing: "ease", composite: null,
-      marginTop: "12px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      color: "rgb(255, 255, 255)", marginTop: "16px" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
-   'animation with different properties on different keyframes, all ' +
-   'with the same easing function');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-different-props-and-easing 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 4, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "linear", composite: null,
-      color: "rgb(0, 0, 0)", marginTop: "8px" },
-    { offset: 0.25, computedOffset: 0.25, easing: "steps(1)", composite: null,
-      color: "rgb(0, 0, 255)" },
-    { offset: 0.75, computedOffset: 0.75, easing: "ease-in", composite: null,
-      marginTop: "12px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      color: "rgb(255, 255, 255)", marginTop: "16px" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
-   'animation with different properties on different keyframes, with ' +
-   'a different easing function on each');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-merge-offset 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      color: "rgb(0, 0, 0)", marginTop: "8px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      color: "rgb(255, 255, 255)", marginTop: "16px" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
-   'animation with multiple keyframes for the same time, and all with ' +
-   'the same easing function');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-merge-offset-and-easing 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 3, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "steps(1)", composite: null,
-      color: "rgb(0, 0, 0)", fontSize: "16px" },
-    { offset: 0, computedOffset: 0, easing: "linear", composite: null,
-      marginTop: "8px", paddingLeft: "2px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      color: "rgb(255, 255, 255)", fontSize: "32px", marginTop: "16px",
-      paddingLeft: "4px" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
-   'animation with multiple keyframes for the same time and with ' +
-   'different easing functions');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-no-merge-equiv-easing 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 3, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "steps(1)", composite: null,
-      marginTop: "0px", marginRight: "0px", marginBottom: "0px" },
-    { offset: 0.5, computedOffset: 0.5, easing: "steps(1)", composite: null,
-      marginTop: "10px", marginRight: "10px", marginBottom: "10px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      marginTop: "20px", marginRight: "20px", marginBottom: "20px" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
-   'animation with multiple keyframes for the same time and with ' +
-   'different but equivalent easing functions');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-overriding 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 6, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      paddingTop: "30px" },
-    { offset: 0.5, computedOffset: 0.5, easing: "ease", composite: null,
-      paddingTop: "20px" },
-    { offset: 0.75, computedOffset: 0.75, easing: "ease", composite: null,
-      paddingTop: "20px" },
-    { offset: 0.85, computedOffset: 0.85, easing: "ease", composite: null,
-      paddingTop: "30px" },
-    { offset: 0.851, computedOffset: 0.851, easing: "ease", composite: null,
-      paddingTop: "60px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      paddingTop: "70px" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for ' +
-   'overlapping keyframes');
-
-// Gecko-specific test case: We are specifically concerned here that the
-// computed value for filter, "none", is correctly represented.
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-filter 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      filter: "none" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      filter: "blur(5px) sepia(60%) saturate(30%)" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
-   'animations with filter properties and missing keyframes');
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-filter-drop-shadow 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      filter: "drop-shadow(rgb(0, 255, 0) 10px 10px 10px)" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      filter: "drop-shadow(rgb(255, 0, 0) 50px 30px 10px)" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
-   'animation with drop-shadow of filter property');
-
-// Gecko-specific test case: We are specifically concerned here that the
-// computed value for text-shadow and a "none" specified on a keyframe
-// are correctly represented.
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.textShadow = '1px 1px 2px rgb(0, 0, 0), ' +
-                         '0 0 16px rgb(0, 0, 255), ' +
-                         '0 0 3.2px rgb(0, 0, 255)';
-  div.style.animation = 'anim-text-shadow 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      textShadow: "rgb(0, 0, 0) 1px 1px 2px,"
-                  + " rgb(0, 0, 255) 0px 0px 16px,"
-                  + " rgb(0, 0, 255) 0px 0px 3.2px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      textShadow: "none" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
-   'animations with text-shadow properties and missing keyframes');
-
-// Gecko-specific test case: We are specifically concerned here that the
-// initial value for background-size and the specified list are correctly
-// represented.
-
-test(function(t) {
-  var div = addDiv(t);
-
-  div.style.animation = 'anim-background-size 100s';
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      backgroundSize: "auto auto" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      backgroundSize: "50% auto, 6px auto, contain" },
-  ];
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-
-  // Test inheriting a background-size value
-
-  expected[0].backgroundSize = div.style.backgroundSize =
-    "30px auto, 40% auto, auto auto";
-  frames = getKeyframes(div);
-
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i
-                        + " after updating current style");
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
-   'animations with background-size properties and missing keyframes');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim-variables 100s';
-
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      transform: "none" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      transform: "translate(100px, 0px)" },
-  ];
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
-   'animations with CSS variables as keyframe values');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim-variables-shorthand 100s';
-
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      marginBottom: "0px",
-      marginLeft: "0px",
-      marginRight: "0px",
-      marginTop: "0px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      marginBottom: "100px",
-      marginLeft: "100px",
-      marginRight: "100px",
-      marginTop: "100px" },
-  ];
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
-   'animations with CSS variables as keyframe values in a shorthand property');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim-custom-property-in-keyframe 100s';
-
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      color: "rgb(0, 0, 0)" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      color: "rgb(0, 255, 0)" },
-  ];
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
-   'animations with a CSS variable which is overriden by the value in keyframe');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim-only-custom-property-in-keyframe 100s';
-
-  var frames = getKeyframes(div);
-
-  assert_equals(frames.length, 2, "number of frames");
-
-  var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", composite: null,
-      transform: "translate(100px, 0px)" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: null,
-      transform: "none" },
-  ];
-  for (var i = 0; i < frames.length; i++) {
-    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
-  }
-}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
-   'animations with only custom property in a keyframe');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_pseudoElement-get-animations.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-@keyframes anim1 { }
-@keyframes anim2 { }
-.before::before {
-  animation: anim1 10s;
-  content: '';
-}
-.after-with-mix-anims-trans::after {
-  content: '';
-  animation: anim1 10s, anim2 10s;
-  width: 0px;
-  height: 0px;
-  transition: all 100s;
-}
-.after-change::after {
-  width: 100px;
-  height: 100px;
-  content: '';
-}
-</style>
-<body>
-<script>
-'use strict';
-
-test(function(t) {
-  var div = addDiv(t, { class: 'before' });
-  var pseudoTarget = document.getAnimations()[0].effect.target;
-  assert_equals(pseudoTarget.getAnimations().length, 1,
-                'Expected number of animations are returned');
-  assert_equals(pseudoTarget.getAnimations()[0].animationName, 'anim1',
-                'CSS animation name matches');
-}, 'getAnimations returns CSSAnimation objects');
-
-test(function(t) {
-  var div = addDiv(t, { class: 'after-with-mix-anims-trans' });
-  // Trigger transitions
-  flushComputedStyle(div);
-  div.classList.add('after-change');
-
-  // Create additional animation on the pseudo-element from script
-  var pseudoTarget = document.getAnimations()[0].effect.target;
-  var effect = new KeyframeEffectReadOnly(pseudoTarget,
-                                          { background: ["blue", "red"] },
-                                          3 * MS_PER_SEC);
-  var newAnimation = new Animation(effect, document.timeline);
-  newAnimation.id = 'scripted-anim';
-  newAnimation.play();
-
-  // Check order - the script-generated animation should appear later
-  var anims = pseudoTarget.getAnimations();
-  assert_equals(anims.length, 5,
-                'Got expected number of animations/trnasitions running on ' +
-                '::after pseudo element');
-  assert_equals(anims[0].transitionProperty, 'height',
-                '1st animation is the 1st transition sorted by name');
-  assert_equals(anims[1].transitionProperty, 'width',
-                '2nd animation is the 2nd transition sorted by name ');
-  assert_equals(anims[2].animationName, 'anim1',
-                '3rd animation is the 1st animation in animation-name list');
-  assert_equals(anims[3].animationName, 'anim2',
-                '4rd animation is the 2nd animation in animation-name list');
-  assert_equals(anims[4].id, 'scripted-anim',
-                'Animation added by script appears last');
-}, 'getAnimations returns css transitions/animations, and script-generated ' +
-   'animations in the expected order');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_setting-effect.html
+++ /dev/null
@@ -1,130 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src='../testcommon.js'></script>
-<style>
-  @keyframes anim {
-    from {
-      margin-left: 0px;
-    }
-    to {
-      margin-left: 100px;
-    }
-  }
-</style>
-<body>
-<script>
-'use strict';
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim 100s';
-
-  var watcher = new EventWatcher(t, div, [ 'animationend',
-                                           'animationcancel' ]);
-  var animation = div.getAnimations()[0];
-  return animation.ready.then(function() {
-    animation.currentTime = 50 * MS_PER_SEC;
-    animation.effect = null;
-    assert_equals(animation.playState, 'finished');
-    assert_equals(getComputedStyle(div).marginLeft, '0px');
-    return watcher.wait_for('animationend');
-  });
-}, 'Setting a null effect on a running animation fires an animationend event');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim 100s';
-
-  var animation = div.getAnimations()[0];
-  return animation.ready.then(function() {
-    animation.currentTime = 50 * MS_PER_SEC;
-    animation.effect = new KeyframeEffect(div,
-                                          { left: [ '0px' , '100px'] },
-                                          100 * MS_PER_SEC);
-    assert_equals(animation.playState, 'running');
-    assert_equals(getComputedStyle(div).marginLeft, '0px');
-    assert_equals(getComputedStyle(div).left, '50px');
-  });
-}, 'Replacing an animation\'s effect with an effect that targets a different ' +
-   'property should update both properties');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim 100s';
-
-  var animation = div.getAnimations()[0];
-  return animation.ready.then(function() {
-    animation.currentTime = 50 * MS_PER_SEC;
-    animation.effect = new KeyframeEffect(div,
-                                          { left: [ '0px' , '100px'] },
-                                          20 * MS_PER_SEC);
-    assert_equals(animation.playState, 'finished');
-  });
-}, 'Replacing an animation\'s effect with a shorter one that should have ' +
-   'already finished, the animation finishes immediately');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = 'anim 100s';
-
-  var animation = div.getAnimations()[0];
-  assert_true(animation.pending);
-
-  animation.effect = new KeyframeEffect(div,
-                                        { left: [ '0px' , '100px'] },
-                                        100 * MS_PER_SEC);
-  assert_true(animation.pending);
-
-  return animation.ready.then(function() {
-    assert_false(animation.pending);
-  });
-}, 'A play-pending animation\'s effect whose effect is replaced still exits ' +
-   'the pending state');
-
-promise_test(function(t) {
-  var div1 = addDiv(t);
-  var div2 = addDiv(t);
-
-  var watcher1 = new EventWatcher(t, div1, 'animationstart');
-  // Watch |div2| as well to ensure it does *not* get events.
-  var watcher2 = new EventWatcher(t, div2, 'animationstart');
-
-  div1.style.animation = 'anim 100s';
-
-  var animation = div1.getAnimations()[0];
-  animation.effect = new KeyframeEffect(div2,
-                                        { left: [ '0px', '100px' ] },
-                                        100 * MS_PER_SEC);
-
-  return watcher1.wait_for('animationstart').then(function() {
-    assert_equals(animation.effect.target, div2);
-
-    // Then wait a couple of frames and check that no event was dispatched.
-    return waitForAnimationFrames(2);
-  });
-}, 'The event is dispatched at the original element even after setting an ' +
-   'effect with a different target element');
-
-promise_test(function(t) {
-  var div = addDiv(t);
-  var watcher = new EventWatcher(t, div, [ 'animationstart',
-                                           'animationend',
-                                           'animationcancel' ]);
-  div.style.animation = 'anim 100s';
-  var animation = div.getAnimations()[0];
-  animation.finish();
-
-  return watcher.wait_for([ 'animationstart',
-                            'animationend' ]).then(function(evt) {
-    // Set a longer effect
-    animation.effect = new KeyframeEffect(div,
-                                          { left: [ '0px', '100px' ] },
-                                          200 * MS_PER_SEC);
-    return watcher.wait_for('animationstart');
-  });
-}, 'After replacing a finished animation\'s effect with a longer one ' +
-   'it fires an animationstart event');
-
-done();
-</script>
-</body>
--- a/dom/animation/test/css-animations/test_animation-cancel.html
+++ b/dom/animation/test/css-animations/test_animation-cancel.html
@@ -1,15 +1,193 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes translateAnim {
+  to { transform: translate(100px) }
+}
+@keyframes marginLeftAnim {
+  to { margin-left: 100px }
+}
+@keyframes marginLeftAnim100To200 {
+  from { margin-left: 100px }
+  to { margin-left: 200px }
+}
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_animation-cancel.html");
+
+promise_test(function(t) {
+  var div = addDiv(t, { style: 'animation: translateAnim 100s' });
+  var animation = div.getAnimations()[0];
+
+  return animation.ready.then(function() {
+    assert_not_equals(getComputedStyle(div).transform, 'none',
+                      'transform style is animated before cancelling');
+    animation.cancel();
+    assert_equals(getComputedStyle(div).transform, 'none',
+                  'transform style is no longer animated after cancelling');
+  });
+}, 'Animated style is cleared after cancelling a running CSS animation');
+
+promise_test(function(t) {
+  var div = addDiv(t, { style: 'animation: translateAnim 100s forwards' });
+  var animation = div.getAnimations()[0];
+  animation.finish();
+
+  return animation.ready.then(function() {
+    assert_not_equals(getComputedStyle(div).transform, 'none',
+                      'transform style is filling before cancelling');
+    animation.cancel();
+    assert_equals(getComputedStyle(div).transform, 'none',
+                  'fill style is cleared after cancelling');
+  });
+}, 'Animated style is cleared after cancelling a filling CSS animation');
+
+test(function(t) {
+  var div = addDiv(t, { style: 'animation: marginLeftAnim 100s linear' });
+  var animation = div.getAnimations()[0];
+  animation.cancel();
+
+  assert_equals(getComputedStyle(div).marginLeft, '0px',
+                'margin-left style is not animated after cancelling');
+
+  animation.currentTime = 50 * 1000;
+  assert_equals(getComputedStyle(div).marginLeft, '50px',
+                'margin-left style is updated when cancelled animation is'
+                + ' seeked');
+}, 'After canceling an animation, it can still be seeked');
+
+promise_test(function(t) {
+  var div =
+    addDiv(t, { style: 'animation: marginLeftAnim100To200 100s linear' });
+  var animation = div.getAnimations()[0];
+
+  return animation.ready.then(function() {
+    animation.cancel();
+    assert_equals(getComputedStyle(div).marginLeft, '0px',
+                  'margin-left style is not animated after cancelling');
+    animation.play();
+    assert_equals(getComputedStyle(div).marginLeft, '100px',
+                  'margin-left style is animated after re-starting animation');
+    return animation.ready;
+  }).then(function() {
+    assert_equals(animation.playState, 'running',
+                  'Animation succeeds in running after being re-started');
   });
+}, 'After cancelling an animation, it can still be re-used');
+
+test(function(t) {
+  var div =
+    addDiv(t, { style: 'animation: marginLeftAnim100To200 100s linear' });
+  var animation = div.getAnimations()[0];
+  animation.cancel();
+  assert_equals(getComputedStyle(div).marginLeft, '0px',
+                'margin-left style is not animated after cancelling');
+
+  // Trigger a change to some animation properties and check that this
+  // doesn't cause the animation to become live again
+  div.style.animationDuration = '200s';
+  assert_equals(getComputedStyle(div).marginLeft, '0px',
+                'margin-left style is still not animated after updating'
+                + ' animation-duration');
+  assert_equals(animation.playState, 'idle',
+                'Animation is still idle after updating animation-duration');
+}, 'After cancelling an animation, updating animation properties doesn\'t make'
+   + ' it live again');
+
+test(function(t) {
+  var div =
+    addDiv(t, { style: 'animation: marginLeftAnim100To200 100s linear' });
+  var animation = div.getAnimations()[0];
+  animation.cancel();
+  assert_equals(getComputedStyle(div).marginLeft, '0px',
+                'margin-left style is not animated after cancelling');
+
+  // Make some changes to animation-play-state and check that the
+  // animation doesn't become live again. This is because it should be
+  // possible to cancel an animation from script such that all future
+  // changes to style are ignored.
+
+  // Redundant change
+  div.style.animationPlayState = 'running';
+  assert_equals(animation.playState, 'idle',
+                'Animation is still idle after a redundant change to'
+                + ' animation-play-state');
+
+  // Pause
+  div.style.animationPlayState = 'paused';
+  assert_equals(animation.playState, 'idle',
+                'Animation is still idle after setting'
+                + ' animation-play-state: paused');
+
+  // Play
+  div.style.animationPlayState = 'running';
+  assert_equals(animation.playState, 'idle',
+                'Animation is still idle after re-setting'
+                + ' animation-play-state: running');
+
+}, 'After cancelling an animation, updating animation-play-state doesn\'t'
+   + ' make it live again');
+
+promise_test(function(t) {
+  var div = addDiv(t, { style: 'animation: translateAnim 10s both' });
+  div.style.marginLeft = '0px';
+
+  var animation = div.getAnimations()[0];
+
+  return animation.ready.then(function() {
+    assert_equals(animation.playState, 'running');
+
+    div.style.animationName = 'none';
+    flushComputedStyle(div);
+    return waitForFrame();
+  }).then(function() {
+    assert_equals(animation.playState, 'idle');
+    assert_equals(getComputedStyle(div).marginLeft, '0px');
+  });
+}, 'Setting animation-name to \'none\' cancels the animation');
+
+promise_test(function(t) {
+  var div = addDiv(t, { style: 'animation: translateAnim 10s both' });
+  var animation = div.getAnimations()[0];
+
+  return animation.ready.then(function() {
+    assert_equals(animation.playState, 'running');
+
+    div.style.display = 'none';
+    return waitForFrame();
+  }).then(function() {
+    assert_equals(animation.playState, 'idle');
+    assert_equals(getComputedStyle(div).marginLeft, '0px');
+  });
+}, 'Setting display:none on an element cancel its animations');
+
+promise_test(function(t) {
+  var parentDiv = addDiv(t);
+  var childDiv  = document.createElement('div');
+  parentDiv.appendChild(childDiv);
+
+  childDiv.setAttribute('style', 'animation: translateAnim 10s both');
+  flushComputedStyle(childDiv);
+
+  var animation = childDiv.getAnimations()[0];
+
+  return animation.ready.then(function() {
+    assert_equals(animation.playState, 'running');
+
+    parentDiv.style.display = 'none';
+    return waitForFrame();
+  }).then(function() {
+    assert_equals(animation.playState, 'idle');
+    assert_equals(getComputedStyle(childDiv).marginLeft, '0px');
+  });
+}, 'Setting display:none on an ancestor element cancels animations on ' +
+   'descendants');
+
 </script>
+</body>
 </html>
--- a/dom/animation/test/css-animations/test_animation-computed-timing.html
+++ b/dom/animation/test/css-animations/test_animation-computed-timing.html
@@ -1,16 +1,568 @@
 <!doctype html>
-<html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes moveAnimation {
+  from { margin-left: 100px }
+  to { margin-left: 200px }
+}
+</style>
+<body>
 <div id="log"></div>
 <script>
+
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_animation-computed-timing.html");
+
+// --------------------
+// 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.
+
 </script>
-</html>
+</body>
--- a/dom/animation/test/css-animations/test_animation-currenttime.html
+++ b/dom/animation/test/css-animations/test_animation-currenttime.html
@@ -1,15 +1,347 @@
 <!doctype html>
-<meta charset=utf-8>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<div id="log"></div>
-<script>
+<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="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="../testcommon.js"></script>
+  </head>
+  <body>
+    <div id="log"></div>
+    <script type="text/javascript">
+
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_animation-currenttime.html");
+
+// 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'];
+
+test(function(t)
+{
+  var div = addDiv(t, {'class': 'animated-div'});
+  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');
+
+  // Make sure the animation is running before we set the current time.
+  animation.startTime = animation.timeline.currentTime;
+
+  animation.currentTime = 50 * MS_PER_SEC;
+  assert_time_equals_literal(animation.currentTime, 50 * MS_PER_SEC,
+    'Check setting of currentTime actually works');
+}, '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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  return animation.ready.then(function() {
+    // 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;
+    return eventWatcher.wait_for('animationstart');
+  }).then(function() {
+    animation.currentTime = 200 * MS_PER_SEC;
+    return eventWatcher.wait_for('animationend');
+  });
+}, '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 100s 100s";
+  var animation = div.getAnimations()[0];
+  animation.currentTime = 200 * MS_PER_SEC;
+  var previousTimelineTime = animation.timeline.currentTime;
+
+  return eventWatcher.wait_for(['animationstart',
+                                'animationend']).then(function() {
+    assert_true(document.timeline.currentTime - previousTimelineTime <
+                100 * MS_PER_SEC,
+                'Sanity check that seeking worked rather than the events ' +
+                'firing after normal playback through the very long ' +
+                'animation duration');
+
+    animation.currentTime = 150 * MS_PER_SEC;
+    return eventWatcher.wait_for('animationstart');
+  }).then(function() {
+    animation.currentTime = 0;
+    return eventWatcher.wait_for('animationend');
+  });
+}, '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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  var retPromise = eventWatcher.wait_for('animationstart').then(function() {
+    animation.currentTime = 50 * MS_PER_SEC;
+    animation.currentTime = 150 * MS_PER_SEC;
+
+    return waitForAnimationFrames(2);
+  });
+  // get us into the initial state:
+  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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  var retPromise = eventWatcher.wait_for('animationstart').then(function() {
+    animation.currentTime = 250 * MS_PER_SEC;
+    animation.currentTime = 150 * MS_PER_SEC;
+
+    return waitForAnimationFrames(2);
   });
-</script>
+  // get us into the initial state:
+  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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  var retPromise =  eventWatcher.wait_for(['animationstart',
+                                           'animationend']).then(function() {
+    animation.currentTime = 50 * MS_PER_SEC;
+    animation.currentTime = 250 * MS_PER_SEC;
+
+    return waitForAnimationFrames(2);
+  });
+  // get us into the initial state:
+  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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  var retPromise =  eventWatcher.wait_for(['animationstart',
+                                           'animationend']).then(function() {
+    animation.currentTime = 150 * MS_PER_SEC;
+    animation.currentTime = 250 * MS_PER_SEC;
+
+    return waitForAnimationFrames(2);
+  });
+  // get us into the initial state:
+  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 100s"
+  var animation = div.getAnimations()[0];
+
+  animation.pause();
+  animation.currentTime = 150 * MS_PER_SEC;
+
+  return eventWatcher.wait_for(['animationstart',
+                                'animationend']).then(function() {
+    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 100s";
+
+  var animation = div.getAnimations()[0];
+
+  return animation.ready.then(function() {
+    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');
+
+promise_test(function(t) {
+  var div = addDiv(t, {'class': 'animated-div'});
+  div.style.animation = 'anim 100s';
+
+  var animation = div.getAnimations()[0];
+  var pauseTime;
+
+  return animation.ready.then(function() {
+    assert_not_equals(animation.currentTime, null,
+      'Animation.currentTime not null on ready Promise resolve');
+    animation.pause();
+    return animation.ready;
+  }).then(function() {
+    pauseTime = animation.currentTime;
+    return waitForFrame();
+  }).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 100s";
+  var animation = div.getAnimations()[0];
+
+  return animation.ready.then(function() {
+    // just before animation ends:
+    animation.currentTime = 100 * MS_PER_SEC - 1;
+    return waitForAnimationFrames(2);
+  }).then(function() {
+    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 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;
+
+    return waitForAnimationFrames(2);
+  }).then(function() {
+    assert_equals(animation.currentTime, 0,
+      '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];
+
+  return animation.ready.then(function() {
+    animation.finish();
+
+    // Initiate a pause then abort it
+    animation.pause();
+    animation.play();
+
+    // Wait to return to running state
+    return animation.ready;
+  }).then(function() {
+    assert_true(animation.currentTime < 100 * 1000,
+                'After aborting a pause when finished, the currentTime should'
+                + ' jump back towards the start of the animation');
+  });
+}, 'After aborting a pause when finished, the call to play() should rewind'
+   + ' the current time');
+
+    </script>
+  </body>
 </html>
--- a/dom/animation/test/css-animations/test_animation-finish.html
+++ b/dom/animation/test/css-animations/test_animation-finish.html
@@ -1,15 +1,97 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes anim {
+  from { margin-left: 100px; }
+  to { margin-left: 200px; }
+}
+</style>
+<body>
 <div id="log"></div>
 <script>
+
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_animation-finish.html");
-  });
+
+const ANIM_PROP_VAL = 'anim 100s';
+const ANIM_DURATION = 100000; // ms
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = ANIM_PROP_VAL;
+  div.style.animationIterationCount = 'infinite';
+  var animation = div.getAnimations()[0];
+
+  var threw = false;
+  try {
+    animation.finish();
+  } catch (e) {
+    threw = true;
+    assert_equals(e.name, 'InvalidStateError',
+                  'Exception should be an InvalidStateError exception when ' +
+                  'trying to finish an infinite animation');
+  }
+  assert_true(threw,
+              'Expect InvalidStateError exception trying to finish an ' +
+              'infinite animation');
+}, 'Test exceptions when finishing infinite animation');
+
+async_test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = ANIM_PROP_VAL + ' paused';
+  var animation = div.getAnimations()[0];
+
+  animation.ready.then(t.step_func(function() {
+    animation.finish();
+    assert_equals(animation.playState, 'finished',
+                  'The play state of a paused animation should become ' +
+                  '"finished" after finish() is called');
+    assert_times_equal(animation.startTime,
+                       animation.timeline.currentTime - ANIM_DURATION,
+                       'The start time of a paused animation should be set ' +
+                       'after calling finish()');
+    t.done();
+  }));
+}, 'Test finish() while paused');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = ANIM_PROP_VAL + ' paused';
+  var animation = div.getAnimations()[0];
+
+  // Update playbackRate so we can test that the calculated startTime
+  // respects it
+  animation.playbackRate = 2;
+
+  // While animation is still pause-pending call finish()
+  animation.finish();
+
+  assert_equals(animation.playState, 'finished',
+                'The play state of a pause-pending animation should become ' +
+                '"finished" after finish() is called');
+  assert_times_equal(animation.startTime,
+                     animation.timeline.currentTime - ANIM_DURATION / 2,
+                     'The start time of a pause-pending animation should ' +
+                     'be set after calling finish()');
+}, 'Test finish() while pause-pending with positive playbackRate');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = ANIM_PROP_VAL + ' paused';
+  var animation = div.getAnimations()[0];
+
+  animation.playbackRate = -2;
+  animation.finish();
+
+  assert_equals(animation.playState, 'finished',
+                'The play state of a pause-pending animation should become ' +
+                '"finished" after finish() is called');
+  assert_equals(animation.startTime, animation.timeline.currentTime,
+                'The start time of a pause-pending animation should be ' +
+                'set after calling finish()');
+}, 'Test finish() while pause-pending with negative playbackRate');
+
 </script>
-</html>
+</body>
--- a/dom/animation/test/css-animations/test_animation-finished.html
+++ b/dom/animation/test/css-animations/test_animation-finished.html
@@ -1,15 +1,95 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes abc {
+  to { transform: translate(10px) }
+}
+@keyframes def {}
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_animation-finished.html");
+
+const ANIM_PROP_VAL = 'abc 100s';
+const ANIM_DURATION = 100 * MS_PER_SEC;
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  // Set up pending animation
+  div.style.animation = ANIM_PROP_VAL;
+  var animation = div.getAnimations()[0];
+  var previousFinishedPromise = animation.finished;
+  // Set up listeners on finished promise
+  var retPromise = animation.finished.then(function() {
+    assert_unreached('finished promise is fulfilled');
+  }).catch(function(err) {
+    assert_equals(err.name, 'AbortError',
+                  'finished promise is rejected with AbortError');
+    assert_not_equals(animation.finished, previousFinishedPromise,
+                      'Finished promise should change after the original is ' +
+                      'rejected');
   });
+
+  // Now cancel the animation and flush styles
+  div.style.animation = '';
+  getComputedStyle(div).animation;
+
+  return retPromise;
+}, 'finished promise is rejected when an animation is cancelled by resetting ' +
+   'the animation property');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  // As before, but this time instead of removing all animations, simply update
+  // the list of animations. At least for Firefox, updating is a different
+  // code path.
+
+  // Set up pending animation
+  div.style.animation = ANIM_PROP_VAL;
+  var animation = div.getAnimations()[0];
+  var previousFinishedPromise = animation.finished;
+
+  // Set up listeners on finished promise
+  var retPromise = animation.finished.then(function() {
+    assert_unreached('finished promise was fulfilled');
+  }).catch(function(err) {
+    assert_equals(err.name, 'AbortError',
+                  'finished promise is rejected with AbortError');
+    assert_not_equals(animation.finished, previousFinishedPromise,
+                      'Finished promise should change after the original is ' +
+                      'rejected');
+  });
+
+  // Now update the animation and flush styles
+  div.style.animation = 'def 100s';
+  getComputedStyle(div).animation;
+
+  return retPromise;
+}, 'finished promise is rejected when an animation is cancelled by changing ' +
+   'the animation property');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = ANIM_PROP_VAL;
+  var animation = div.getAnimations()[0];
+  var previousFinishedPromise = animation.finished;
+  animation.currentTime = ANIM_DURATION;
+  return animation.finished.then(function() {
+    div.style.animationPlayState = 'running';
+    return waitForAnimationFrames(2);
+  }).then(function() {
+    assert_equals(animation.finished, previousFinishedPromise,
+                  'Should not replay when animation-play-state changes to ' +
+                  '"running" on finished animation');
+    assert_equals(animation.currentTime, ANIM_DURATION,
+                  'currentTime should not change when animation-play-state ' +
+                  'changes to "running" on finished animation');
+  });
+}, 'Test finished promise changes when animationPlayState set to running');
+
 </script>
-</html>
+</body>
--- a/dom/animation/test/css-animations/test_animation-id.html
+++ b/dom/animation/test/css-animations/test_animation-id.html
@@ -1,15 +1,26 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes abc { }
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_animation-id.html");
-  });
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'abc 100s';
+  var animation = div.getAnimations()[0];
+  assert_equals(animation.id, '', 'id for CSS Animation is initially empty');
+  animation.id = 'anim'
+
+  assert_equals(animation.id, 'anim', 'animation.id reflects the value set');
+}, 'Animation.id for CSS Animations');
+
 </script>
+</body>
 </html>
--- a/dom/animation/test/css-animations/test_animation-pausing.html
+++ b/dom/animation/test/css-animations/test_animation-pausing.html
@@ -1,16 +1,168 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes anim {
+  0% { margin-left: 0px }
+  100% { margin-left: 10000px }
+}
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true],
-            ["dom.animations-api.pending-member.enabled", true]]},
-  function() {
-    window.open("file_animation-pausing.html");
+
+function getMarginLeft(cs) {
+  return parseFloat(cs.marginLeft);
+}
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  var cs = getComputedStyle(div);
+  div.style.animation = 'anim 1000s paused';
+  var animation = div.getAnimations()[0];
+  assert_equals(getMarginLeft(cs), 0,
+                'Initial value of margin-left is zero');
+  animation.play();
+
+  return animation.ready.then(waitForNextFrame).then(function() {
+    assert_greater_than(getMarginLeft(cs), 0,
+                        'Playing value of margin-left is greater than zero');
+  });
+}, 'play() overrides animation-play-state');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  var cs = getComputedStyle(div);
+  div.style.animation = 'anim 1000s paused';
+  var animation = div.getAnimations()[0];
+  assert_equals(getMarginLeft(cs), 0,
+                'Initial value of margin-left is zero');
+
+  animation.pause();
+  div.style.animationPlayState = 'running';
+
+  return animation.ready.then(waitForNextFrame).then(function() {
+    assert_equals(cs.animationPlayState, 'running',
+                  'animation-play-state is running');
+    assert_equals(getMarginLeft(cs), 0,
+                  'Paused value of margin-left is zero');
+  });
+}, 'pause() overrides animation-play-state');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  var cs = getComputedStyle(div);
+  div.style.animation = 'anim 1000s paused';
+  var animation = div.getAnimations()[0];
+  assert_equals(getMarginLeft(cs), 0,
+                'Initial value of margin-left is zero');
+  animation.play();
+  var previousAnimVal;
+
+  return animation.ready.then(function() {
+    div.style.animationPlayState = 'running';
+    cs.animationPlayState; // Trigger style resolution
+    return waitForNextFrame();
+  }).then(function() {
+    assert_equals(cs.animationPlayState, 'running',
+                  'animation-play-state is running');
+    div.style.animationPlayState = 'paused';
+    return animation.ready;
+  }).then(function() {
+    assert_equals(cs.animationPlayState, 'paused',
+                  'animation-play-state is paused');
+    previousAnimVal = getMarginLeft(cs);
+    return waitForNextFrame();
+  }).then(function() {
+    assert_equals(getMarginLeft(cs), previousAnimVal,
+                  'Animated value of margin-left does not change when'
+                  + ' paused by style');
   });
+}, 'play() is overridden by later setting "animation-play-state: paused"');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  var cs = getComputedStyle(div);
+  div.style.animation = 'anim 1000s';
+  var animation = div.getAnimations()[0];
+  assert_equals(getMarginLeft(cs), 0,
+                'Initial value of margin-left is zero');
+
+  // Set the specified style first. If implementations fail to
+  // apply the style changes first, they will ignore the redundant
+  // call to play() and fail to correctly override the pause style.
+  div.style.animationPlayState = 'paused';
+  animation.play();
+  var previousAnimVal = getMarginLeft(cs);
+
+  return animation.ready.then(waitForNextFrame).then(function() {
+    assert_equals(cs.animationPlayState, 'paused',
+                  'animation-play-state is paused');
+    assert_greater_than(getMarginLeft(cs), previousAnimVal,
+                        'Playing value of margin-left is increasing');
+  });
+}, 'play() flushes pending changes to animation-play-state first');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  var cs = getComputedStyle(div);
+  div.style.animation = 'anim 1000s paused';
+  var animation = div.getAnimations()[0];
+  assert_equals(getMarginLeft(cs), 0,
+                'Initial value of margin-left is zero');
+
+  // Unlike the previous test for play(), since calling pause() is sticky,
+  // we'll apply it even if the underlying style also says we're paused.
+  //
+  // We would like to test that implementations flush styles before running
+  // pause() but actually there's no style we can currently set that will
+  // change the behavior of pause(). That may change in the future
+  // (e.g. if we introduce animation-timeline or animation-playback-rate etc.).
+  //
+  // For now this just serves as a sanity check that we do the same thing
+  // even if we set style before calling the API.
+  div.style.animationPlayState = 'running';
+  animation.pause();
+  var previousAnimVal = getMarginLeft(cs);
+
+  return animation.ready.then(waitForNextFrame).then(function() {
+    assert_equals(cs.animationPlayState, 'running',
+                  'animation-play-state is running');
+    assert_equals(getMarginLeft(cs), previousAnimVal,
+                  'Paused value of margin-left does not change');
+  });
+}, 'pause() applies pending changes to animation-play-state first');
+// (Note that we can't actually test for this; see comment above, in test-body.)
+
+promise_test(function(t) {
+  var div = addDiv(t, { style: 'animation: anim 1000s' });
+  var animation = div.getAnimations()[0];
+  var readyPromiseRun = false;
+
+  return animation.ready.then(function() {
+    div.style.animationPlayState = 'paused';
+    assert_true(animation.pending && animation.playState === 'paused',
+                'Animation is pause-pending');
+
+    // Set current time
+    animation.currentTime = 5 * MS_PER_SEC;
+    assert_equals(animation.playState, 'paused',
+                  'Animation is paused immediately after setting currentTime');
+    assert_equals(animation.startTime, null,
+                  'Animation startTime is unresolved immediately after ' +
+                  'setting currentTime');
+    assert_equals(animation.currentTime, 5 * MS_PER_SEC,
+                  'Animation currentTime does not change when forcing a ' +
+                  'pause operation to complete');
+
+    // The ready promise should now be resolved. If it's not then test will
+    // probably time out before anything else happens that causes it to resolve.
+    return animation.ready;
+  });
+}, 'Setting the current time completes a pending pause');
+
 </script>
-</html>
+</body>
--- a/dom/animation/test/css-animations/test_animation-playstate.html
+++ b/dom/animation/test/css-animations/test_animation-playstate.html
@@ -1,16 +1,61 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes anim { }
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true],
-            ["dom.animations-api.pending-member.enabled", true]]},
-  function() {
-    window.open("file_animation-playstate.html");
-  });
+
+test(function(t) {
+  var div = addDiv(t);
+  var cs = getComputedStyle(div);
+  div.style.animation = 'anim 1000s';
+  var animation = div.getAnimations()[0];
+  assert_equals(animation.playState, 'running');
+}, 'Animation returns correct playState when running');
+
+test(function(t) {
+  var div = addDiv(t);
+  var cs = getComputedStyle(div);
+  div.style.animation = 'anim 1000s paused';
+  var animation = div.getAnimations()[0];
+  assert_equals(animation.playState, 'paused');
+}, 'Animation returns correct playState when paused');
+
+test(function(t) {
+  var div = addDiv(t);
+  var cs = getComputedStyle(div);
+  div.style.animation = 'anim 1000s';
+  var animation = div.getAnimations()[0];
+  animation.pause();
+  assert_equals(animation.playState, 'paused');
+}, 'Animation.playState updates when paused by script');
+
+test(function(t) {
+  var div = addDiv(t);
+  var cs = getComputedStyle(div);
+  div.style.animation = 'anim 1000s paused';
+  var animation = div.getAnimations()[0];
+  div.style.animationPlayState = 'running';
+
+  // This test also checks that calling playState flushes style
+  assert_equals(animation.playState, 'running',
+                'Animation.playState reports running after updating'
+                + ' animation-play-state (got: ' + animation.playState + ')');
+}, 'Animation.playState updates when resumed by setting style');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim 1000s';
+  var animation = div.getAnimations()[0];
+  animation.cancel();
+  assert_equals(animation.playState, 'idle');
+}, 'Animation returns correct playState when cancelled');
+
 </script>
-</html>
+</body>
--- a/dom/animation/test/css-animations/test_animation-ready.html
+++ b/dom/animation/test/css-animations/test_animation-ready.html
@@ -1,16 +1,149 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes abc {
+  to { transform: translate(10px) }
+}
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true],
-            ["dom.animations-api.pending-member.enabled", true]]},
-  function() {
-    window.open("file_animation-ready.html");
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'abc 100s paused';
+  var animation = div.getAnimations()[0];
+  var originalReadyPromise = animation.ready;
+
+  return animation.ready.then(function() {
+    div.style.animationPlayState = 'running';
+    assert_not_equals(animation.ready, originalReadyPromise,
+                      'After updating animation-play-state a new ready promise'
+                      + ' object is created');
+  });
+}, 'A new ready promise is created when setting animation-play-state: running');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+
+  // Set up pending animation
+  div.style.animation = 'abc 100s';
+  var animation = div.getAnimations()[0];
+  assert_true(animation.pending, 'Animation is initially pending');
+
+  // Set up listeners on ready promise
+  var retPromise = animation.ready.then(function() {
+    assert_unreached('ready promise is fulfilled');
+  }).catch(function(err) {
+    assert_equals(err.name, 'AbortError',
+                  'ready promise is rejected with AbortError');
+  });
+
+  // Now cancel the animation and flush styles
+  div.style.animation = '';
+  getComputedStyle(div).animation;
+
+  return retPromise;
+}, 'ready promise is rejected when an animation is canceled by resetting'
+   + ' the animation property');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+
+  // As before, but this time instead of removing all animations, simply update
+  // the list of animations. At least for Firefox, updating is a different
+  // code path.
+
+  // Set up pending animation
+  div.style.animation = 'abc 100s';
+  var animation = div.getAnimations()[0];
+  assert_true(animation.pending, 'Animation is initially pending');
+
+  // Set up listeners on ready promise
+  var retPromise = animation.ready.then(function() {
+    assert_unreached('ready promise was fulfilled');
+  }).catch(function(err) {
+    assert_equals(err.name, 'AbortError',
+                  'ready promise is rejected with AbortError');
   });
+
+  // Now update the animation and flush styles
+  div.style.animation = 'def 100s';
+  getComputedStyle(div).animation;
+
+  return retPromise;
+}, 'ready promise is rejected when an animation is cancelled by updating'
+   + ' the animation property');
+
+promise_test(function(t) {
+  var div = addDiv(t, { style: 'animation: abc 100s' });
+  var animation = div.getAnimations()[0];
+  var originalReadyPromise = animation.ready;
+
+  return animation.ready.then(function() {
+    div.style.animationPlayState = 'paused';
+    assert_not_equals(animation.ready, originalReadyPromise,
+                      'A new Promise object is generated when setting'
+                      + ' animation-play-state: paused');
+  });
+}, 'A new ready promise is created when setting animation-play-state: paused');
+
+promise_test(function(t) {
+  var div = addDiv(t, { style: 'animation: abc 100s' });
+  var animation = div.getAnimations()[0];
+
+  return animation.ready.then(function() {
+    div.style.animationPlayState = 'paused';
+    var firstReadyPromise = animation.ready;
+    animation.pause();
+    assert_equals(animation.ready, firstReadyPromise,
+                  'Ready promise objects are identical after redundant pause');
+  });
+}, 'Pausing twice re-uses the same Promise');
+
+promise_test(function(t) {
+  var div = addDiv(t, { style: 'animation: abc 100s' });
+  var animation = div.getAnimations()[0];
+
+  return animation.ready.then(function() {
+    div.style.animationPlayState = 'paused';
+
+    // Flush style and verify we're pending at the same time
+    assert_true(animation.pending, 'Animation is pending');
+    var pauseReadyPromise = animation.ready;
+
+    // Now play again immediately
+    div.style.animationPlayState = 'running';
+    assert_true(animation.pending, 'Animation is still pending');
+    assert_equals(animation.ready, pauseReadyPromise,
+                  'The pause Promise is re-used when playing while waiting'
+                  + ' to pause');
+
+    return animation.ready;
+  }).then(function() {
+    assert_true(!animation.pending && animation.playState === 'running',
+                'Animation is running after aborting a pause');
+  });
+}, 'If a pause operation is interrupted, the ready promise is reused');
+
+promise_test(function(t) {
+  var div = addDiv(t, { style: 'animation: abc 100s' });
+  var animation = div.getAnimations()[0];
+
+  return animation.ready.then(function() {
+    div.style.animationPlayState = 'paused';
+    return animation.ready;
+  }).then(function(resolvedAnimation) {
+    assert_equals(resolvedAnimation, animation,
+                  'Promise received when ready Promise for a pause operation'
+                  + ' is completed is the animation on which the pause was'
+                  + ' performed');
+  });
+}, 'When a pause is complete the Promise callback gets the correct animation');
+
 </script>
-</html>
+</body>
--- a/dom/animation/test/css-animations/test_animation-reverse.html
+++ b/dom/animation/test/css-animations/test_animation-reverse.html
@@ -1,15 +1,30 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes anim {
+  to { transform: translate(100px) }
+}
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_animation-reverse.html");
-  });
+
+test(function(t) {
+  var div = addDiv(t, { style: 'animation: anim 100s' });
+  var animation = div.getAnimations()[0];
+  div.style.animation = "";
+  flushComputedStyle(div);
+
+  assert_equals(animation.currentTime, null);
+  animation.reverse();
+
+  assert_equals(animation.currentTime, 100 * MS_PER_SEC,
+    'animation.currentTime should be its effect end');
+}, 'reverse() from idle state starts playing the animation');
+
 </script>
-</html>
+</body>
--- a/dom/animation/test/css-animations/test_animation-starttime.html
+++ b/dom/animation/test/css-animations/test_animation-starttime.html
@@ -1,15 +1,385 @@
 <!doctype html>
-<meta charset=utf-8>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<div id="log"></div>
-<script>
+<html>
+  <head>
+    <meta charset=utf-8>
+    <title>Tests for the effect of setting a CSS animation's
+           Animation.startTime</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="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="../testcommon.js"></script>
+  </head>
+  <body>
+    <div id="log"></div>
+    <script type="text/javascript">
+
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]] },
-  function() {
-    window.open("file_animation-starttime.html");
+
+// 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'];
+
+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 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 ' +
+                'the time when it was started');
+    var startTimeBeforePausing = animation.startTime;
+
+    div.style.animationPlayState = 'paused';
+    // Flush styles just in case querying animation.startTime doesn't flush
+    // styles (which would be a bug in of itself and could mask a further bug
+    // by causing startTime to appear to not change).
+    getComputedStyle(div).animationPlayState;
+
+    assert_equals(animation.startTime, startTimeBeforePausing,
+                  'The startTime does not change when pausing-pending');
+    return animation.ready;
+  }).then(function() {
+    assert_equals(animation.startTime, null,
+                  '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 100s 100s';
+  var animation = div.getAnimations()[0];
+  var currentTime = animation.timeline.currentTime;
+  animation.startTime = currentTime;
+
+  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 100s 100s';
+  var animation = div.getAnimations()[0];
+
+  return animation.ready.then(function() {
+    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 = animation.timeline.currentTime - 100 * MS_PER_SEC;
+    return eventWatcher.wait_for('animationstart');
+  }).then(function() {
+    animation.startTime = animation.timeline.currentTime - 200 * MS_PER_SEC;
+    return eventWatcher.wait_for('animationend');
   });
-</script>
+}, '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 100s 100s';
+  var animation = div.getAnimations()[0];
+  animation.startTime = animation.timeline.currentTime - 200 * MS_PER_SEC;
+  var previousTimelineTime = animation.timeline.currentTime;
+
+  return eventWatcher.wait_for(['animationstart',
+                                'animationend']).then(function() {
+    assert_true(document.timeline.currentTime - previousTimelineTime <
+                  100 * MS_PER_SEC,
+                'Sanity check that seeking worked rather than the events ' +
+                'firing after normal playback through the very long ' +
+                'animation duration');
+
+    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.
+    return eventWatcher.wait_for('animationstart');
+  }).then(function() {
+    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() {
+    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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  var retPromise =  eventWatcher.wait_for('animationstart').then(function() {
+    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 = 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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  var retPromise = eventWatcher.wait_for('animationstart').then(function() {
+    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 = 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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  var retPromise = eventWatcher.wait_for(['animationstart',
+                                          'animationend']).then(function() {
+    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 = 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 100s 100s";
+  var animation = div.getAnimations()[0];
+
+  var retPromise = eventWatcher.wait_for(['animationstart',
+                                          'animationend']).then(function() {
+    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 = 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 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');
+
+    animation.pause();
+    return animation.ready;
+  }).then(function() {
+    assert_equals(animation.startTime, null,
+      'Animation.startTime is null after paused');
+    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];
+
+  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');
+
+    </script>
+  </body>
 </html>
--- a/dom/animation/test/css-animations/test_animations-dynamic-changes.html
+++ b/dom/animation/test/css-animations/test_animations-dynamic-changes.html
@@ -1,15 +1,158 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes anim1 {
+  to { left: 100px }
+}
+@keyframes anim2 { }
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_animations-dynamic-changes.html");
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim1 100s';
+  var originalAnimation = div.getAnimations()[0];
+  var originalStartTime;
+  var originalCurrentTime;
+
+  // Wait a moment so we can confirm the startTime doesn't change (and doesn't
+  // simply reflect the current time).
+  return originalAnimation.ready.then(function() {
+    originalStartTime = originalAnimation.startTime;
+    originalCurrentTime = originalAnimation.currentTime;
+
+    // Wait a moment so we can confirm the startTime doesn't change (and
+    // doesn't simply reflect the current time).
+    return waitForNextFrame();
+  }).then(function() {
+    div.style.animationDuration = '200s';
+    var animation = div.getAnimations()[0];
+    assert_equals(animation, originalAnimation,
+                  'The same Animation is returned after updating'
+                  + ' animation duration');
+    assert_equals(animation.startTime, originalStartTime,
+                  'Animations returned by getAnimations preserve'
+                  + ' their startTime even when they are updated');
+    // Sanity check
+    assert_not_equals(animation.currentTime, originalCurrentTime,
+                      'Animation.currentTime has updated in next'
+                      + ' requestAnimationFrame callback');
   });
+}, 'Animations preserve their startTime when changed');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim1 100s, anim1 100s';
+
+  // Store original state
+  var animations = div.getAnimations();
+  var animation1 = animations[0];
+  var animation2 = animations[1];
+
+  // Update first in list
+  div.style.animationDuration = '200s, 100s';
+  animations = div.getAnimations();
+  assert_equals(animations[0], animation1,
+                'First Animation is in same position after update');
+  assert_equals(animations[1], animation2,
+                'Second Animation is in same position after update');
+}, 'Updated Animations maintain their order in the list');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim1 200s, anim1 100s';
+
+  // Store original state
+  var animations = div.getAnimations();
+  var animation1 = animations[0];
+  var animation2 = animations[1];
+
+  // Wait before continuing so we can compare start times (otherwise the
+  // new Animation objects and existing Animation objects will all have the same
+  // start time).
+  return waitForAllAnimations(animations).then(waitForFrame).then(function() {
+    // Swap duration of first and second in list and prepend animation at the
+    // same time
+    div.style.animation = 'anim1 100s, anim1 100s, anim1 200s';
+    animations = div.getAnimations();
+    assert_true(animations[0] !== animation1 && animations[0] !== animation2,
+                'New Animation is prepended to start of list');
+    assert_equals(animations[1], animation1,
+                  'First Animation is in second position after update');
+    assert_equals(animations[2], animation2,
+                  'Second Animation is in third position after update');
+    assert_equals(animations[1].startTime, animations[2].startTime,
+                  'Old Animations have the same start time');
+    // TODO: Check that animations[0].startTime === null
+    return animations[0].ready;
+  }).then(function() {
+    assert_greater_than(animations[0].startTime, animations[1].startTime,
+                        'New Animation has later start time');
+  });
+}, 'Only the startTimes of existing animations are preserved');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim1 100s, anim1 100s';
+  var secondAnimation = div.getAnimations()[1];
+
+  // Wait before continuing so we can compare start times
+  return secondAnimation.ready.then(waitForNextFrame).then(function() {
+    // Trim list of animations
+    div.style.animationName = 'anim1';
+    var animations = div.getAnimations();
+    assert_equals(animations.length, 1, 'List of Animations was trimmed');
+    assert_equals(animations[0], secondAnimation,
+                  'Remaining Animation is the second one in the list');
+    assert_equals(typeof(animations[0].startTime), 'number',
+                  'Remaining Animation has resolved startTime');
+    assert_less_than(animations[0].startTime,
+                     animations[0].timeline.currentTime,
+                     'Remaining Animation preserves startTime');
+  });
+}, 'Animations are removed from the start of the list while preserving'
+   + ' the state of existing Animations');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim1 100s';
+  var firstAddedAnimation = div.getAnimations()[0],
+      secondAddedAnimation,
+      animations;
+
+  // Wait and add second Animation
+  return firstAddedAnimation.ready.then(waitForFrame).then(function() {
+    div.style.animation = 'anim1 100s, anim1 100s';
+    secondAddedAnimation = div.getAnimations()[0];
+
+    // Wait again and add another Animation
+    return secondAddedAnimation.ready.then(waitForFrame);
+  }).then(function() {
+    div.style.animation = 'anim1 100s, anim2 100s, anim1 100s';
+    animations = div.getAnimations();
+    assert_not_equals(firstAddedAnimation, secondAddedAnimation,
+                      'New Animations are added to start of the list');
+    assert_equals(animations[0], secondAddedAnimation,
+                  'Second Animation remains in same position after'
+                  + ' interleaving');
+    assert_equals(animations[2], firstAddedAnimation,
+                  'First Animation remains in same position after'
+                  + ' interleaving');
+    return animations[1].ready;
+  }).then(function() {
+    assert_greater_than(animations[1].startTime, animations[0].startTime,
+                        'Interleaved animation starts later than existing ' +
+                        'animations');
+    assert_greater_than(animations[0].startTime, animations[2].startTime,
+                        'Original animations retain their start time');
+  });
+}, 'Animation state is preserved when interleaving animations in list');
+
 </script>
-</html>
+</body>
--- a/dom/animation/test/css-animations/test_cssanimation-animationname.html
+++ b/dom/animation/test/css-animations/test_cssanimation-animationname.html
@@ -1,15 +1,39 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes xyz {
+  to { left: 100px }
+}
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_cssanimation-animationname.html");
-  });
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'xyz 100s';
+  assert_equals(div.getAnimations()[0].animationName, 'xyz',
+                'Animation name matches keyframes rule name');
+}, 'Animation name makes keyframe rule');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'x\\yz 100s';
+  assert_equals(div.getAnimations()[0].animationName, 'xyz',
+                'Escaped animation name matches keyframes rule name');
+}, 'Escaped animation name');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'x\\79 z 100s';
+  assert_equals(div.getAnimations()[0].animationName, 'xyz',
+                'Hex-escaped animation name matches keyframes rule'
+                + ' name');
+}, 'Animation name with hex-escape');
+
 </script>
-</html>
+</body>
--- a/dom/animation/test/css-animations/test_document-get-animations.html
+++ b/dom/animation/test/css-animations/test_document-get-animations.html
@@ -1,15 +1,284 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes animLeft {
+  to { left: 100px }
+}
+@keyframes animTop {
+  to { top: 100px }
+}
+@keyframes animBottom {
+  to { bottom: 100px }
+}
+@keyframes animRight {
+  to { right: 100px }
+}
+::before {
+  content: ''
+}
+::after {
+  content: ''
+}
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_document-get-animations.html");
+
+test(function(t) {
+  assert_equals(document.getAnimations().length, 0,
+    'getAnimations returns an empty sequence for a document'
+    + ' with no animations');
+}, 'getAnimations for non-animated content');
+
+test(function(t) {
+  var div = addDiv(t);
+
+  // Add an animation
+  div.style.animation = 'animLeft 100s';
+  assert_equals(document.getAnimations().length, 1,
+                'getAnimations returns a running CSS Animation');
+
+  // Add another animation
+  div.style.animation = 'animLeft 100s, animTop 100s';
+  assert_equals(document.getAnimations().length, 2,
+                'getAnimations returns two running CSS Animations');
+
+  // Remove both
+  div.style.animation = '';
+  assert_equals(document.getAnimations().length, 0,
+                'getAnimations returns no running CSS Animations');
+}, 'getAnimations for CSS Animations');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'animLeft 100s, animTop 100s, animRight 100s, ' +
+                        'animBottom 100s';
+
+  var animations = document.getAnimations();
+  assert_equals(animations.length, 4,
+                'getAnimations returns all running CSS Animations');
+  assert_equals(animations[0].animationName, 'animLeft',
+                'Order of first animation returned');
+  assert_equals(animations[1].animationName, 'animTop',
+                'Order of second animation returned');
+  assert_equals(animations[2].animationName, 'animRight',
+                'Order of third animation returned');
+  assert_equals(animations[3].animationName, 'animBottom',
+                'Order of fourth animation returned');
+}, 'Order of CSS Animations - within an element');
+
+test(function(t) {
+  var div1 = addDiv(t, { style: 'animation: animLeft 100s' });
+  var div2 = addDiv(t, { style: 'animation: animLeft 100s' });
+  var div3 = addDiv(t, { style: 'animation: animLeft 100s' });
+  var div4 = addDiv(t, { style: 'animation: animLeft 100s' });
+
+  var animations = document.getAnimations();
+  assert_equals(animations.length, 4,
+                'getAnimations returns all running CSS Animations');
+  assert_equals(animations[0].effect.target, div1,
+                'Order of first animation returned');
+  assert_equals(animations[1].effect.target, div2,
+                'Order of second animation returned');
+  assert_equals(animations[2].effect.target, div3,
+                'Order of third animation returned');
+  assert_equals(animations[3].effect.target, div4,
+                'Order of fourth animation returned');
+
+  // Order should be depth-first pre-order so add some depth as follows:
+  //
+  //      <parent>
+  //       /  |
+  //      2   3
+  //    /  \
+  //   1   4
+  //
+  // Which should give: 2, 1, 4, 3
+  div2.appendChild(div1);
+  div2.appendChild(div4);
+  animations = document.getAnimations();
+  assert_equals(animations[0].effect.target, div2,
+                'Order of first animation returned after tree surgery');
+  assert_equals(animations[1].effect.target, div1,
+                'Order of second animation returned after tree surgery');
+  assert_equals(animations[2].effect.target, div4,
+                'Order of third animation returned after tree surgery');
+  assert_equals(animations[3].effect.target, div3,
+                'Order of fourth animation returned after tree surgery');
+
+}, 'Order of CSS Animations - across elements');
+
+test(function(t) {
+  var div1 = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
+  var div2 = addDiv(t, { style: 'animation: animBottom 100s' });
+
+  var expectedResults = [ [ div1, 'animLeft' ],
+                          [ div1, 'animTop' ],
+                          [ div2, 'animBottom' ] ];
+  var animations = document.getAnimations();
+  assert_equals(animations.length, expectedResults.length,
+                'getAnimations returns all running CSS Animations');
+  animations.forEach(function(anim, i) {
+    assert_equals(anim.effect.target, expectedResults[i][0],
+                  'Target of animation in position ' + i);
+    assert_equals(anim.animationName, expectedResults[i][1],
+                  'Name of animation in position ' + i);
+  });
+
+  // Modify tree structure and animation list
+  div2.appendChild(div1);
+  div1.style.animation = 'animLeft 100s, animRight 100s, animTop 100s';
+
+  expectedResults = [ [ div2, 'animBottom' ],
+                      [ div1, 'animLeft' ],
+                      [ div1, 'animRight' ],
+                      [ div1, 'animTop' ] ];
+  animations = document.getAnimations();
+  assert_equals(animations.length, expectedResults.length,
+                'getAnimations returns all running CSS Animations after ' +
+                'making changes');
+  animations.forEach(function(anim, i) {
+    assert_equals(anim.effect.target, expectedResults[i][0],
+                  'Target of animation in position ' + i + ' after changes');
+    assert_equals(anim.animationName, expectedResults[i][1],
+                  'Name of animation in position ' + i + ' after changes');
   });
+}, 'Order of CSS Animations - across and within elements');
+
+test(function(t) {
+  var div = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
+  var animLeft = document.getAnimations()[0];
+  assert_equals(animLeft.animationName, 'animLeft',
+                'Originally, animLeft animation comes first');
+
+  // Disassociate animLeft from markup and restart
+  div.style.animation = 'animTop 100s';
+  animLeft.play();
+
+  var animations = document.getAnimations();
+  assert_equals(animations.length, 2,
+                'getAnimations returns markup-bound and free animations');
+  assert_equals(animations[0].animationName, 'animTop',
+                'Markup-bound animations come first');
+  assert_equals(animations[1], animLeft, 'Free animations come last');
+}, 'Order of CSS Animations - markup-bound vs free animations');
+
+test(function(t) {
+  var div = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
+  var animLeft = document.getAnimations()[0];
+  var animTop  = document.getAnimations()[1];
+
+  // Disassociate both animations from markup and restart in opposite order
+  div.style.animation = '';
+  animTop.play();
+  animLeft.play();
+
+  var animations = document.getAnimations();
+  assert_equals(animations.length, 2,
+                'getAnimations returns free animations');
+  assert_equals(animations[0], animTop,
+                'Free animations are returned in the order they are started');
+  assert_equals(animations[1], animLeft,
+                'Animations started later are returned later');
+
+  // Restarting an animation should have no effect
+  animTop.cancel();
+  animTop.play();
+  assert_equals(document.getAnimations()[0], animTop,
+                'After restarting, the ordering of free animations' +
+                ' does not change');
+}, 'Order of CSS Animations - free animations');
+
+test(function(t) {
+  // Add an animation first
+  var div = addDiv(t, { style: 'animation: animLeft 100s' });
+  div.style.top = '0px';
+  div.style.transition = 'all 100s';
+  flushComputedStyle(div);
+
+  // *Then* add a transition
+  div.style.top = '100px';
+  flushComputedStyle(div);
+
+  // Although the transition was added later, it should come first in the list
+  var animations = document.getAnimations();
+  assert_equals(animations.length, 2,
+                'Both CSS animations and transitions are returned');
+  assert_class_string(animations[0], 'CSSTransition', 'Transition comes first');
+  assert_class_string(animations[1], 'CSSAnimation', 'Animation comes second');
+}, 'Order of CSS Animations and CSS Transitions');
+
+test(function(t) {
+  var div = addDiv(t, { style: 'animation: animLeft 100s forwards' });
+  div.getAnimations()[0].finish();
+  assert_equals(document.getAnimations().length, 1,
+                'Forwards-filling CSS animations are returned');
+}, 'Finished but filling CSS Animations are returned');
+
+test(function(t) {
+  var div = addDiv(t, { style: 'animation: animLeft 100s' });
+  div.getAnimations()[0].finish();
+  assert_equals(document.getAnimations().length, 0,
+                'Non-filling finished CSS animations are not returned');
+}, 'Finished but not filling CSS Animations are not returned');
+
+test(function(t) {
+  var div = addDiv(t, { style: 'animation: animLeft 100s 100s' });
+  assert_equals(document.getAnimations().length, 1,
+                'Yet-to-start CSS animations are returned');
+}, 'Yet-to-start CSS Animations are returned');
+
+test(function(t) {
+  var div = addDiv(t, { style: 'animation: animLeft 100s' });
+  div.getAnimations()[0].cancel();
+  assert_equals(document.getAnimations().length, 0,
+                'CSS animations cancelled by the API are not returned');
+}, 'CSS Animations cancelled via the API are not returned');
+
+test(function(t) {
+  var div = addDiv(t, { style: 'animation: animLeft 100s' });
+  var anim = div.getAnimations()[0];
+  anim.cancel();
+  anim.play();
+  assert_equals(document.getAnimations().length, 1,
+                'CSS animations cancelled and restarted by the API are ' +
+                'returned');
+}, 'CSS Animations cancelled and restarted via the API are returned');
+
+test(function(t) {
+  addStyle(t, { '#parent::after': 'animation: animLeft 10s;',
+                '#parent::before': 'animation: animRight 10s;' });
+  // create two divs with these arrangement:
+  //       parent
+  //     ::before,
+  //     ::after
+  //        |
+  //       child
+  var parent = addDiv(t, { 'id': 'parent' });
+  var child = addDiv(t);
+  parent.appendChild(child);
+  [parent, child].forEach((div) => {
+    div.setAttribute('style', 'animation: animBottom 10s');
+  });
+
+  var anims = document.getAnimations();
+  assert_equals(anims.length, 4,
+                'CSS animations on both pseudo-elements and elements ' +
+                'are returned');
+  assert_equals(anims[0].effect.target, parent,
+                'The animation targeting the parent element comes first');
+  assert_equals(anims[1].effect.target.type, '::before',
+                'The animation targeting the ::before element comes second');
+  assert_equals(anims[2].effect.target.type, '::after',
+                'The animation targeting the ::after element comes third');
+  assert_equals(anims[3].effect.target, child,
+                'The animation targeting the child element comes last');
+}, 'CSS Animations targetting (pseudo-)elements should have correct order ' +
+   'after sorting');
+
 </script>
-</html>
+</body>
--- a/dom/animation/test/css-animations/test_effect-target.html
+++ b/dom/animation/test/css-animations/test_effect-target.html
@@ -1,15 +1,62 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes anim { }
+::before {
+  content: ''
+}
+::after {
+  content: ''
+}
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_effect-target.html");
-  });
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim 100s';
+  var animation = div.getAnimations()[0];
+  assert_equals(animation.effect.target, div,
+    'Animation.target is the animatable div');
+}, 'Returned CSS animations have the correct effect target');
+
+test(function(t) {
+  addStyle(t, { '.after::after': 'animation: anim 10s, anim 100s;' });
+  var div = addDiv(t, { class: 'after' });
+  var anims = document.getAnimations();
+  assert_equals(anims.length, 2,
+                'Got animations running on ::after pseudo element');
+  assert_equals(anims[0].effect.target, anims[1].effect.target,
+                'Both animations return the same target object');
+}, 'effect.target should return the same CSSPseudoElement object each time');
+
+test(function(t) {
+  addStyle(t, { '.after::after': 'animation: anim 10s;' });
+  var div = addDiv(t, { class: 'after' });
+  var pseudoTarget = document.getAnimations()[0].effect.target;
+  var effect = new KeyframeEffectReadOnly(pseudoTarget,
+                                          { background: ["blue", "red"] },
+                                          3 * MS_PER_SEC);
+  var newAnim = new Animation(effect, document.timeline);
+  newAnim.play();
+  var anims = document.getAnimations();
+  assert_equals(anims.length, 2,
+                'Got animations running on ::after pseudo element');
+  assert_not_equals(anims[0], newAnim,
+                    'The scriped-generated animation appears last');
+  assert_equals(newAnim.effect.target, pseudoTarget,
+                'The effect.target of the scripted-generated animation is ' +
+                'the same as the one from the argument of ' +
+                'KeyframeEffectReadOnly constructor');
+  assert_equals(anims[0].effect.target, newAnim.effect.target,
+                'Both animations return the same target object');
+}, 'effect.target from the script-generated animation should return the same ' +
+   'CSSPseudoElement object as that from the CSS generated animation');
+
 </script>
-</html>
+</body>
--- a/dom/animation/test/css-animations/test_element-get-animations.html
+++ b/dom/animation/test/css-animations/test_element-get-animations.html
@@ -1,16 +1,453 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes anim1 {
+  to { left: 100px }
+}
+@keyframes anim2 {
+  to { top: 100px }
+}
+@keyframes multiPropAnim {
+  to { background: green, opacity: 0.5, left: 100px, top: 100px }
+}
+::before {
+  content: ''
+}
+::after {
+  content: ''
+}
+@keyframes empty { }
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true],
-            ["dom.animations-api.pending-member.enabled", true]]},
-  function() {
-    window.open("file_element-get-animations.html");
+
+test(function(t) {
+  var div = addDiv(t);
+  assert_equals(div.getAnimations().length, 0,
+    'getAnimations returns an empty sequence for an element'
+    + ' with no animations');
+}, 'getAnimations for non-animated content');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+
+  // FIXME: This test does too many things. It should be split up.
+
+  // Add an animation
+  div.style.animation = 'anim1 100s';
+  var animations = div.getAnimations();
+  assert_equals(animations.length, 1,
+    'getAnimations returns an Animation running CSS Animations');
+  return animations[0].ready.then(function() {
+    var startTime = animations[0].startTime;
+    assert_true(startTime > 0 && startTime <= document.timeline.currentTime,
+      'CSS animation has a sensible start time');
+
+    // Wait a moment then add a second animation.
+    //
+    // We wait for the next frame so that we can test that the start times of
+    // the animations differ.
+    return waitForFrame();
+  }).then(function() {
+    div.style.animation = 'anim1 100s, anim2 100s';
+    animations = div.getAnimations();
+    assert_equals(animations.length, 2,
+      'getAnimations returns one Animation for each value of'
+      + ' animation-name');
+    // Wait until both Animations are ready
+    // (We don't make any assumptions about the order of the Animations since
+    //  that is the purpose of the following test.)
+    return waitForAllAnimations(animations);
+  }).then(function() {
+    assert_true(animations[0].startTime < animations[1].startTime,
+      'Additional Animations for CSS animations start after the original'
+      + ' animation and appear later in the list');
+  });
+}, 'getAnimations for CSS Animations');
+
+test(function(t) {
+  var div = addDiv(t, { style: 'animation: anim1 100s' });
+  assert_class_string(div.getAnimations()[0], 'CSSAnimation',
+                      'Interface of returned animation is CSSAnimation');
+}, 'getAnimations returns CSSAnimation objects for CSS Animations');
+
+test(function(t) {
+  var div = addDiv(t);
+
+  // Add an animation that targets multiple properties
+  div.style.animation = 'multiPropAnim 100s';
+  assert_equals(div.getAnimations().length, 1,
+    'getAnimations returns only one Animation for a CSS Animation'
+    + ' that targets multiple properties');
+}, 'getAnimations for multi-property animations');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+
+  // Add an animation
+  div.style.backgroundColor = 'red';
+  div.style.animation = 'anim1 100s';
+  getComputedStyle(div).backgroundColor;
+
+  // Wait until a frame after the animation starts, then add a transition
+  var animations = div.getAnimations();
+  return animations[0].ready.then(waitForFrame).then(function() {
+    div.style.transition = 'all 100s';
+    div.style.backgroundColor = 'green';
+
+    animations = div.getAnimations();
+    assert_equals(animations.length, 2,
+      'getAnimations returns Animations for both animations and'
+      + ' transitions that run simultaneously');
+    assert_class_string(animations[0], 'CSSTransition',
+                        'First-returned animation is the CSS Transition');
+    assert_class_string(animations[1], 'CSSAnimation',
+                        'Second-returned animation is the CSS Animation');
+  });
+}, 'getAnimations for both CSS Animations and CSS Transitions at once');
+
+async_test(function(t) {
+  var div = addDiv(t);
+
+  // Set up event listener
+  div.addEventListener('animationend', t.step_func(function() {
+    assert_equals(div.getAnimations().length, 0,
+      'getAnimations does not return Animations for finished '
+      + ' (and non-forwards-filling) CSS Animations');
+    t.done();
+  }));
+
+  // Add a very short animation
+  div.style.animation = 'anim1 0.01s';
+}, 'getAnimations for CSS Animations that have finished');
+
+async_test(function(t) {
+  var div = addDiv(t);
+
+  // Set up event listener
+  div.addEventListener('animationend', t.step_func(function() {
+    assert_equals(div.getAnimations().length, 1,
+      'getAnimations returns Animations for CSS Animations that have'
+      + ' finished but are filling forwards');
+    t.done();
+  }));
+
+  // Add a very short animation
+  div.style.animation = 'anim1 0.01s forwards';
+}, 'getAnimations for CSS Animations that have finished but are'
+   + ' forwards filling');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'none 100s';
+
+  var animations = div.getAnimations();
+  assert_equals(animations.length, 0,
+    'getAnimations returns an empty sequence for an element'
+    + ' with animation-name: none');
+
+  div.style.animation = 'none 100s, anim1 100s';
+  animations = div.getAnimations();
+  assert_equals(animations.length, 1,
+    'getAnimations returns Animations only for those CSS Animations whose'
+    + ' animation-name is not none');
+}, 'getAnimations for CSS Animations with animation-name: none');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'missing 100s';
+  var animations = div.getAnimations();
+  assert_equals(animations.length, 0,
+    'getAnimations returns an empty sequence for an element'
+    + ' with animation-name: missing');
+
+  div.style.animation = 'anim1 100s, missing 100s';
+  animations = div.getAnimations();
+  assert_equals(animations.length, 1,
+    'getAnimations returns Animations only for those CSS Animations whose'
+    + ' animation-name is found');
+}, 'getAnimations for CSS Animations with animation-name: missing');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim1 100s, notyet 100s';
+  var animations = div.getAnimations();
+  assert_equals(animations.length, 1,
+    'getAnimations initally only returns Animations for CSS Animations whose'
+    + ' animation-name is found');
+
+  return animations[0].ready.then(waitForFrame).then(function() {
+    var keyframes = '@keyframes notyet { to { left: 100px; } }';
+    document.styleSheets[0].insertRule(keyframes, 0);
+    animations = div.getAnimations();
+    assert_equals(animations.length, 2,
+      'getAnimations includes Animation when @keyframes rule is added'
+      + ' later');
+    return waitForAllAnimations(animations);
+  }).then(function() {
+    assert_true(animations[0].startTime < animations[1].startTime,
+      'Newly added animation has a later start time');
+    document.styleSheets[0].deleteRule(0);
+  });
+}, 'getAnimations for CSS Animations where the @keyframes rule is added'
+   + ' later');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim1 100s, anim1 100s';
+  assert_equals(div.getAnimations().length, 2,
+    'getAnimations returns one Animation for each CSS animation-name'
+    + ' even if the names are duplicated');
+}, 'getAnimations for CSS Animations with duplicated animation-name');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'empty 100s';
+  assert_equals(div.getAnimations().length, 1,
+    'getAnimations returns Animations for CSS animations with an'
+    + ' empty keyframes rule');
+}, 'getAnimations for CSS Animations with empty keyframes rule');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim1 100s 100s';
+  var animations = div.getAnimations();
+  assert_equals(animations.length, 1,
+    'getAnimations returns animations for CSS animations whose'
+    + ' delay makes them start later');
+  return animations[0].ready.then(waitForFrame).then(function() {
+    assert_true(animations[0].startTime <= document.timeline.currentTime,
+      'For CSS Animations in delay phase, the start time of the Animation is'
+      + ' not in the future');
   });
+}, 'getAnimations for CSS animations in delay phase');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim1 0s 100s';
+  assert_equals(div.getAnimations().length, 1,
+    'getAnimations returns animations for CSS animations whose'
+    + ' duration is zero');
+  div.remove();
+}, 'getAnimations for zero-duration CSS Animations');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim1 100s';
+  var originalAnimation = div.getAnimations()[0];
+
+  // Update pause state (an Animation change)
+  div.style.animationPlayState = 'paused';
+  var pendingAnimation = div.getAnimations()[0];
+  assert_equals(pendingAnimation.playState, 'paused',
+                'animation\'s play state is updated');
+  assert_equals(originalAnimation, pendingAnimation,
+                'getAnimations returns the same objects even when their'
+                + ' play state changes');
+
+  // Update duration (an Animation change)
+  div.style.animationDuration = '200s';
+  var extendedAnimation = div.getAnimations()[0];
+  // FIXME: Check extendedAnimation.effect.timing.duration has changed once the
+  // API is available
+  assert_equals(originalAnimation, extendedAnimation,
+                'getAnimations returns the same objects even when their'
+                + ' duration changes');
+}, 'getAnimations returns objects with the same identity');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim1 100s';
+
+  assert_equals(div.getAnimations().length, 1,
+    'getAnimations returns an animation before cancelling');
+
+  var animation = div.getAnimations()[0];
+
+  animation.cancel();
+  assert_equals(div.getAnimations().length, 0,
+    'getAnimations does not return cancelled animations');
+
+  animation.play();
+  assert_equals(div.getAnimations().length, 1,
+    'getAnimations returns cancelled animations that have been re-started');
+
+}, 'getAnimations for CSS Animations that are cancelled');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim2 100s';
+
+  return div.getAnimations()[0].ready.then(function() {
+    // Prepend to the list and test that even though anim1 was triggered
+    // *after* anim2, it should come first because it appears first
+    // in the animation-name property.
+    div.style.animation = 'anim1 100s, anim2 100s';
+    var anims = div.getAnimations();
+    assert_equals(anims[0].animationName, 'anim1',
+                  'animation order after prepending to list');
+    assert_equals(anims[1].animationName, 'anim2',
+                  'animation order after prepending to list');
+
+    // Normally calling cancel and play would this push anim1 to the top of
+    // the stack but it shouldn't for CSS animations that map an the
+    // animation-name property.
+    var anim1 = anims[0];
+    anim1.cancel();
+    anim1.play();
+    anims = div.getAnimations();
+    assert_equals(anims[0].animationName, 'anim1',
+                  'animation order after cancelling and restarting');
+    assert_equals(anims[1].animationName, 'anim2',
+                  'animation order after cancelling and restarting');
+  });
+}, 'getAnimations for CSS Animations follows animation-name order');
+
+test(function(t) {
+  addStyle(t, { '#target::after': 'animation: anim1 10s;',
+                '#target::before': 'animation: anim1 10s;' });
+  var target = addDiv(t, { 'id': 'target' });
+  target.style.animation = 'anim1 100s';
+
+  var animations = target.getAnimations({ subtree: false });
+  assert_equals(animations.length, 1,
+                'Should find only the element');
+  assert_equals(animations[0].effect.target, target,
+                'Effect target should be the element');
+}, 'Test AnimationFilter{ subtree: false } with single element');
+
+test(function(t) {
+  addStyle(t, { '#target::after': 'animation: anim1 10s;',
+                '#target::before': 'animation: anim1 10s;' });
+  var target = addDiv(t, { 'id': 'target' });
+  target.style.animation = 'anim1 100s';
+
+  var animations = target.getAnimations({ subtree: true });
+  assert_equals(animations.length, 3,
+                'getAnimations({ subtree: true }) ' +
+                'should return animations on pseudo-elements');
+  assert_equals(animations[0].effect.target, target,
+                'The animation targeting the parent element ' +
+                'should be returned first');
+  assert_equals(animations[1].effect.target.type, '::before',
+                'The animation targeting the ::before pseudo-element ' +
+                'should be returned second');
+  assert_equals(animations[2].effect.target.type, '::after',
+                'The animation targeting the ::after pesudo-element ' +
+                'should be returned last');
+}, 'Test AnimationFilter{ subtree: true } with single element');
+
+test(function(t) {
+  addStyle(t, { '#parent::after': 'animation: anim1 10s;',
+                '#parent::before': 'animation: anim1 10s;',
+                '#child::after': 'animation: anim1 10s;',
+                '#child::before': 'animation: anim1 10s;' });
+  var parent = addDiv(t, { 'id': 'parent' });
+  parent.style.animation = 'anim1 100s';
+  var child = addDiv(t, { 'id': 'child' });
+  child.style.animation = 'anim1 100s';
+  parent.appendChild(child);
+
+  var animations = parent.getAnimations({ subtree: false });
+  assert_equals(animations.length, 1,
+                'Should find only the element even if it has a child');
+  assert_equals(animations[0].effect.target, parent,
+                'Effect target shuld be the element');
+}, 'Test AnimationFilter{ subtree: false } with element that has a child');
+
+test(function(t) {
+  addStyle(t, { '#parent::after': 'animation: anim1 10s;',
+                '#parent::before': 'animation: anim1 10s;',
+                '#child::after': 'animation: anim1 10s;',
+                '#child::before': 'animation: anim1 10s;' });
+  var parent = addDiv(t, { 'id': 'parent' });
+  var child = addDiv(t, { 'id': 'child' });
+  parent.style.animation = 'anim1 100s';
+  child.style.animation = 'anim1 100s';
+  parent.appendChild(child);
+
+  var animations = parent.getAnimations({ subtree: true });
+  assert_equals(animations.length, 6,
+                'Should find all elements, pesudo-elements that parent has');
+
+  assert_equals(animations[0].effect.target, parent,
+                'The animation targeting the parent element ' +
+                'should be returned first');
+  assert_equals(animations[1].effect.target.type, '::before',
+                'The animation targeting the ::before pseudo-element ' +
+                'should be returned second');
+  assert_equals(animations[1].effect.target.parentElement, parent,
+                'This ::before element should be child of parent element');
+  assert_equals(animations[2].effect.target.type, '::after',
+                'The animation targeting the ::after pesudo-element ' +
+                'should be returned third');
+  assert_equals(animations[2].effect.target.parentElement, parent,
+                'This ::after element should be child of parent element');
+
+  assert_equals(animations[3].effect.target, child,
+                'The animation targeting the child element ' +
+                'should be returned fourth');
+  assert_equals(animations[4].effect.target.type, '::before',
+                'The animation targeting the ::before pseudo-element ' +
+                'should be returned fifth');
+  assert_equals(animations[4].effect.target.parentElement, child,
+                'This ::before element should be child of child element');
+  assert_equals(animations[5].effect.target.type, '::after',
+                'The animation targeting the ::after pesudo-element ' +
+                'should be returned last');
+  assert_equals(animations[5].effect.target.parentElement, child,
+                'This ::after element should be child of child element');
+}, 'Test AnimationFilter{ subtree: true } with element that has a child');
+
+test(function(t) {
+  var parent = addDiv(t, { 'id': 'parent' });
+  var child1 = addDiv(t, { 'id': 'child1' });
+  var grandchild1 = addDiv(t, { 'id': 'grandchild1' });
+  var grandchild2 = addDiv(t, { 'id': 'grandchild2' });
+  var child2 = addDiv(t, { 'id': 'child2' });
+
+  parent.style.animation = 'anim1 100s';
+  child1.style.animation = 'anim1 100s';
+  grandchild1.style.animation = 'anim1 100s';
+  grandchild2.style.animation = 'anim1 100s';
+  child2.style.animation = 'anim1 100s';
+
+  parent.appendChild(child1);
+  child1.appendChild(grandchild1);
+  child1.appendChild(grandchild2);
+  parent.appendChild(child2);
+
+  var animations = parent.getAnimations({ subtree: true });
+  assert_equals(
+    parent.getAnimations({ subtree: true }).length, 5,
+                         'Should find all descendants of the element');
+
+  assert_equals(animations[0].effect.target, parent,
+                'The animation targeting the parent element ' +
+                'should be returned first');
+
+  assert_equals(animations[1].effect.target, child1,
+                'The animation targeting the child1 element ' +
+                'should be returned second');
+
+  assert_equals(animations[2].effect.target, grandchild1,
+                'The animation targeting the grandchild1 element ' +
+                'should be returned third');
+
+  assert_equals(animations[3].effect.target, grandchild2,
+                'The animation targeting the grandchild2 element ' +
+                'should be returned fourth');
+
+  assert_equals(animations[4].effect.target, child2,
+                'The animation targeting the child2 element ' +
+                'should be returned last');
+
+}, 'Test AnimationFilter{ subtree: true } with element that has many descendant');
+
 </script>
-</html>
+</body>
--- a/dom/animation/test/css-animations/test_event-dispatch.html
+++ b/dom/animation/test/css-animations/test_event-dispatch.html
@@ -1,15 +1,380 @@
 <!doctype html>
 <meta charset=utf-8>
+<title>Tests for CSS animation event dispatch</title>
+<link rel="help" href="https://drafts.csswg.org/css-animations-2/#event-dispatch"/>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+  @keyframes anim {
+    from { margin-left: 0px; }
+    to { margin-left: 100px; }
+  }
+</style>
+<body>
 <div id="log"></div>
 <script>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]] },
-  function() {
-    window.open("file_event-dispatch.html");
+
+/**
+ * Helper class to record the elapsedTime member of each event.
+ * The EventWatcher class in testharness.js allows us to wait on
+ * multiple events in a certain order but only records the event
+ * parameters of the most recent event.
+ */
+function AnimationEventHandler(target) {
+  this.target = target;
+  this.target.onanimationstart = evt => {
+   this.animationstart = evt.elapsedTime;
+  };
+  this.target.onanimationiteration = evt => {
+    this.animationiteration = evt.elapsedTime;
+  };
+  this.target.onanimationend = evt => {
+    this.animationend = evt.elapsedTime;
+  };
+  this.target.onanimationcancel = evt => {
+    this.animationcancel = evt.elapsedTime;
+  };
+}
+AnimationEventHandler.prototype.clear = () => {
+  this.animationstart     = undefined;
+  this.animationiteration = undefined;
+  this.animationend       = undefined;
+  this.animationcancel    = undefined;
+}
+
+function setupAnimation(t, animationStyle) {
+  const div = addDiv(t, { style: 'animation: ' + animationStyle });
+  // Note that this AnimationEventHandler should be created before EventWatcher
+  // to capture all events in the handler prior to the EventWatcher since
+  // testharness.js proceeds when the EventWatcher received watching events.
+  const handler = new AnimationEventHandler(div);
+  const watcher = new EventWatcher(t, div, [ 'animationstart',
+                                           'animationiteration',
+                                           'animationend',
+                                           'animationcancel' ]);
+  const animation = div.getAnimations()[0];
+
+  return { animation, watcher, div, handler };
+}
+
+promise_test(t => {
+  // Add 1ms delay to ensure that the delay is not included in the elapsedTime.
+  const { animation, watcher } = setupAnimation(t, 'anim 100s 1ms');
+
+  return watcher.wait_for('animationstart').then(evt => {
+    assert_equals(evt.elapsedTime, 0.0);
+  });
+}, 'Idle -> Active');
+
+promise_test(t => {
+  const { animation, watcher, div, handler } = setupAnimation(t, 'anim 100s');
+
+  // Seek to After phase.
+  animation.finish();
+  return watcher.wait_for([ 'animationstart',
+                            'animationend' ]).then(() => {
+    assert_equals(handler.animationstart, 0.0);
+    assert_equals(handler.animationend, 100);
+  });
+}, 'Idle -> After');
+
+promise_test(t => {
+  const { animation, watcher } =
+    setupAnimation(t, 'anim 100s 100s paused');
+
+  return animation.ready.then(() => {
+    // Seek to Active phase.
+    animation.currentTime = 100 * MS_PER_SEC;
+    return watcher.wait_for('animationstart');
+  }).then(evt => {
+    assert_equals(evt.elapsedTime, 0.0);
+  });
+}, 'Before -> Active');
+
+promise_test(t => {
+  const { animation, watcher, div, handler } =
+    setupAnimation(t, 'anim 100s 100s paused');
+
+  return animation.ready.then(() => {
+    // Seek to After phase.
+    animation.finish();
+    return watcher.wait_for([ 'animationstart', 'animationend' ]);
+  }).then(evt => {
+    assert_equals(handler.animationstart, 0.0);
+    assert_equals(handler.animationend, 100.0);
+  });
+}, 'Before -> After');
+
+promise_test(t => {
+  const { animation, watcher, div } = setupAnimation(t, 'anim 100s paused');
+
+  return watcher.wait_for('animationstart').then(evt => {
+    // Make idle
+    div.style.display = 'none';
+    return watcher.wait_for('animationcancel');
+  }).then(evt => {
+    assert_equals(evt.elapsedTime, 0.0);
+  });
+}, 'Active -> Idle, display: none');
+
+promise_test(t => {
+  const { animation, watcher, div } = setupAnimation(t, 'anim 100s');
+
+  return watcher.wait_for('animationstart').then(evt => {
+    animation.currentTime = 100.0;
+    // Make idle
+    animation.timeline = null;
+    return watcher.wait_for('animationcancel');
+  }).then(evt => {
+    assert_time_equals_literal(evt.elapsedTime, 0.1);
+  });
+}, 'Active -> Idle, setting Animation.timeline = null');
+
+promise_test(t => {
+  // we should NOT pause animation since calling cancel synchronously.
+  const { animation, watcher, div } = setupAnimation(t, 'anim 100s');
+
+  return watcher.wait_for('animationstart').then(evt => {
+    animation.currentTime = 50.0;
+    animation.cancel();
+    return watcher.wait_for('animationcancel');
+  }).then(evt => {
+    assert_time_equals_literal(evt.elapsedTime, 0.05);
+  });
+}, 'Active -> Idle, calling Animation.cancel()');
+
+promise_test(t => {
+  const { animation, watcher } =
+    setupAnimation(t, 'anim 100s 100s paused');
+
+  // Seek to Active phase.
+  animation.currentTime = 100 * MS_PER_SEC;
+  return watcher.wait_for('animationstart').then(() => {
+    // Seek to Before phase.
+    animation.currentTime = 0;
+    return watcher.wait_for('animationend');
+  }).then(evt => {
+    assert_equals(evt.elapsedTime, 0.0);
+  });
+}, 'Active -> Before');
+
+promise_test(t => {
+  const { animation, watcher } = setupAnimation(t, 'anim 100s paused');
+
+  return watcher.wait_for('animationstart').then(evt => {
+    // Seek to After phase.
+    animation.finish();
+    return watcher.wait_for('animationend');
+  }).then(evt => {
+    assert_equals(evt.elapsedTime, 100.0);
+  });
+}, 'Active -> After');
+
+promise_test(t => {
+  const { animation, watcher, div, handler } =
+    setupAnimation(t, 'anim 100s 100s paused');
+
+  // Seek to After phase.
+  animation.finish();
+  return watcher.wait_for([ 'animationstart',
+                            'animationend' ]).then(() => {
+    // Seek to Before phase.
+    animation.currentTime = 0;
+    handler.clear();
+    return watcher.wait_for([ 'animationstart', 'animationend' ]);
+  }).then(() => {
+    assert_equals(handler.animationstart, 100.0);
+    assert_equals(handler.animationend, 0.0);
   });
+}, 'After -> Before');
+
+promise_test(t => {
+  const { animation, watcher, div } =
+    setupAnimation(t, 'anim 100s 100s paused');
+
+  // Seek to After phase.
+  animation.finish();
+  return watcher.wait_for([ 'animationstart',
+                            'animationend' ]).then(() => {
+    // Seek to Active phase.
+    animation.currentTime = 100 * MS_PER_SEC;
+    return watcher.wait_for('animationstart');
+  }).then(evt => {
+    assert_equals(evt.elapsedTime, 100.0);
+  });
+}, 'After -> Active');
+
+promise_test(t => {
+  const { animation, watcher, div }
+    = setupAnimation(t, 'anim 100s 100s 3 paused');
+
+  return animation.ready.then(() => {
+    // Seek to iteration 0 (no animationiteration event should be dispatched)
+    animation.currentTime = 100 * MS_PER_SEC;
+    return watcher.wait_for('animationstart');
+  }).then(evt => {
+    // Seek to iteration 2
+    animation.currentTime = 300 * MS_PER_SEC;
+    return watcher.wait_for('animationiteration');
+  }).then(evt => {
+    assert_equals(evt.elapsedTime, 200);
+    // Seek to After phase (no animationiteration event should be dispatched)
+    animation.currentTime = 400 * MS_PER_SEC;
+    return watcher.wait_for('animationend');
+  }).then(evt => {
+    assert_equals(evt.elapsedTime, 300);
+  });
+}, 'Active -> Active (forwards)');
+
+promise_test(t => {
+  const { animation, watcher } = setupAnimation(t, 'anim 100s 100s 3');
+
+  // Seek to After phase.
+  animation.finish();
+  return watcher.wait_for([ 'animationstart',
+                            'animationend' ]).then(() => {
+    // Seek to iteration 2 (no animationiteration event should be dispatched)
+    animation.pause();
+    animation.currentTime = 300 * MS_PER_SEC;
+    return watcher.wait_for('animationstart');
+  }).then(() => {
+    // Seek to mid of iteration 0 phase.
+    animation.currentTime = 200 * MS_PER_SEC;
+    return watcher.wait_for('animationiteration');
+  }).then(evt => {
+    assert_equals(evt.elapsedTime, 200.0);
+    // Seek to before phase (no animationiteration event should be dispatched)
+    animation.currentTime = 0;
+    return watcher.wait_for('animationend');
+  });
+}, 'Active -> Active (backwards)');
+
+promise_test(t => {
+  const { animation, watcher, div } =
+    setupAnimation(t, 'anim 100s paused');
+  return watcher.wait_for('animationstart').then(evt => {
+    // Seek to Idle phase.
+    div.style.display = 'none';
+    flushComputedStyle(div);
+
+    return watcher.wait_for('animationcancel');
+  }).then(() => {
+    // Restart this animation.
+    div.style.display = '';
+    return watcher.wait_for('animationstart');
+  });
+}, 'Active -> Idle -> Active: animationstart is fired by restarting animation');
+
+promise_test(t => {
+  const { animation, watcher } =
+    setupAnimation(t, 'anim 100s 100s 2 paused');
+
+  // Make After.
+  animation.finish();
+  return watcher.wait_for([ 'animationstart',
+                            'animationend' ]).then(evt => {
+    animation.playbackRate = -1;
+    return watcher.wait_for('animationstart');
+  }).then(evt => {
+    assert_equals(evt.elapsedTime, 200);
+    // Seek to 1st iteration
+    animation.currentTime = 200 * MS_PER_SEC - 1;
+    return watcher.wait_for('animationiteration');
+  }).then(evt => {
+    assert_equals(evt.elapsedTime, 100);
+    // Seek to before
+    animation.currentTime = 100 * MS_PER_SEC - 1;
+    return watcher.wait_for('animationend');
+  }).then(evt => {
+    assert_equals(evt.elapsedTime, 0);
+    assert_equals(animation.playState, 'running'); // delay
+  });
+}, 'Negative playbackRate sanity test(Before -> Active -> Before)');
+
+promise_test(t => {
+  const { animation, watcher } = setupAnimation(t, 'anim 100s');
+
+  return watcher.wait_for('animationstart').then(evt => {
+    // Make idle
+    animation.cancel();
+    return watcher.wait_for('animationcancel');
+  }).then(evt => {
+    animation.cancel();
+    // Then wait a couple of frames and check that no event was dispatched.
+    return waitForAnimationFrames(2);
+  });
+}, 'Call Animation.cancel after cancelling animation.');
+
+promise_test(t => {
+  const { animation, watcher } = setupAnimation(t, 'anim 100s');
+
+  return watcher.wait_for('animationstart').then(evt => {
+    // Make idle
+    animation.cancel();
+    animation.play();
+    return watcher.wait_for([ 'animationcancel',
+                              'animationstart' ]);
+  });
+}, 'Restart animation after cancelling animation immediately.');
+
+promise_test(t => {
+  const { animation, watcher } = setupAnimation(t, 'anim 100s');
+
+  return watcher.wait_for('animationstart').then(evt => {
+    // Make idle
+    animation.cancel();
+    animation.play();
+    animation.cancel();
+    return watcher.wait_for('animationcancel');
+  }).then(evt => {
+    // Then wait a couple of frames and check that no event was dispatched.
+    return waitForAnimationFrames(2);
+  });
+}, 'Call Animation.cancel after restarting animation immediately.');
+
+promise_test(t => {
+  const { animation, watcher } = setupAnimation(t, 'anim 100s');
+
+  return watcher.wait_for('animationstart').then(evt => {
+    // Make idle
+    animation.timeline = null;
+    return watcher.wait_for('animationcancel');
+  }).then(evt => {
+    animation.timeline = document.timeline;
+    animation.play();
+    return watcher.wait_for('animationstart');
+  });
+}, 'Set timeline and play transition after clearing the timeline.');
+
+promise_test(t => {
+  const { animation, watcher } = setupAnimation(t, 'anim 100s');
+
+  return watcher.wait_for('animationstart').then(evt => {
+    // Make idle
+    animation.cancel();
+    return watcher.wait_for('animationcancel');
+  }).then(evt => {
+    animation.effect = null;
+    // Then wait a couple of frames and check that no event was dispatched.
+    return waitForAnimationFrames(2);
+  });
+}, 'Set null target effect after cancelling the animation.');
+
+promise_test(t => {
+  const { animation, watcher } = setupAnimation(t, 'anim 100s');
+
+  return watcher.wait_for('animationstart').then(evt => {
+    animation.effect = null;
+    return watcher.wait_for('animationend');
+  }).then(evt => {
+    animation.cancel();
+    // Then wait a couple of frames and check that no event was dispatched.
+    return waitForAnimationFrames(2);
+  });
+}, 'Cancel the animation after clearing the target effect.');
+
 </script>
+</body>
 </html>
--- a/dom/animation/test/css-animations/test_event-order.html
+++ b/dom/animation/test/css-animations/test_event-order.html
@@ -1,15 +1,163 @@
 <!doctype html>
 <meta charset=utf-8>
+<title>Tests for CSS animation event order</title>
+<link rel="help" href="https://drafts.csswg.org/css-animations-2/#event-dispatch"/>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+  @keyframes anim {
+    from { margin-left: 0px; }
+    to { margin-left: 100px; }
+  }
+</style>
+<body>
 <div id="log"></div>
-<script>
+<script type='text/javascript'>
 'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_event-order.html");
+
+/**
+ * Asserts that the set of actual and received events match.
+ * @param actualEvents   An array of the received AnimationEvent objects.
+ * @param expectedEvents A series of array objects representing the expected
+ *        events, each having the form:
+ *          [ event type, target element, elapsed time ]
+ */
+function checkEvents(actualEvents, ...expectedEvents) {
+  assert_equals(actualEvents.length, expectedEvents.length,
+                `Number of actual events (${actualEvents.length}: \
+${actualEvents.map(event => event.type).join(', ')}) should match expected \
+events (${expectedEvents.map(event => event.type).join(', ')})`);
+
+  actualEvents.forEach((actualEvent, i) => {
+    assert_equals(expectedEvents[i][0], actualEvent.type,
+                  'Event type should match');
+    assert_equals(expectedEvents[i][1], actualEvent.target,
+                  'Event target should match');
+    assert_equals(expectedEvents[i][2], actualEvent.elapsedTime,
+                  'Event\'s elapsed time should match');
+  });
+}
+
+function setupAnimation(t, animationStyle, receiveEvents) {
+  const div = addDiv(t, { style: "animation: " + animationStyle });
+
+  ['start', 'iteration', 'end'].forEach(name => {
+    div['onanimation' + name] = evt => {
+    receiveEvents.push({ type:        evt.type,
+                         target:      evt.target,
+                         elapsedTime: evt.elapsedTime });
+    };
   });
+
+  const watcher = new EventWatcher(t, div, [ 'animationstart',
+                                             'animationiteration',
+                                             'animationend' ]);
+
+  const animation = div.getAnimations()[0];
+
+  return [animation, watcher, div];
+}
+
+promise_test(t => {
+  let events = [];
+  const [animation1, watcher1, div1] =
+    setupAnimation(t, 'anim 100s 2 paused', events);
+  const [animation2, watcher2, div2] =
+    setupAnimation(t, 'anim 100s 2 paused', events);
+
+  return Promise.all([ watcher1.wait_for('animationstart'),
+                       watcher2.wait_for('animationstart') ]).then(() => {
+    checkEvents(events, ['animationstart', div1, 0],
+                        ['animationstart', div2, 0]);
+
+    events.length = 0;  // Clear received event array
+
+    animation1.currentTime = 100 * MS_PER_SEC;
+    animation2.currentTime = 100 * MS_PER_SEC;
+    return Promise.all([ watcher1.wait_for('animationiteration'),
+                         watcher2.wait_for('animationiteration') ]);
+  }).then(() => {
+    checkEvents(events, ['animationiteration', div1, 100],
+                        ['animationiteration', div2, 100]);
+
+    events.length = 0;  // Clear received event array
+
+    animation1.finish();
+    animation2.finish();
+
+    return Promise.all([ watcher1.wait_for('animationend'),
+                         watcher2.wait_for('animationend') ]);
+  }).then(() => {
+    checkEvents(events, ['animationend', div1, 200],
+                        ['animationend', div2, 200]);
+  });
+}, 'Test same events are ordered by elements.');
+
+promise_test(t => {
+  let events = [];
+  const [animation1, watcher1, div1] =
+    setupAnimation(t, 'anim 200s 400s', events);
+  const [animation2, watcher2, div2] =
+    setupAnimation(t, 'anim 300s 2', events);
+
+  return watcher2.wait_for('animationstart').then(evt => {
+    animation1.currentTime = 400 * MS_PER_SEC;
+    animation2.currentTime = 400 * MS_PER_SEC;
+
+    events.length = 0;  // Clear received event array
+
+    return Promise.all([ watcher1.wait_for('animationstart'),
+                         watcher2.wait_for('animationiteration') ]);
+  }).then(() => {
+    checkEvents(events, ['animationiteration', div2, 300],
+                        ['animationstart',     div1, 0]);
+  });
+}, 'Test start and iteration events are ordered by time.');
+
+promise_test(t => {
+  let events = [];
+  const [animation1, watcher1, div1] =
+    setupAnimation(t, 'anim 150s', events);
+  const [animation2, watcher2, div2] =
+    setupAnimation(t, 'anim 100s 2', events);
+
+  return Promise.all([ watcher1.wait_for('animationstart'),
+                       watcher2.wait_for('animationstart') ]).then(() => {
+    animation1.currentTime = 150 * MS_PER_SEC;
+    animation2.currentTime = 150 * MS_PER_SEC;
+
+    events.length = 0;  // Clear received event array
+
+    return Promise.all([ watcher1.wait_for('animationend'),
+                         watcher2.wait_for('animationiteration') ]);
+  }).then(() => {
+    checkEvents(events, ['animationiteration', div2, 100],
+                        ['animationend',       div1, 150]);
+  });
+}, 'Test iteration and end events are ordered by time.');
+
+promise_test(t => {
+  let events = [];
+  const [animation1, watcher1, div1] =
+    setupAnimation(t, 'anim 100s 100s', events);
+  const [animation2, watcher2, div2] =
+    setupAnimation(t, 'anim 100s 2', events);
+
+  animation1.finish();
+  animation2.finish();
+
+  return Promise.all([ watcher1.wait_for([ 'animationstart',
+                                           'animationend' ]),
+                       watcher2.wait_for([ 'animationstart',
+                                           'animationend' ]) ]).then(() => {
+    checkEvents(events, ['animationstart', div2, 0],
+                        ['animationstart', div1, 0],
+                        ['animationend',   div1, 100],
+                        ['animationend',   div2, 200]);
+  });
+}, 'Test start and end events are sorted correctly when fired simultaneously');
+
 </script>
+</body>
 </html>
--- a/dom/animation/test/css-animations/test_keyframeeffect-getkeyframes.html
+++ b/dom/animation/test/css-animations/test_keyframeeffect-getkeyframes.html
@@ -1,15 +1,756 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes anim-empty { }
+
+@keyframes anim-empty-frames {
+  from { }
+  to   { }
+}
+
+@keyframes anim-only-timing {
+  from { animation-timing-function: linear; }
+  to   { }
+}
+
+@keyframes anim-only-non-animatable {
+  from { animation-duration: 3s; }
+  to   { animation-duration: 5s; }
+}
+
+@keyframes anim-simple {
+  from { color: rgb(0, 0, 0); }
+  to   { color: rgb(255, 255, 255); }
+}
+
+@keyframes anim-simple-three {
+  from { color: rgb(0, 0, 0); }
+  50%  { color: rgb(0, 0, 255); }
+  to   { color: rgb(255, 255, 255); }
+}
+
+@keyframes anim-simple-timing {
+  from { color: rgb(0, 0, 0); animation-timing-function: linear; }
+  50%  { color: rgb(0, 0, 255);  animation-timing-function: ease-in-out; }
+  to   { color: rgb(255, 255, 255); animation-timing-function: step-end; }
+}
+
+@keyframes anim-simple-timing-some {
+  from { color: rgb(0, 0, 0); animation-timing-function: linear; }
+  50%  { color: rgb(0, 0, 255); }
+  to   { color: rgb(255, 255, 255); }
+}
+
+@keyframes anim-simple-shorthand {
+  from { margin: 8px; }
+  to   { margin: 16px; }
+}
+
+@keyframes anim-omit-to {
+  from { color: rgb(0, 0, 255); }
+}
+
+@keyframes anim-omit-from {
+  to   { color: rgb(0, 0, 255); }
+}
+
+@keyframes anim-omit-from-to {
+  50%  { color: rgb(0, 0, 255); }
+}
+
+@keyframes anim-partially-omit-to {
+  from { margin-top: 50px;
+         margin-bottom: 100px; }
+  to   { margin-top: 150px !important; /* ignored */
+         margin-bottom: 200px; }
+}
+
+@keyframes anim-different-props {
+  from { color: rgb(0, 0, 0); margin-top: 8px; }
+  25%  { color: rgb(0, 0, 255); }
+  75%  { margin-top: 12px; }
+  to   { color: rgb(255, 255, 255); margin-top: 16px }
+}
+
+@keyframes anim-different-props-and-easing {
+  from { color: rgb(0, 0, 0); margin-top: 8px; animation-timing-function: linear; }
+  25%  { color: rgb(0, 0, 255); animation-timing-function: step-end; }
+  75%  { margin-top: 12px; animation-timing-function: ease-in; }
+  to   { color: rgb(255, 255, 255); margin-top: 16px }
+}
+
+@keyframes anim-merge-offset {
+  from { color: rgb(0, 0, 0); }
+  to   { color: rgb(255, 255, 255); }
+  from { margin-top: 8px; }
+  to   { margin-top: 16px; }
+}
+
+@keyframes anim-merge-offset-and-easing {
+  from { color: rgb(0, 0, 0); animation-timing-function: step-end; }
+  to   { color: rgb(255, 255, 255); }
+  from { margin-top: 8px; animation-timing-function: linear; }
+  to   { margin-top: 16px; }
+  from { font-size: 16px; animation-timing-function: step-end; }
+  to   { font-size: 32px; }
+  from { padding-left: 2px; animation-timing-function: linear; }
+  to   { padding-left: 4px; }
+}
+
+@keyframes anim-no-merge-equiv-easing {
+  from { margin-top: 0px; animation-timing-function: steps(1, end); }
+  from { margin-right: 0px; animation-timing-function: step-end; }
+  from { margin-bottom: 0px; animation-timing-function: steps(1); }
+  50%  { margin-top: 10px; animation-timing-function: step-end; }
+  50%  { margin-right: 10px; animation-timing-function: step-end; }
+  50%  { margin-bottom: 10px; animation-timing-function: step-end; }
+  to   { margin-top: 20px; margin-right: 20px; margin-bottom: 20px; }
+}
+
+@keyframes anim-overriding {
+  from          { padding-top: 50px }
+  50%, from     { padding-top: 30px } /* wins: 0% */
+  75%, 85%, 50% { padding-top: 20px } /* wins: 75%, 50% */
+  100%, 85%     { padding-top: 70px } /* wins: 100% */
+  85.1%         { padding-top: 60px } /* wins: 85.1% */
+  85%           { padding-top: 30px } /* wins: 85% */
+}
+
+@keyframes anim-filter {
+  to { filter: blur(5px) sepia(60%) saturate(30%); }
+}
+
+@keyframes anim-filter-drop-shadow {
+  from { filter: drop-shadow(10px 10px 10px rgb(0, 255, 0)); }
+  to { filter: drop-shadow(50px 30px 10px rgb(255, 0, 0)); }
+}
+
+@keyframes anim-text-shadow {
+  to { text-shadow: none; }
+}
+
+@keyframes anim-background-size {
+  to { background-size: 50%, 6px, contain }
+}
+
+:root {
+  --var-100px: 100px;
+  --end-color: rgb(255, 0, 0);
+}
+@keyframes anim-variables {
+  to { transform: translate(var(--var-100px), 0) }
+}
+@keyframes anim-variables-shorthand {
+  to { margin: var(--var-100px) }
+}
+@keyframes anim-custom-property-in-keyframe {
+  to { --end-color: rgb(0, 255, 0); color: var(--end-color) }
+}
+@keyframes anim-only-custom-property-in-keyframe {
+  from { transform: translate(100px, 0) }
+  to { --not-used: 200px }
+}
+</style>
+<body>
 <div id="log"></div>
 <script>
-'use strict';
-setup({explicit_done: true});
-SpecialPowers.pushPrefEnv(
-  { "set": [["dom.animations-api.core.enabled", true]]},
-  function() {
-    window.open("file_keyframeeffect-getkeyframes.html");
+"use strict";
+
+function getKeyframes(e) {
+  return e.getAnimations()[0].effect.getKeyframes();
+}
+
+function assert_frames_equal(a, b, name) {
+  assert_equals(Object.keys(a).sort().toString(),
+                Object.keys(b).sort().toString(),
+                "properties on " + name);
+  for (var p in a) {
+    if (p === 'offset' || p === 'computedOffset') {
+      assert_approx_equals(a[p], b[p], 0.00001,
+                           "value for '" + p + "' on " + name);
+    } else {
+      assert_equals(a[p], b[p], "value for '" + p + "' on " + name);