Bug 1258972 - Move finish and playbackrate mochitest to web platform tests. r=birtles.
authorMantaroh Yoshinaga <mantaroh@gmail.com>
Thu, 31 Mar 2016 18:30:00 +0200
changeset 291147 8ab93deb75d746735e53dc603fb8aa026e73f75f
parent 291146 cce5b60332cdbbbd8e0876c0c16dbec046090f96
child 291148 3713e22cafec9aa6cf0c39d279d22eca355a84f8
push id74488
push usercbook@mozilla.com
push dateFri, 01 Apr 2016 07:52:11 +0000
treeherdermozilla-inbound@3713e22cafec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs1258972
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1258972 - Move finish and playbackrate mochitest to web platform tests. r=birtles.
dom/animation/test/css-animations/file_animation-finish.html
dom/animation/test/css-animations/file_animation-playbackrate.html
dom/animation/test/css-animations/test_animation-playbackrate.html
dom/animation/test/mochitest.ini
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/web-animations/animation/finish.html
testing/web-platform/tests/web-animations/animation/playbackRate.html
testing/web-platform/tests/web-animations/testcommon.js
--- a/dom/animation/test/css-animations/file_animation-finish.html
+++ b/dom/animation/test/css-animations/file_animation-finish.html
@@ -1,55 +1,28 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="../testcommon.js"></script>
 <style>
-
-.animated-div {
-  margin-left: 10px;
-}
-
 @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;
-  var animation = div.getAnimations()[0];
-
-  animation.playbackRate = 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 animation with playbackRate == 0');
-  }
-  assert_true(threw,
-              'Expect InvalidStateError exception trying to finish an ' +
-              'animation with playbackRate == 0');
-}, 'Test exceptions when finishing non-running animation');
-
-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;
@@ -57,77 +30,16 @@ test(function(t) {
                   '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');
 
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = ANIM_PROP_VAL;
-  var animation = div.getAnimations()[0];
-
-  animation.finish();
-  assert_equals(animation.currentTime, ANIM_DURATION,
-                'After finishing, the currentTime should be set to the end ' +
-                'of the active duration');
-}, 'Test finishing of animation');
-
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = ANIM_PROP_VAL;
-  var animation = div.getAnimations()[0];
-
-  animation.currentTime = ANIM_DURATION + 1000; // 1s past effect end
-
-  animation.finish();
-  assert_equals(animation.currentTime, ANIM_DURATION,
-                'After finishing, the currentTime should be set back to the ' +
-                'end of the active duration');
-}, 'Test finishing of animation with a current time past the effect end');
-
-async_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = ANIM_PROP_VAL;
-  var animation = div.getAnimations()[0];
-
-  animation.currentTime = ANIM_DURATION;
-
-  animation.finished.then(t.step_func(function() {
-    animation.playbackRate = -1;
-    animation.finish();
-    assert_equals(animation.currentTime, 0,
-                  'After finishing a reversed animation the currentTime ' +
-                  'should be set to zero');
-    t.done();
-  }));
-}, 'Test finishing of reversed animation');
-
-async_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = ANIM_PROP_VAL;
-  var animation = div.getAnimations()[0];
-
-  animation.currentTime = ANIM_DURATION;
-
-  animation.finished.then(t.step_func(function() {
-    animation.playbackRate = -1;
-
-    animation.currentTime = -1000;
-
-    animation.finish();
-    assert_equals(animation.currentTime, 0,
-                  'After finishing a reversed animation the currentTime ' +
-                  'should be set back to zero');
-    t.done();
-  }));
-}, 'Test finishing of reversed animation with a current time less than zero');
-
 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',
@@ -175,91 +87,11 @@ test(function(t) {
   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');
 
-test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = ANIM_PROP_VAL;
-  var animation = div.getAnimations()[0];
-
-  animation.playbackRate = 0.5;
-  animation.finish();
-
-  assert_equals(animation.playState, 'finished',
-                'The play state of a play-pending animation should become ' +
-                '"finished" after finish() is called');
-  assert_approx_equals(animation.startTime,
-                       animation.timeline.currentTime - ANIM_DURATION / 0.5,
-                       0.0001,
-                       'The start time of a play-pending animation should ' +
-                       'be set after calling finish()');
-}, 'Test finish() while play-pending');
-
-// FIXME: Add a test for when we are play-pending without an active timeline.
-// - In that case even after calling finish() we should still be pending but
-//   the current time should be updated
-
-async_test(function(t) {
-  var div = addDiv(t);
-  div.style.animation = ANIM_PROP_VAL;
-  var animation = div.getAnimations()[0];
-
-  animation.ready.then(t.step_func(function() {
-    // Trigger pause
-    animation.pause();
-    // Then abort
-    animation.play();
-
-    // We are now in the unusual situation of being play-pending whilst having
-    // a resolved start time. Check that finish() still triggers a transition
-    // to the finished state immediately.
-    animation.finish();
-    assert_equals(animation.playState, 'finished',
-                  'After aborting a pause then calling finish() the play ' +
-                  'state of an animation should become "finished" immediately');
-    t.done();
-  }));
-}, 'Test finish() during aborted pause');
-
-async_test(function(t) {
-  var div = addDiv(t, {'class': 'animated-div'});
-  div.style.animation = ANIM_PROP_VAL;
-  var animation = div.getAnimations()[0];
-
-  animation.ready.then(t.step_func(function() {
-    animation.finish();
-    var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
-    assert_equals(marginLeft, 10,
-                  'The computed style should be reset when finish() is ' +
-                  'called');
-    t.done();
-  }));
-}, 'Test resetting of computed style');
-
-async_test(function(t) {
-  var div = addDiv(t, {'class': 'animated-div'});
-  div.style.animation = ANIM_PROP_VAL;
-  var animation = div.getAnimations()[0];
-
-  var resolvedFinished = false;
-  animation.finished.then(function() {
-    resolvedFinished = true;
-  });
-
-  animation.ready.then(function() {
-    animation.finish();
-  }).then(t.step_func(function() {
-    assert_true(resolvedFinished,
-      'Animation.finished should be resolved soon after ' +
-      'Animation.finish()');
-    t.done();
-  }));
-
-}, 'Test finish() resolves finished promise synchronously');
-
 done();
 </script>
 </body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/file_animation-playbackrate.html
+++ /dev/null
@@ -1,105 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="../testcommon.js"></script>
-<style>
-div {
-  /* Make it easier to calculate expected values: */
-  animation-timing-function: linear ! important;
-}
-
-@keyframes anim {
-  from { margin-left: 100px; }
-  to { margin-left: 200px; }
-}
-</style>
-<body>
-<script>
-'use strict';
-
-function assert_playbackrate(animation,
-                             previousAnimationCurrentTime,
-                             previousTimelineCurrentTime,
-                             description) {
-  var accuracy = 0.001; /* accuracy of DOMHighResTimeStamp */
-
-  var animationCurrentTimeDifference =
-    animation.currentTime - previousAnimationCurrentTime;
-  var timelineCurrentTimeDifference =
-    animation.timeline.currentTime - previousTimelineCurrentTime;
-
-  assert_approx_equals(animationCurrentTimeDifference,
-                       timelineCurrentTimeDifference * animation.playbackRate,
-                       accuracy,
-                       description);
-}
-
-async_test(function(t) {
-  var div = addDiv(test, {'style': 'animation: anim 10s'});
-  var animation = div.getAnimations()[0];
-
-  animation.ready.then(t.step_func_done(function() {
-    animation.currentTime = 7000; // ms
-    animation.playbackRate = 0.5;
-
-    assert_equals(animation.currentTime, 7000,
-      'Reducing Animation.playbackRate should not change the currentTime ' +
-      'of a playing animation');
-
-    animation.playbackRate = 2;
-
-    assert_equals(animation.currentTime, 7000,
-      'Increasing Animation.playbackRate should not change the currentTime ' +
-      'of a playing animation');
-  }));
-}, 'Test the initial effect of setting playbackRate on currentTime');
-
-async_test(function(t) {
-  var div = addDiv(test, {'style': 'animation: anim 100s'});
-  var animation = div.getAnimations()[0];
-
-  animation.playbackRate = 2;
-
-  var previousTimelineCurrentTime;
-  var previousAnimationCurrentTime;
-
-  animation.ready.then(function() {
-    previousAnimationCurrentTime = animation.currentTime;
-    previousTimelineCurrentTime = animation.timeline.currentTime;
-    return waitForFrame();
-  }).then(t.step_func_done(function() {
-    assert_playbackrate(animation,
-      previousAnimationCurrentTime,
-      previousTimelineCurrentTime,
-      'animation.currentTime should be 10 times faster than timeline.');
-  }));
-}, 'Test the effect of setting playbackRate on currentTime');
-
-async_test(function(t) {
-  var div = addDiv(test, {'style': 'animation: anim 100s'});
-  var animation = div.getAnimations()[0];
-
-  animation.playbackRate = 2;
-
-  var previousTimelineCurrentTime;
-  var previousAnimationCurrentTime;
-
-  animation.ready.then(function() {
-    previousAnimationCurrentTime = animation.currentTime;
-    previousTimelineCurrentTime = animation.timeline.currentTime;
-
-    animation.playbackRate = 1;
-
-    return waitForFrame();
-  }).then(t.step_func_done(function() {
-    assert_equals(animation.playbackRate, 1,
-      'sanity check: animation.playbackRate is still 1.');
-    assert_playbackrate(animation,
-      previousAnimationCurrentTime,
-      previousTimelineCurrentTime,
-      'animation.currentTime should be the same speed as timeline now.');
-  }));
-}, 'Test the effect of setting playbackRate while playing animation');
-
-done();
-</script>
-</body>
deleted file mode 100644
--- a/dom/animation/test/css-animations/test_animation-playbackrate.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<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-playbackrate.html");
-  });
-</script>
-</html>
--- a/dom/animation/test/mochitest.ini
+++ b/dom/animation/test/mochitest.ini
@@ -22,18 +22,16 @@ support-files = css-animations/file_anim
 [css-animations/test_animation-oncancel.html]
 support-files = css-animations/file_animation-oncancel.html
 [css-animations/test_animation-onfinish.html]
 support-files = css-animations/file_animation-onfinish.html
 [css-animations/test_animation-pausing.html]
 support-files = css-animations/file_animation-pausing.html
 [css-animations/test_animation-play.html]
 support-files = css-animations/file_animation-play.html
-[css-animations/test_animation-playbackrate.html]
-support-files = css-animations/file_animation-playbackrate.html
 [css-animations/test_animation-playstate.html]
 support-files = css-animations/file_animation-playstate.html
 [css-animations/test_animation-ready.html]
 support-files = css-animations/file_animation-ready.html
 [css-animations/test_animation-reverse.html]
 support-files = css-animations/file_animation-reverse.html
 [css-animations/test_animation-starttime.html]
 support-files = css-animations/file_animation-starttime.html
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -28425,16 +28425,24 @@
         "path": "web-animations/animation-timeline/idlharness.html",
         "url": "/web-animations/animation-timeline/idlharness.html"
       },
       {
         "path": "web-animations/animation/constructor.html",
         "url": "/web-animations/animation/constructor.html"
       },
       {
+        "path": "web-animations/animation/finish.html",
+        "url": "/web-animations/animation/finish.html"
+      },
+      {
+        "path": "web-animations/animation/playbackRate.html",
+        "url": "/web-animations/animation/playbackRate.html"
+      },
+      {
         "path": "web-animations/keyframe-effect/constructor.html",
         "url": "/web-animations/keyframe-effect/constructor.html"
       },
       {
         "path": "web-animations/keyframe-effect/effect-easing.html",
         "url": "/web-animations/keyframe-effect/effect-easing.html"
       },
       {
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/web-animations/animation/finish.html
@@ -0,0 +1,210 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animation.finish()</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-finish">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+var gKeyFrames = { 'marginLeft': ['100px', '200px'] };
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.playbackRate = 0;
+
+  assert_throws({name: 'InvalidStateError'}, function() {
+    animation.finish();
+  });
+}, 'Test exceptions when finishing non-running animation');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames,
+                              {duration : 100 * MS_PER_SEC,
+                               iterations : Infinity});
+
+  assert_throws({name: 'InvalidStateError'}, function() {
+    animation.finish();
+  });
+}, 'Test exceptions when finishing infinite animation');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.finish();
+
+  assert_equals(animation.currentTime, 100 * MS_PER_SEC,
+                'After finishing, the currentTime should be set to the end ' +
+                'of the active duration');
+}, 'Test finishing of animation');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+   // 1s past effect end
+  animation.currentTime =
+    animation.effect.getComputedTiming().endTime + 1 * MS_PER_SEC;
+  animation.finish();
+
+  assert_equals(animation.currentTime, 100 * MS_PER_SEC,
+                'After finishing, the currentTime should be set back to the ' +
+                'end of the active duration');
+}, 'Test finishing of animation with a current time past the effect end');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.currentTime = 100 * MS_PER_SEC;
+  return animation.finished.then(function() {
+    animation.playbackRate = -1;
+    animation.finish();
+
+    assert_equals(animation.currentTime, 0,
+                  'After finishing a reversed animation the currentTime ' +
+                  'should be set to zero');
+  });
+}, 'Test finishing of reversed animation');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.currentTime = 100 * MS_PER_SEC;
+  return animation.finished.then(function() {
+    animation.playbackRate = -1;
+    animation.currentTime = -1000;
+    animation.finish();
+
+    assert_equals(animation.currentTime, 0,
+                  'After finishing a reversed animation the currentTime ' +
+                  'should be set back to zero');
+  });
+}, 'Test finishing of reversed animation with a current time less than zero');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.pause();
+  return animation.ready.then(function() {
+    animation.finish();
+
+    assert_equals(animation.playState, 'finished',
+                  'The play state of a paused animation should become ' +
+                  '"finished" after finish() is called');
+    assert_approx_equals(animation.startTime,
+                         animation.timeline.currentTime - 100 * MS_PER_SEC,
+                         0.0001,
+                         'The start time of a paused animation should be set ' +
+                         'after calling finish()');
+  });
+}, 'Test finish() while paused');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.pause();
+  // 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_approx_equals(animation.startTime,
+                       animation.timeline.currentTime - 100 * MS_PER_SEC / 2,
+                       0.0001,
+                       '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 = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.pause();
+  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');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.playbackRate = 0.5;
+  animation.finish();
+
+  assert_equals(animation.playState, 'finished',
+                'The play state of a play-pending animation should become ' +
+                '"finished" after finish() is called');
+  assert_approx_equals(animation.startTime,
+                       animation.timeline.currentTime - 100 * MS_PER_SEC / 0.5,
+                       0.0001,
+                       'The start time of a play-pending animation should ' +
+                       'be set after calling finish()');
+}, 'Test finish() while play-pending');
+
+// FIXME: Add a test for when we are play-pending without an active timeline.
+// - In that case even after calling finish() we should still be pending but
+//   the current time should be updated
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  return animation.ready.then(function() {
+    animation.pause();
+    animation.play();
+    // We are now in the unusual situation of being play-pending whilst having
+    // a resolved start time. Check that finish() still triggers a transition
+    // to the finished state immediately.
+    animation.finish();
+
+    assert_equals(animation.playState, 'finished',
+                  'After aborting a pause then calling finish() the play ' +
+                  'state of an animation should become "finished" immediately');
+  });
+}, 'Test finish() during aborted pause');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  div.style.marginLeft = '10px';
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  return animation.ready.then(function() {
+    animation.finish();
+    var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
+
+    assert_equals(marginLeft, 10,
+                  'The computed style should be reset when finish() is ' +
+                  'called');
+  });
+}, 'Test resetting of computed style');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  var resolvedFinished = false;
+  animation.finished.then(function() {
+    resolvedFinished = true;
+  });
+
+  return animation.ready.then(function() {
+    animation.finish();
+  }).then(function() {
+    assert_true(resolvedFinished,
+      'Animation.finished should be resolved soon after ' +
+      'Animation.finish()');
+  });
+}, 'Test finish() resolves finished promise synchronously');
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/web-animations/animation/playbackRate.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animation.playbackRate</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-playbackrate">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+"use strict";
+
+var keyFrames = { 'marginLeft': ['100px', '200px'] };
+
+function assert_playbackrate(animation,
+                             previousAnimationCurrentTime,
+                             previousTimelineCurrentTime,
+                             description) {
+  var accuracy = 0.001; /* accuracy of DOMHighResTimeStamp */
+  var animationCurrentTimeDifference =
+    animation.currentTime - previousAnimationCurrentTime;
+  var timelineCurrentTimeDifference =
+    animation.timeline.currentTime - previousTimelineCurrentTime;
+
+  assert_approx_equals(animationCurrentTimeDifference,
+                       timelineCurrentTimeDifference * animation.playbackRate,
+                       accuracy,
+                       description);
+}
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({keyFrames}, 100 * MS_PER_SEC);
+  return animation.ready.then(function() {
+    animation.currentTime = 7 * MS_PER_SEC; // ms
+    animation.playbackRate = 0.5;
+
+    assert_equals(animation.currentTime, 7 * MS_PER_SEC,
+      'Reducing Animation.playbackRate should not change the currentTime ' +
+      'of a playing animation');
+    animation.playbackRate = 2;
+    assert_equals(animation.currentTime, 7 * MS_PER_SEC,
+      'Increasing Animation.playbackRate should not change the currentTime ' +
+      'of a playing animation');
+  });
+}, 'Test the initial effect of setting playbackRate on currentTime');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({keyFrames}, 100 * MS_PER_SEC);
+  animation.playbackRate = 2;
+  var previousTimelineCurrentTime;
+  var previousAnimationCurrentTime;
+  return animation.ready.then(function() {
+    previousAnimationCurrentTime = animation.currentTime;
+    previousTimelineCurrentTime = animation.timeline.currentTime;
+    return waitForAnimationFrames(1);
+  }).then(function() {
+    assert_playbackrate(animation,
+      previousAnimationCurrentTime,
+      previousTimelineCurrentTime,
+      'animation.currentTime should be 2 times faster than timeline.');
+  });
+}, 'Test the effect of setting playbackRate on currentTime');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({keyFrames}, 100 * MS_PER_SEC);
+  animation.playbackRate = 2;
+  var previousTimelineCurrentTime;
+  var previousAnimationCurrentTime;
+  return animation.ready.then(function() {
+    previousAnimationCurrentTime = animation.currentTime;
+    previousTimelineCurrentTime = animation.timeline.currentTime;
+    animation.playbackRate = 1;
+    return waitForAnimationFrames(1);
+  }).then(function() {
+    assert_equals(animation.playbackRate, 1,
+      'sanity check: animation.playbackRate is still 1.');
+    assert_playbackrate(animation,
+      previousAnimationCurrentTime,
+      previousTimelineCurrentTime,
+      'animation.currentTime should be the same speed as timeline now.');
+  });
+}, 'Test the effect of setting playbackRate while playing animation');
+
+</script>
+</body>
--- a/testing/web-platform/tests/web-animations/testcommon.js
+++ b/testing/web-platform/tests/web-animations/testcommon.js
@@ -4,16 +4,17 @@ 3-clause BSD License [2]. To contribute 
 policies and contribution forms [3].
 
 [1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
 [2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
 [3] http://www.w3.org/2004/10/27-testcases
  */
 
 "use strict";
+var MS_PER_SEC = 1000;
 
 // creates div element, appends it to the document body and
 // removes the created element during test cleanup
 function createDiv(test, doc) {
   if (!doc) {
     doc = document;
   }
   var div = doc.createElement('div');