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 407565 fdd1a0082c71
parent 407564 e29b54201696 (current diff)
parent 407553 d6ccaacd9692 (diff)
child 407566 e7b736c64e87
child 407682 a1171de0b81e
child 407689 ba49fafd4e53
push id100718
push userbtara@mozilla.com
push date2018-03-12 10:00 +0000
treeherdermozilla-inbound@e7b736c64e87 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone60.0a1
first release with
nightly linux32
fdd1a0082c71 / 60.0a1 / 20180312100129 / files
nightly linux64
fdd1a0082c71 / 60.0a1 / 20180312100129 / files
nightly mac
fdd1a0082c71 / 60.0a1 / 20180312100129 / files
nightly win32
fdd1a0082c71 / 60.0a1 / 20180312100129 / files
nightly win64
fdd1a0082c71 / 60.0a1 / 20180312100129 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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);
+    }
+  }
+}
+
+// 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)&