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 291206 8ab93deb75d746735e53dc603fb8aa026e73f75f
parent 291205 cce5b60332cdbbbd8e0876c0c16dbec046090f96
child 291207 3713e22cafec9aa6cf0c39d279d22eca355a84f8
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs1258972
milestone48.0a1
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');