Bug 1466031 - Update test_animation-starttime.html; r?hiro draft
authorBrian Birtles <birtles@gmail.com>
Mon, 04 Jun 2018 10:10:40 +0900
changeset 803425 0a0d0899e79227fd6924cd032b8f5932c397f57b
parent 803424 e5f7015f5ac37e363dd53d0b5e743d5dbdc2b743
child 803426 961861cb11f78c567c1653433561f08907719dba
push id112095
push userbmo:bbirtles@mozilla.com
push dateMon, 04 Jun 2018 01:13:47 +0000
reviewershiro
bugs1466031
milestone62.0a1
Bug 1466031 - Update test_animation-starttime.html; r?hiro This patch updates the tests in this file as follows: * startTime of a newly created (play-pending) animation is unresolved -> Covered by 'startTime of a play-pending animation is unresolved' in wpt/web-animations/interfaces/Animation/startTime.html However, it would be useful to have a test a new CSS animation is play-pending so I have extended the test in test_animation-playstate.html to cover this. * startTime of a newly created (pause-pending) animation is unresolved -> Covered by 'startTime of a pause-pending animation is unresolved' in wpt/web-animations/interfaces/Animation/startTime.html * startTime is resolved when running -> Covered by 'startTime is resolved when running' in wpt/web-animations/interfaces/Animation/startTime.html * startTime is unresolved when paused -> Moved to wpt/web-animations/timing-model/animations/pausing-an-animation.html * startTime while pause-pending and play-pending -> Moved to wpt/web-animations/timing-model/animations/pausing-an-animation.html * startTime while play-pending from finished state, startTime while play-pending from finished state using finish() -> Merged and moved to wpt/web-animations/timing-model/animations/playing-an-animation.html * Pausing should make the startTime become null -> Simplified and merged into the test for 'startTime is unresolved when paused' / 'Pausing clears the start time' test in wpt/web-animations/timing-model/animations/pausing-an-animation.html * Sanity test to check round-tripping assigning to a new animation's startTime -> Updated and left. * Skipping forward through animation -> This is really testing two things: (a) That you can seek a CSS animation using the start time. For this it makes sense to have a separate test that also checks that the computed style is updated (like we have for current time). (b) That seeking a CSS animation using the start time triggers dispatching events. This patch splits the above into two separate tests. * Skipping backwards through animation, Redundant change, before -> active, then back, Redundant change, before -> after, then back, Redundant change, active -> before, then back, Redundant change, active -> after, then back, Redundant change, after -> before, then back, Redundant change, after -> active, then back -> All these tests are really just exercising event dispatch which is already covered by test_event-dispatch.html. Provided we have a test that checks that events are dispatched when setting the startTime we don't need to test each combination again since we have tests for each of these combinations already when using the currentTime to seek and we can assume UAs are following the same code path at this point. As a result this patch drops these tests. * Setting startTime to null -> Covered by 'Setting an unresolved start time sets the hold time' in wpt/web-animations/timing-model/animations/setting-the-start-time-of-an-animation.html * Animation.startTime after pausing -> Covered by the new 'Pausing clears the start time' test in wpt/web-animations/timing-model/animations/pausing-an-animation.html * Animation.startTime after canceling -> Merged into wpt/web-animations/timing-model/animations/canceling-an-animation.html and made it follow the spec a little more closely (which requires clearing the start time and hold time). MozReview-Commit-ID: JwZ6PvsfYWn
dom/animation/test/css-animations/test_animation-playstate.html
dom/animation/test/css-animations/test_animation-starttime.html
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/web-animations/timing-model/animations/canceling-an-animation.html
testing/web-platform/tests/web-animations/timing-model/animations/pausing-an-animation.html
testing/web-platform/tests/web-animations/timing-model/animations/playing-an-animation.html
--- a/dom/animation/test/css-animations/test_animation-playstate.html
+++ b/dom/animation/test/css-animations/test_animation-playstate.html
@@ -8,20 +8,22 @@
 @keyframes anim { }
 </style>
 <body>
 <div id="log"></div>
 <script>
 'use strict';
 
 test(t => {
-  const div = addDiv(t, { 'style': 'animation: anim 1000s' });
+  const div = addDiv(t, { 'style': 'animation: anim 100s' });
   const animation = div.getAnimations()[0];
+  assert_true(animation.pending);
   assert_equals(animation.playState, 'running');
-}, 'Animation returns correct playState when running');
+  assert_equals(animation.startTime, null);
+}, 'A new CSS animation is initially play-pending');
 
 test(t => {
   const div = addDiv(t, { 'style': 'animation: anim 1000s paused' });
   const animation = div.getAnimations()[0];
   assert_equals(animation.playState, 'paused');
 }, 'Animation returns correct playState when paused');
 
 test(t => {
--- a/dom/animation/test/css-animations/test_animation-starttime.html
+++ b/dom/animation/test/css-animations/test_animation-starttime.html
@@ -11,353 +11,63 @@
   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">
+</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';
 
-// 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(t => {
-  const div = addDiv(t, { 'style': 'animation: anim 100s' });
-  const animation = div.getAnimations()[0];
-
-  assert_equals(animation.startTime, null, 'startTime is unresolved');
-}, 'startTime of a newly created (play-pending) animation is unresolved');
-
-test(t => {
-  const div = addDiv(t, { 'style': 'animation: anim 100s paused' });
-  const animation = div.getAnimations()[0];
-  assert_equals(animation.startTime, null, 'startTime is unresolved');
-}, 'startTime of a newly created (pause-pending) animation is unresolved');
-
-promise_test(async t => {
-  const div = addDiv(t, { 'style': 'animation: anim 100s' });
-  const animation = div.getAnimations()[0];
-
-  await animation.ready;
-
-  assert_true(animation.startTime > 0, 'startTime is resolved when running');
-}, 'startTime is resolved when running');
-
-promise_test(async t => {
-  const div = addDiv(t, { 'style': 'animation: anim 100s paused' });
-  const animation = div.getAnimations()[0];
-
-  await animation.ready;
-
-  assert_equals(animation.startTime, null,
-                'startTime is unresolved when paused');
-}, 'startTime is unresolved when paused');
-
-promise_test(async t => {
-  const div = addDiv(t, { 'style': 'animation: anim 100s' });
+  const div = addDiv(t, { 'class': 'animated-div' });
+  div.style.animation = 'anim 100s 100s';
   const animation = div.getAnimations()[0];
 
-  await animation.ready;
-
-  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');
+  const timelineTime = animation.timeline.currentTime;
+  animation.startTime = timelineTime;
 
-promise_test(async t => {
-  const div = addDiv(t, { 'style': 'animation: anim 100s' });
-  const animation = div.getAnimations()[0];
-  // Seek to end to put us in the finished state
-  animation.currentTime = 100 * MS_PER_SEC;
-
-  await animation.ready;
-
-  // 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(t => {
-  const div = addDiv(t, { 'style': 'animation: anim 100s' });
-  const 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()');
+  assert_times_equal(animation.startTime, timelineTime,
+    'Check setting of startTime actually works');
+}, 'The start time of a CSS animation can be set');
 
 promise_test(async t => {
-  const div = addDiv(t, { style: 'animation: anim 100s' });
+  const div = addDiv(t, { 'class': 'animated-div' });
+  div.style.animation = 'anim 100s 100s';
   const animation = div.getAnimations()[0];
 
-  assert_equals(animation.startTime, null, 'The initial startTime is null');
-  const initialTimelineTime = document.timeline.currentTime;
-
-  await animation.ready;
-
-  assert_true(animation.startTime > initialTimelineTime,
-              'After the animation has started, startTime is greater than ' +
-              'the time when it was started');
-  const 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;
+  // Seek to the half-way point
+  animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
 
-  assert_equals(animation.startTime, startTimeBeforePausing,
-                'The startTime does not change when pausing-pending');
-  await animation.ready;
-
-  assert_equals(animation.startTime, null,
-                'After actually pausing, the startTime of an animation ' +
-                'is null');
-}, 'Pausing should make the startTime become null');
-
-test(t => {
-  const div = addDiv(t, {'class': 'animated-div'});
-  div.style.animation = 'anim 100s 100s';
-  const animation = div.getAnimations()[0];
-  const 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');
+  assert_equals(getComputedStyle(div).marginLeft, '150px');
+}, 'The start time can be set to seek a CSS animation');
 
 promise_test(async t => {
-  const div = addDiv(t, {'class': 'animated-div'});
-  const eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
+  const div = addDiv(t, { class: 'animated-div' });
+  const eventWatcher = new EventWatcher(t, div, [
+    'animationstart',
+    'animationend',
+  ]);
   div.style.animation = 'anim 100s 100s';
   const animation = div.getAnimations()[0];
 
   await animation.ready;
 
-  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;
   await eventWatcher.wait_for('animationstart');
 
   animation.startTime = animation.timeline.currentTime - 200 * MS_PER_SEC;
   await eventWatcher.wait_for('animationend');
-}, 'Skipping forward through animation');
-
-promise_test(async t => {
-  const div = addDiv(t, {'class': 'animated-div'});
-  const eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
-  div.style.animation = 'anim 100s 100s';
-  const animation = div.getAnimations()[0];
-  animation.startTime = animation.timeline.currentTime - 200 * MS_PER_SEC;
-  const previousTimelineTime = animation.timeline.currentTime;
-
-  await eventWatcher.wait_for(['animationstart', 'animationend']);
-
-  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.
-  await eventWatcher.wait_for('animationstart');
-
-  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.
-  await eventWatcher.wait_for('animationend');
-
-  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(async t => {
-  const div = addDiv(t, {'class': 'animated-div'});
-  const eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
-  div.style.animation = "anim 100s 100s";
-  const animation = div.getAnimations()[0];
-
-  animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
-  animation.startTime = animation.timeline.currentTime - 50 * MS_PER_SEC;
-
-  await waitForAnimationFrames(2);
-}, 'Redundant change, before -> active, then back');
-
-promise_test(async t => {
-  const div = addDiv(t, {'class': 'animated-div'});
-  const eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
-  div.style.animation = "anim 100s 100s";
-  const animation = div.getAnimations()[0];
-
-  animation.startTime = animation.timeline.currentTime - 250 * MS_PER_SEC;
-  animation.startTime = animation.timeline.currentTime - 50 * MS_PER_SEC;
-
-  await waitForAnimationFrames(2);
-}, 'Redundant change, before -> after, then back');
-
-promise_test(async t => {
-  const div = addDiv(t, {'class': 'animated-div'});
-  const eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
-  div.style.animation = "anim 100s 100s";
-  const animation = div.getAnimations()[0];
-
-  // Get us into the initial state:
-  animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
-
-  eventWatcher.wait_for('animationstart');
-
-  animation.startTime = animation.timeline.currentTime - 50 * MS_PER_SEC;
-  animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
-
-  await waitForAnimationFrames(2);
-}, 'Redundant change, active -> before, then back');
+}, 'Seeking a CSS animation using the start time dispatches animation events');
 
-promise_test(async t => {
-  const div = addDiv(t, {'class': 'animated-div'});
-  const eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
-  div.style.animation = "anim 100s 100s";
-  const animation = div.getAnimations()[0];
-
-  // Get us into the initial state:
-  animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
-
-  eventWatcher.wait_for('animationstart');
-
-  animation.startTime = animation.timeline.currentTime - 250 * MS_PER_SEC;
-  animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
-
-  await waitForAnimationFrames(2);
-}, 'Redundant change, active -> after, then back');
-
-promise_test(async t => {
-  const div = addDiv(t, {'class': 'animated-div'});
-  const eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
-  div.style.animation = "anim 100s 100s";
-  const animation = div.getAnimations()[0];
-
-  // Get us into the initial state:
-  animation.startTime = animation.timeline.currentTime - 250 * MS_PER_SEC;
-
-  eventWatcher.wait_for(['animationstart', 'animationend']);
-
-  animation.startTime = animation.timeline.currentTime - 50 * MS_PER_SEC;
-  animation.startTime = animation.timeline.currentTime - 250 * MS_PER_SEC;
-
-  await waitForAnimationFrames(2);
-}, 'Redundant change, after -> before, then back');
-
-promise_test(async t => {
-  const div = addDiv(t, {'class': 'animated-div'});
-  const eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
-  div.style.animation = "anim 100s 100s";
-  const animation = div.getAnimations()[0];
-
-  // Get us into the initial state:
-  animation.startTime = animation.timeline.currentTime - 250 * MS_PER_SEC;
-
-  eventWatcher.wait_for(['animationstart', 'animationend']);
-
-  animation.startTime = animation.timeline.currentTime - 150 * MS_PER_SEC;
-  animation.startTime = animation.timeline.currentTime - 250 * MS_PER_SEC;
-
-  await waitForAnimationFrames(2);
-}, 'Redundant change, after -> active, then back');
-
-promise_test(async t => {
-  const div = addDiv(t, {'class': 'animated-div'});
-  div.style.animation = 'anim 100s 100s';
-  const animation = div.getAnimations()[0];
-  await animation.ready;
-
-  const storedCurrentTime = animation.currentTime;
-  animation.startTime = null;
-  await animation.ready;
-
-  assert_equals(animation.currentTime, storedCurrentTime,
-                'Test that hold time is correct');
-}, 'Setting startTime to null');
-
-promise_test(async t => {
-  const div = addDiv(t, {'class': 'animated-div'});
-  div.style.animation = 'anim 100s';
-  const animation = div.getAnimations()[0];
-
-  await animation.ready;
-  assert_not_equals(animation.startTime, null,
-    'Animation.startTime not null on ready Promise resolve');
-
-  animation.pause();
-  await animation.ready;
-
-  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(async t => {
-  const div = addDiv(t, {'class': 'animated-div'});
-  div.style.animation = 'anim 100s';
-  const animation = div.getAnimations()[0];
-  await animation.ready;
-
-  animation.cancel();
-  assert_equals(animation.startTime, null,
-                'The startTime of a canceled animation should be null');
-}, 'Animation.startTime after canceling');
-
-    </script>
-  </body>
+</script>
+</body>
 </html>
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -615876,33 +615876,33 @@
    "b8cc580e3e8d17961ffff4b693857f6c333dd57f",
    "testharness"
   ],
   "web-animations/timing-model/animation-effects/simple-iteration-progress.html": [
    "602fe7e6880e0b18329262699872c696f451d744",
    "testharness"
   ],
   "web-animations/timing-model/animations/canceling-an-animation.html": [
-   "cb9e7f8e950fad65783149d2c8014c567bf077a9",
+   "c2750f33d773b01a9ed5ac4bb8c9f65f7e78265a",
    "testharness"
   ],
   "web-animations/timing-model/animations/finishing-an-animation.html": [
    "afe654435332e798b3771b6ec6ca13bcca99e421",
    "testharness"
   ],
   "web-animations/timing-model/animations/pausing-an-animation.html": [
-   "27e4132548fc430fae19f3bab9cc8dc8c5a263ca",
+   "55acd5e4394d3c2543a00d90656a8134c497287b",
    "testharness"
   ],
   "web-animations/timing-model/animations/play-states.html": [
    "0ab2fa3a464001272d1af541ea769fa967490c3b",
    "testharness"
   ],
   "web-animations/timing-model/animations/playing-an-animation.html": [
-   "f6c36cc2370b08037e5a99009e6def67df84a4a7",
+   "1ef3259d06115d748ee92c143bdf07d9ce665224",
    "testharness"
   ],
   "web-animations/timing-model/animations/reversing-an-animation.html": [
    "053cc1287bd6dfc9688b4e1700a15bedc11bd92b",
    "testharness"
   ],
   "web-animations/timing-model/animations/seamlessly-updating-the-playback-rate-of-an-animation.html": [
    "a7e28aa0b40a39b00da257e347cb6ecf8d1d2882",
--- a/testing/web-platform/tests/web-animations/timing-model/animations/canceling-an-animation.html
+++ b/testing/web-platform/tests/web-animations/timing-model/animations/canceling-an-animation.html
@@ -10,19 +10,22 @@
 <div id="log"></div>
 <script>
 'use strict';
 
 test(t => {
   const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
   animation.cancel();
 
+  assert_equals(animation.startTime, null,
+                'The start time of a canceled animation should be unresolved');
   assert_equals(animation.currentTime, null,
-                'The current time of a canceled animation should be null');
-}, 'Canceling an animation should cause its current time to be unresolved');
+                'The hold time of a canceled animation should be unresolved');
+}, 'Canceling an animation should cause its start time and hold time to be'
+   + ' unresolved');
 
 promise_test(t => {
   const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
   const retPromise = animation.ready.then(() => {
     assert_unreached('ready promise was fulfilled');
   }).catch(err => {
     assert_equals(err.name, 'AbortError',
                   'ready promise is rejected with AbortError');
--- a/testing/web-platform/tests/web-animations/timing-model/animations/pausing-an-animation.html
+++ b/testing/web-platform/tests/web-animations/timing-model/animations/pausing-an-animation.html
@@ -8,16 +8,45 @@
 <script src="../../testcommon.js"></script>
 <body>
 <div id="log"></div>
 <script>
 'use strict';
 
 promise_test(async t => {
   const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+  await animation.ready;
+
+  const startTimeBeforePausing = animation.startTime;
+
+  animation.pause();
+  assert_equals(animation.startTime, startTimeBeforePausing,
+                'The start time does not change when pausing-pending');
+
+  await animation.ready;
+
+  assert_equals(animation.startTime, null,
+                'The start time is unresolved when paused');
+}, 'Pausing clears the start time');
+
+promise_test(async t => {
+  const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+  await animation.ready;
+
+  animation.pause();
+  assert_not_equals(animation.startTime, null,
+                    'The start time is resolved when pause-pending');
+
+  animation.play();
+  assert_not_equals(animation.startTime, null,
+                    'The start time is preserved when a pause is aborted');
+}, 'Aborting a pause preserves the start time');
+
+promise_test(async t => {
+  const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
   const promise = animation.ready;
   animation.pause();
 
   const promiseResult = await promise;
 
   assert_equals(promiseResult, animation);
   assert_equals(animation.ready, promise);
   assert_false(animation.pending, 'No longer pause-pending');
--- a/testing/web-platform/tests/web-animations/timing-model/animations/playing-an-animation.html
+++ b/testing/web-platform/tests/web-animations/timing-model/animations/playing-an-animation.html
@@ -48,16 +48,25 @@ promise_test(async t => {
   await animation.ready;
 
   assert_true(animation.currentTime < 100 * 1000,
               'After aborting a pause when finished, the current time should'
               + ' jump back to the start of the animation');
 }, 'Playing a pause-pending but previously finished animation seeks back to'
    + ' to the start');
 
+promise_test(async t => {
+  const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+  animation.finish();
+  await animation.ready;
+
+  animation.play();
+  assert_equals(animation.startTime, null, 'start time is unresolved');
+}, 'Playing a finished animation clears the start time');
+
 test(t => {
   const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
   animation.cancel();
   const promise = animation.ready;
   animation.play();
   assert_not_equals(animation.ready, promise);
 }, 'The ready promise should be replaced if the animation is not already'
    + ' pending');