| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 <!DOCTYPE html> | 
|  | 2 <meta charset=utf-8> | 
|  | 3 <title>Animation.finished</title> | 
|  | 4 <link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-finis
     hed"> | 
|  | 5 <script src="../../../../resources/testharness.js"></script> | 
|  | 6 <script src="../../../../resources/testharnessreport.js"></script> | 
|  | 7 <script src="../testcommon.js"></script> | 
|  | 8 <link rel="stylesheet" href="../../../../resources/testharness.css"> | 
|  | 9 <body> | 
|  | 10 <div id="log"></div> | 
|  | 11 <script> | 
|  | 12 "use strict"; | 
|  | 13 | 
|  | 14 promise_test(function(t) { | 
|  | 15   var div = createDiv(t); | 
|  | 16   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 17   var previousFinishedPromise = animation.finished; | 
|  | 18   return animation.ready.then(function() { | 
|  | 19     assert_equals(animation.finished, previousFinishedPromise, | 
|  | 20                   'Finished promise is the same object when playing starts'); | 
|  | 21     animation.pause(); | 
|  | 22     assert_equals(animation.finished, previousFinishedPromise, | 
|  | 23                   'Finished promise does not change when pausing'); | 
|  | 24     animation.play(); | 
|  | 25     assert_equals(animation.finished, previousFinishedPromise, | 
|  | 26                   'Finished promise does not change when play() unpauses'); | 
|  | 27 | 
|  | 28     animation.currentTime = 100 * MS_PER_SEC; | 
|  | 29 | 
|  | 30     return animation.finished; | 
|  | 31   }).then(function() { | 
|  | 32     assert_equals(animation.finished, previousFinishedPromise, | 
|  | 33                   'Finished promise is the same object when playing completes'); | 
|  | 34   }); | 
|  | 35 }, 'Test pausing then playing does not change the finished promise'); | 
|  | 36 | 
|  | 37 promise_test(function(t) { | 
|  | 38   var div = createDiv(t); | 
|  | 39   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 40   var previousFinishedPromise = animation.finished; | 
|  | 41   animation.finish(); | 
|  | 42   return animation.finished.then(function() { | 
|  | 43     assert_equals(animation.finished, previousFinishedPromise, | 
|  | 44                   'Finished promise is the same object when playing completes'); | 
|  | 45     animation.play(); | 
|  | 46     assert_not_equals(animation.finished, previousFinishedPromise, | 
|  | 47                   'Finished promise changes when replaying animation'); | 
|  | 48 | 
|  | 49     previousFinishedPromise = animation.finished; | 
|  | 50     animation.play(); | 
|  | 51     assert_equals(animation.finished, previousFinishedPromise, | 
|  | 52                   'Finished promise is the same after redundant play() call'); | 
|  | 53 | 
|  | 54   }); | 
|  | 55 }, 'Test restarting a finished animation'); | 
|  | 56 | 
|  | 57 promise_test(function(t) { | 
|  | 58   var div = createDiv(t); | 
|  | 59   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 60   var previousFinishedPromise; | 
|  | 61   animation.finish(); | 
|  | 62   return animation.finished.then(function() { | 
|  | 63     previousFinishedPromise = animation.finished; | 
|  | 64     animation.playbackRate = -1; | 
|  | 65     assert_not_equals(animation.finished, previousFinishedPromise, | 
|  | 66                       'Finished promise should be replaced when reversing a ' + | 
|  | 67                       'finished promise'); | 
|  | 68     animation.currentTime = 0; | 
|  | 69     return animation.finished; | 
|  | 70   }).then(function() { | 
|  | 71     previousFinishedPromise = animation.finished; | 
|  | 72     animation.play(); | 
|  | 73     assert_not_equals(animation.finished, previousFinishedPromise, | 
|  | 74                       'Finished promise is replaced after play() call on ' + | 
|  | 75                       'finished, reversed animation'); | 
|  | 76   }); | 
|  | 77 }, 'Test restarting a reversed finished animation'); | 
|  | 78 | 
|  | 79 promise_test(function(t) { | 
|  | 80   var div = createDiv(t); | 
|  | 81   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 82   var previousFinishedPromise = animation.finished; | 
|  | 83   animation.finish(); | 
|  | 84   return animation.finished.then(function() { | 
|  | 85     animation.currentTime = 100 * MS_PER_SEC + 1000; | 
|  | 86     assert_equals(animation.finished, previousFinishedPromise, | 
|  | 87                   'Finished promise is unchanged jumping past end of ' + | 
|  | 88                   'finished animation'); | 
|  | 89   }); | 
|  | 90 }, 'Test redundant finishing of animation'); | 
|  | 91 | 
|  | 92 promise_test(function(t) { | 
|  | 93   var div = createDiv(t); | 
|  | 94   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 95   // Setup callback to run if finished promise is resolved | 
|  | 96   var finishPromiseResolved = false; | 
|  | 97   animation.finished.then(function() { | 
|  | 98     finishPromiseResolved = true; | 
|  | 99   }); | 
|  | 100   return animation.ready.then(function() { | 
|  | 101     // Jump to mid-way in interval and pause | 
|  | 102     animation.currentTime = 100 * MS_PER_SEC / 2; | 
|  | 103     animation.pause(); | 
|  | 104     return animation.ready; | 
|  | 105   }).then(function() { | 
|  | 106     // Jump to the end | 
|  | 107     // (But don't use finish() since that should unpause as well) | 
|  | 108     animation.currentTime = 100 * MS_PER_SEC; | 
|  | 109     return waitForAnimationFrames(2); | 
|  | 110   }).then(function() { | 
|  | 111     assert_false(finishPromiseResolved, | 
|  | 112                  'Finished promise should not resolve when paused'); | 
|  | 113   }); | 
|  | 114 }, 'Finished promise does not resolve when paused'); | 
|  | 115 | 
|  | 116 promise_test(function(t) { | 
|  | 117   var div = createDiv(t); | 
|  | 118   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 119   // Setup callback to run if finished promise is resolved | 
|  | 120   var finishPromiseResolved = false; | 
|  | 121   animation.finished.then(function() { | 
|  | 122     finishPromiseResolved = true; | 
|  | 123   }); | 
|  | 124   return animation.ready.then(function() { | 
|  | 125     // Jump to mid-way in interval and pause | 
|  | 126     animation.currentTime = 100 * MS_PER_SEC / 2; | 
|  | 127     animation.pause(); | 
|  | 128     // Jump to the end | 
|  | 129     animation.currentTime = 100 * MS_PER_SEC; | 
|  | 130     return waitForAnimationFrames(2); | 
|  | 131   }).then(function() { | 
|  | 132     assert_false(finishPromiseResolved, | 
|  | 133                  'Finished promise should not resolve when pause-pending'); | 
|  | 134   }); | 
|  | 135 }, 'Finished promise does not resolve when pause-pending'); | 
|  | 136 | 
|  | 137 promise_test(function(t) { | 
|  | 138   var div = createDiv(t); | 
|  | 139   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 140   animation.finish(); | 
|  | 141   return animation.finished.then(function(resolvedAnimation) { | 
|  | 142     assert_equals(resolvedAnimation, animation, | 
|  | 143                   'Object identity of animation passed to Promise callback' | 
|  | 144                   + ' matches the animation object owning the Promise'); | 
|  | 145   }); | 
|  | 146 }, 'The finished promise is fulfilled with its Animation'); | 
|  | 147 | 
|  | 148 promise_test(function(t) { | 
|  | 149   var div = createDiv(t); | 
|  | 150   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 151   var previousFinishedPromise = animation.finished; | 
|  | 152 | 
|  | 153   // Set up listeners on finished promise | 
|  | 154   var retPromise = animation.finished.then(function() { | 
|  | 155     assert_unreached('finished promise was fulfilled'); | 
|  | 156   }).catch(function(err) { | 
|  | 157     assert_equals(err.name, 'AbortError', | 
|  | 158                   'finished promise is rejected with AbortError'); | 
|  | 159     assert_not_equals(animation.finished, previousFinishedPromise, | 
|  | 160                       'Finished promise should change after the original is ' + | 
|  | 161                       'rejected'); | 
|  | 162   }); | 
|  | 163 | 
|  | 164   animation.cancel(); | 
|  | 165 | 
|  | 166   return retPromise; | 
|  | 167 }, 'finished promise is rejected when an animation is cancelled by calling ' + | 
|  | 168    'cancel()'); | 
|  | 169 | 
|  | 170 promise_test(function(t) { | 
|  | 171   var div = createDiv(t); | 
|  | 172   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 173   var previousFinishedPromise = animation.finished; | 
|  | 174   animation.finish(); | 
|  | 175   return animation.finished.then(function() { | 
|  | 176     animation.cancel(); | 
|  | 177     assert_not_equals(animation.finished, previousFinishedPromise, | 
|  | 178                       'A new finished promise should be created when' | 
|  | 179                       + ' cancelling a finished animation'); | 
|  | 180   }); | 
|  | 181 }, 'cancelling an already-finished animation replaces the finished promise'); | 
|  | 182 | 
|  | 183 promise_test(function(t) { | 
|  | 184   var div = createDiv(t); | 
|  | 185   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 186   animation.cancel(); | 
|  | 187   // The spec says we still create a new finished promise and reject the old | 
|  | 188   // one even if we're already idle. That behavior might change, but for now | 
|  | 189   // test that we do that. | 
|  | 190   var retPromise = animation.finished.catch(function(err) { | 
|  | 191     assert_equals(err.name, 'AbortError', | 
|  | 192                   'finished promise is rejected with AbortError'); | 
|  | 193   }); | 
|  | 194 | 
|  | 195   // Redundant call to cancel(); | 
|  | 196   var previousFinishedPromise = animation.finished; | 
|  | 197   animation.cancel(); | 
|  | 198   assert_not_equals(animation.finished, previousFinishedPromise, | 
|  | 199                     'A redundant call to cancel() should still generate a new' | 
|  | 200                     + ' finished promise'); | 
|  | 201   return retPromise; | 
|  | 202 }, 'cancelling an idle animation still replaces the finished promise'); | 
|  | 203 | 
|  | 204 promise_test(function(t) { | 
|  | 205   var div = createDiv(t); | 
|  | 206   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 207   const HALF_DUR = 100 * MS_PER_SEC / 2; | 
|  | 208   const QUARTER_DUR = 100 * MS_PER_SEC / 4; | 
|  | 209   var gotNextFrame = false; | 
|  | 210   var currentTimeBeforeShortening; | 
|  | 211   animation.currentTime = HALF_DUR; | 
|  | 212   return animation.ready.then(function() { | 
|  | 213     currentTimeBeforeShortening = animation.currentTime; | 
|  | 214     animation.effect.timing.duration = QUARTER_DUR; | 
|  | 215     // Below we use gotNextFrame to check that shortening of the animation | 
|  | 216     // duration causes the finished promise to resolve, rather than it just | 
|  | 217     // getting resolved on the next animation frame. This relies on the fact | 
|  | 218     // that the promises are resolved as a micro-task before the next frame | 
|  | 219     // happens. | 
|  | 220     waitForAnimationFrames(1).then(function() { | 
|  | 221       gotNextFrame = true; | 
|  | 222     }); | 
|  | 223 | 
|  | 224     return animation.finished; | 
|  | 225   }).then(function() { | 
|  | 226     assert_false(gotNextFrame, 'shortening of the animation duration should ' + | 
|  | 227                                'resolve the finished promise'); | 
|  | 228     assert_equals(animation.currentTime, currentTimeBeforeShortening, | 
|  | 229                   'currentTime should be unchanged when duration shortened'); | 
|  | 230     var previousFinishedPromise = animation.finished; | 
|  | 231     animation.effect.timing.duration = 100 * MS_PER_SEC; | 
|  | 232     assert_not_equals(animation.finished, previousFinishedPromise, | 
|  | 233                       'Finished promise should change after lengthening the ' + | 
|  | 234                       'duration causes the animation to become active'); | 
|  | 235   }); | 
|  | 236 }, 'Test finished promise changes for animation duration changes'); | 
|  | 237 | 
|  | 238 promise_test(function(t) { | 
|  | 239   var div = createDiv(t); | 
|  | 240   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 241   var retPromise = animation.ready.then(function() { | 
|  | 242     animation.playbackRate = 0; | 
|  | 243     animation.currentTime = 100 * MS_PER_SEC + 1000; | 
|  | 244     return waitForAnimationFrames(2); | 
|  | 245   }); | 
|  | 246 | 
|  | 247   animation.finished.then(t.step_func(function() { | 
|  | 248     assert_unreached('finished promise should not resolve when playbackRate ' + | 
|  | 249                      'is zero'); | 
|  | 250   })); | 
|  | 251 | 
|  | 252   return retPromise; | 
|  | 253 }, 'Test finished promise changes when playbackRate == 0'); | 
|  | 254 | 
|  | 255 promise_test(function(t) { | 
|  | 256   var div = createDiv(t); | 
|  | 257   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 258   return animation.ready.then(function() { | 
|  | 259     animation.playbackRate = -1; | 
|  | 260     return animation.finished; | 
|  | 261   }); | 
|  | 262 }, 'Test finished promise resolves when reaching to the natural boundary.'); | 
|  | 263 | 
|  | 264 promise_test(function(t) { | 
|  | 265   var div = createDiv(t); | 
|  | 266   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 267   var previousFinishedPromise = animation.finished; | 
|  | 268   animation.finish(); | 
|  | 269   return animation.finished.then(function() { | 
|  | 270     animation.currentTime = 0; | 
|  | 271     assert_not_equals(animation.finished, previousFinishedPromise, | 
|  | 272                       'Finished promise should change once a prior ' + | 
|  | 273                       'finished promise resolved and the animation ' + | 
|  | 274                       'falls out finished state'); | 
|  | 275   }); | 
|  | 276 }, 'Test finished promise changes when a prior finished promise resolved ' + | 
|  | 277    'and the animation falls out finished state'); | 
|  | 278 | 
|  | 279 test(function(t) { | 
|  | 280   var div = createDiv(t); | 
|  | 281   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 282   var previousFinishedPromise = animation.finished; | 
|  | 283   animation.currentTime = 100 * MS_PER_SEC; | 
|  | 284   animation.currentTime = 100 * MS_PER_SEC / 2; | 
|  | 285   assert_equals(animation.finished, previousFinishedPromise, | 
|  | 286                 'No new finished promise generated when finished state ' + | 
|  | 287                 'is checked asynchronously'); | 
|  | 288 }, 'Test no new finished promise generated when finished state ' + | 
|  | 289    'is checked asynchronously'); | 
|  | 290 | 
|  | 291 test(function(t) { | 
|  | 292   var div = createDiv(t); | 
|  | 293   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 294   var previousFinishedPromise = animation.finished; | 
|  | 295   animation.finish(); | 
|  | 296   animation.currentTime = 100 * MS_PER_SEC / 2; | 
|  | 297   assert_not_equals(animation.finished, previousFinishedPromise, | 
|  | 298                     'New finished promise generated when finished state ' + | 
|  | 299                     'is checked synchronously'); | 
|  | 300 }, 'Test new finished promise generated when finished state ' + | 
|  | 301    'is checked synchronously'); | 
|  | 302 | 
|  | 303 promise_test(function(t) { | 
|  | 304   var div = createDiv(t); | 
|  | 305   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 306   var resolvedFinished = false; | 
|  | 307   animation.finished.then(function() { | 
|  | 308     resolvedFinished = true; | 
|  | 309   }); | 
|  | 310   return animation.ready.then(function() { | 
|  | 311     animation.finish(); | 
|  | 312     animation.currentTime = 100 * MS_PER_SEC / 2; | 
|  | 313   }).then(function() { | 
|  | 314     assert_true(resolvedFinished, | 
|  | 315       'Animation.finished should be resolved even if ' + | 
|  | 316       'the finished state is changed soon'); | 
|  | 317   }); | 
|  | 318 | 
|  | 319 }, 'Test synchronous finished promise resolved even if finished state ' + | 
|  | 320    'is changed soon'); | 
|  | 321 | 
|  | 322 promise_test(function(t) { | 
|  | 323   var div = createDiv(t); | 
|  | 324   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 325   var resolvedFinished = false; | 
|  | 326   animation.finished.then(function() { | 
|  | 327     resolvedFinished = true; | 
|  | 328   }); | 
|  | 329 | 
|  | 330   return animation.ready.then(function() { | 
|  | 331     animation.currentTime = 100 * MS_PER_SEC; | 
|  | 332     animation.finish(); | 
|  | 333   }).then(function() { | 
|  | 334     assert_true(resolvedFinished, | 
|  | 335       'Animation.finished should be resolved soon after finish() is ' + | 
|  | 336       'called even if there are other asynchronous promises just before it'); | 
|  | 337   }); | 
|  | 338 }, 'Test synchronous finished promise resolved even if asynchronous ' + | 
|  | 339    'finished promise happens just before synchronous promise'); | 
|  | 340 | 
|  | 341 promise_test(function(t) { | 
|  | 342   var div = createDiv(t); | 
|  | 343   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 344   animation.finished.then(t.step_func(function() { | 
|  | 345     assert_unreached('Animation.finished should not be resolved'); | 
|  | 346   })); | 
|  | 347 | 
|  | 348   return animation.ready.then(function() { | 
|  | 349     animation.currentTime = 100 * MS_PER_SEC; | 
|  | 350     animation.currentTime = 100 * MS_PER_SEC / 2; | 
|  | 351   }); | 
|  | 352 }, 'Test finished promise is not resolved when the animation ' + | 
|  | 353    'falls out finished state immediately'); | 
|  | 354 | 
|  | 355 promise_test(function(t) { | 
|  | 356   var div = createDiv(t); | 
|  | 357   var animation = div.animate({}, 100 * MS_PER_SEC); | 
|  | 358   return animation.ready.then(function() { | 
|  | 359     animation.currentTime = 100 * MS_PER_SEC; | 
|  | 360     animation.finished.then(t.step_func(function() { | 
|  | 361       assert_unreached('Animation.finished should not be resolved'); | 
|  | 362     })); | 
|  | 363     animation.currentTime = 0; | 
|  | 364   }); | 
|  | 365 | 
|  | 366 }, 'Test finished promise is not resolved once the animation ' + | 
|  | 367    'falls out finished state even though the current finished ' + | 
|  | 368    'promise is generated soon after animation state became finished'); | 
|  | 369 | 
|  | 370 </script> | 
|  | 371 </body> | 
| OLD | NEW | 
|---|