diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /testing/web-platform/tests/web-animations/interfaces/Animation | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'testing/web-platform/tests/web-animations/interfaces/Animation')
15 files changed, 1576 insertions, 0 deletions
diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/cancel.html b/testing/web-platform/tests/web-animations/interfaces/Animation/cancel.html new file mode 100644 index 000000000..f8f174abd --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/cancel.html @@ -0,0 +1,60 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.cancel()</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-cancel"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +'use strict'; + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({transform: ['translate(100px)', 'translate(100px)']}, + 100 * MS_PER_SEC); + return animation.ready.then(function() { + assert_not_equals(getComputedStyle(div).transform, 'none', + 'transform style is animated before cancelling'); + animation.cancel(); + assert_equals(getComputedStyle(div).transform, 'none', + 'transform style is no longer animated after cancelling'); + }); +}, 'Animated style is cleared after calling Animation.cancel()'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({marginLeft: ['100px', '200px']}, + 100 * MS_PER_SEC); + animation.effect.timing.easing = 'linear'; + animation.cancel(); + assert_equals(getComputedStyle(div).marginLeft, '0px', + 'margin-left style is not animated after cancelling'); + + animation.currentTime = 50 * MS_PER_SEC; + assert_equals(getComputedStyle(div).marginLeft, '150px', + 'margin-left style is updated when cancelled animation is' + + ' seeked'); +}, 'After cancelling an animation, it can still be seeked'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({marginLeft:['100px', '200px']}, + 100 * MS_PER_SEC); + return animation.ready.then(function() { + animation.cancel(); + assert_equals(getComputedStyle(div).marginLeft, '0px', + 'margin-left style is not animated after cancelling'); + animation.play(); + assert_equals(getComputedStyle(div).marginLeft, '100px', + 'margin-left style is animated after re-starting animation'); + return animation.ready; + }).then(function() { + assert_equals(animation.playState, 'running', + 'Animation succeeds in running after being re-started'); + }); +}, 'After cancelling an animation, it can still be re-used'); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/constructor.html b/testing/web-platform/tests/web-animations/interfaces/Animation/constructor.html new file mode 100644 index 000000000..4f76194b6 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/constructor.html @@ -0,0 +1,115 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation constructor tests</title> +<link rel="help" href="http://w3c.github.io/web-animations/#dom-animation-animation"> +<link rel="author" title="Hiroyuki Ikezoe" href="mailto:hiikezoe@mozilla-japan.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<div id="target"></div> +<script> +"use strict"; + +var gTarget = document.getElementById("target"); + +function createEffect() { + return new KeyframeEffectReadOnly(gTarget, { opacity: [0, 1] }); +} + +function createNull() { + return null; +} + +var gTestArguments = [ + { + createEffect: createNull, + timeline: null, + expectedTimeline: null, + expectedTimelineDescription: "null", + description: "with null effect and null timeline" + }, + { + createEffect: createNull, + timeline: document.timeline, + expectedTimeline: document.timeline, + expectedTimelineDescription: "document.timeline", + description: "with null effect and non-null timeline" + }, + { + createEffect: createNull, + expectedTimeline: document.timeline, + expectedTimelineDescription: "document.timeline", + description: "with null effect and no timeline parameter" + }, + { + createEffect: createEffect, + timeline: null, + expectedTimeline: null, + expectedTimelineDescription: "null", + description: "with non-null effect and null timeline" + }, + { + createEffect: createEffect, + timeline: document.timeline, + expectedTimeline: document.timeline, + expectedTimelineDescription: "document.timeline", + description: "with non-null effect and non-null timeline" + }, + { + createEffect: createEffect, + expectedTimeline: document.timeline, + expectedTimelineDescription: "document.timeline", + description: "with non-null effect and no timeline parameter" + }, +]; + +gTestArguments.forEach(function(args) { + test(function(t) { + var effect = args.createEffect(); + var animation = new Animation(effect, args.timeline); + + assert_not_equals(animation, null, + "An animation sohuld be created"); + assert_equals(animation.effect, effect, + "Animation returns the same effect passed to " + + "the Constructor"); + assert_equals(animation.timeline, args.expectedTimeline, + "Animation timeline should be " + args.expectedTimelineDescription); + assert_equals(animation.playState, "idle", + "Animation.playState should be initially 'idle'"); + }, "Animation can be constructed " + args.description); +}); + +test(function(t) { + var effect = new KeyframeEffectReadOnly(null, + { left: ["10px", "20px"] }, + { duration: 10000, + fill: "forwards" }); + var anim = new Animation(effect, document.timeline); + anim.pause(); + assert_equals(effect.getComputedTiming().progress, 0.0); + anim.currentTime += 5000; + assert_equals(effect.getComputedTiming().progress, 0.5); + anim.finish(); + assert_equals(effect.getComputedTiming().progress, 1.0); +}, "Animation constructed by an effect with null target runs normally"); + +async_test(function(t) { + var iframe = document.createElement('iframe'); + + iframe.addEventListener('load', t.step_func(function() { + var div = createDiv(t, iframe.contentDocument); + var effect = new KeyframeEffectReadOnly(div, null, 10000); + var anim = new Animation(effect); + assert_equals(anim.timeline, document.timeline); + iframe.remove(); + t.done(); + })); + + document.body.appendChild(iframe); +}, "Animation constructed with a keyframe that target element is in iframe"); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/effect.html b/testing/web-platform/tests/web-animations/interfaces/Animation/effect.html new file mode 100644 index 000000000..d881a96a7 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/effect.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.effect tests</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-effect"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +"use strict"; + +test(function(t) { + var anim = new Animation(); + assert_equals(anim.effect, null, "initial effect is null"); + + var newEffect = new KeyframeEffectReadOnly(createDiv(t), null); + anim.effect = newEffect; + assert_equals(anim.effect, newEffect, "new effect is set"); +}, "effect is set correctly."); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/finish.html b/testing/web-platform/tests/web-animations/interfaces/Animation/finish.html new file mode 100644 index 000000000..9b9c4c710 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/finish.html @@ -0,0 +1,246 @@ +<!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> +<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_times_equal(animation.startTime, + animation.timeline.currentTime - 100 * MS_PER_SEC, + '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_times_equal(animation.startTime, + animation.timeline.currentTime - 100 * MS_PER_SEC / 2, + 'The start time of a pause-pending animation should ' + + 'be set after calling finish()'); +}, 'Test finish() while pause-pending with positive playbackRate'); + +test(function(t) { + var div = 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_times_equal(animation.startTime, + animation.timeline.currentTime - 100 * MS_PER_SEC / 0.5, + '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'); + +promise_test(function(t) { + var effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC); + var animation = new Animation(effect, document.timeline); + 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 with an animation ' + + 'without a target'); + +promise_test(function(t) { + var effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC); + var animation = new Animation(effect, document.timeline); + animation.play(); + + var resolvedFinished = false; + animation.finished.then(function() { + resolvedFinished = true; + }); + + return animation.ready.then(function() { + animation.currentTime = animation.effect.getComputedTiming().endTime - 1; + return waitForAnimationFrames(2); + }).then(function() { + assert_true(resolvedFinished, + 'Animation.finished should be resolved soon after ' + + 'Animation finishes normally'); + }); +}, 'Test normally finished animation resolves finished promise synchronously ' + + 'with an animation without a target'); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/finished.html b/testing/web-platform/tests/web-animations/interfaces/Animation/finished.html new file mode 100644 index 000000000..d56de1b03 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/finished.html @@ -0,0 +1,370 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.finished</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-finished"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +"use strict"; + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var previousFinishedPromise = animation.finished; + return animation.ready.then(function() { + assert_equals(animation.finished, previousFinishedPromise, + 'Finished promise is the same object when playing starts'); + animation.pause(); + assert_equals(animation.finished, previousFinishedPromise, + 'Finished promise does not change when pausing'); + animation.play(); + assert_equals(animation.finished, previousFinishedPromise, + 'Finished promise does not change when play() unpauses'); + + animation.currentTime = 100 * MS_PER_SEC; + + return animation.finished; + }).then(function() { + assert_equals(animation.finished, previousFinishedPromise, + 'Finished promise is the same object when playing completes'); + }); +}, 'Test pausing then playing does not change the finished promise'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var previousFinishedPromise = animation.finished; + animation.finish(); + return animation.finished.then(function() { + assert_equals(animation.finished, previousFinishedPromise, + 'Finished promise is the same object when playing completes'); + animation.play(); + assert_not_equals(animation.finished, previousFinishedPromise, + 'Finished promise changes when replaying animation'); + + previousFinishedPromise = animation.finished; + animation.play(); + assert_equals(animation.finished, previousFinishedPromise, + 'Finished promise is the same after redundant play() call'); + + }); +}, 'Test restarting a finished animation'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var previousFinishedPromise; + animation.finish(); + return animation.finished.then(function() { + previousFinishedPromise = animation.finished; + animation.playbackRate = -1; + assert_not_equals(animation.finished, previousFinishedPromise, + 'Finished promise should be replaced when reversing a ' + + 'finished promise'); + animation.currentTime = 0; + return animation.finished; + }).then(function() { + previousFinishedPromise = animation.finished; + animation.play(); + assert_not_equals(animation.finished, previousFinishedPromise, + 'Finished promise is replaced after play() call on ' + + 'finished, reversed animation'); + }); +}, 'Test restarting a reversed finished animation'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var previousFinishedPromise = animation.finished; + animation.finish(); + return animation.finished.then(function() { + animation.currentTime = 100 * MS_PER_SEC + 1000; + assert_equals(animation.finished, previousFinishedPromise, + 'Finished promise is unchanged jumping past end of ' + + 'finished animation'); + }); +}, 'Test redundant finishing of animation'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + // Setup callback to run if finished promise is resolved + var finishPromiseResolved = false; + animation.finished.then(function() { + finishPromiseResolved = true; + }); + return animation.ready.then(function() { + // Jump to mid-way in interval and pause + animation.currentTime = 100 * MS_PER_SEC / 2; + animation.pause(); + return animation.ready; + }).then(function() { + // Jump to the end + // (But don't use finish() since that should unpause as well) + animation.currentTime = 100 * MS_PER_SEC; + return waitForAnimationFrames(2); + }).then(function() { + assert_false(finishPromiseResolved, + 'Finished promise should not resolve when paused'); + }); +}, 'Finished promise does not resolve when paused'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + // Setup callback to run if finished promise is resolved + var finishPromiseResolved = false; + animation.finished.then(function() { + finishPromiseResolved = true; + }); + return animation.ready.then(function() { + // Jump to mid-way in interval and pause + animation.currentTime = 100 * MS_PER_SEC / 2; + animation.pause(); + // Jump to the end + animation.currentTime = 100 * MS_PER_SEC; + return waitForAnimationFrames(2); + }).then(function() { + assert_false(finishPromiseResolved, + 'Finished promise should not resolve when pause-pending'); + }); +}, 'Finished promise does not resolve when pause-pending'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.finish(); + return animation.finished.then(function(resolvedAnimation) { + assert_equals(resolvedAnimation, animation, + 'Object identity of animation passed to Promise callback' + + ' matches the animation object owning the Promise'); + }); +}, 'The finished promise is fulfilled with its Animation'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var previousFinishedPromise = animation.finished; + + // Set up listeners on finished promise + var retPromise = animation.finished.then(function() { + assert_unreached('finished promise was fulfilled'); + }).catch(function(err) { + assert_equals(err.name, 'AbortError', + 'finished promise is rejected with AbortError'); + assert_not_equals(animation.finished, previousFinishedPromise, + 'Finished promise should change after the original is ' + + 'rejected'); + }); + + animation.cancel(); + + return retPromise; +}, 'finished promise is rejected when an animation is cancelled by calling ' + + 'cancel()'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var previousFinishedPromise = animation.finished; + animation.finish(); + return animation.finished.then(function() { + animation.cancel(); + assert_not_equals(animation.finished, previousFinishedPromise, + 'A new finished promise should be created when' + + ' cancelling a finished animation'); + }); +}, 'cancelling an already-finished animation replaces the finished promise'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.cancel(); + // The spec says we still create a new finished promise and reject the old + // one even if we're already idle. That behavior might change, but for now + // test that we do that. + var retPromise = animation.finished.catch(function(err) { + assert_equals(err.name, 'AbortError', + 'finished promise is rejected with AbortError'); + }); + + // Redundant call to cancel(); + var previousFinishedPromise = animation.finished; + animation.cancel(); + assert_not_equals(animation.finished, previousFinishedPromise, + 'A redundant call to cancel() should still generate a new' + + ' finished promise'); + return retPromise; +}, 'cancelling an idle animation still replaces the finished promise'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + const HALF_DUR = 100 * MS_PER_SEC / 2; + const QUARTER_DUR = 100 * MS_PER_SEC / 4; + var gotNextFrame = false; + var currentTimeBeforeShortening; + animation.currentTime = HALF_DUR; + return animation.ready.then(function() { + currentTimeBeforeShortening = animation.currentTime; + animation.effect.timing.duration = QUARTER_DUR; + // Below we use gotNextFrame to check that shortening of the animation + // duration causes the finished promise to resolve, rather than it just + // getting resolved on the next animation frame. This relies on the fact + // that the promises are resolved as a micro-task before the next frame + // happens. + waitForAnimationFrames(1).then(function() { + gotNextFrame = true; + }); + + return animation.finished; + }).then(function() { + assert_false(gotNextFrame, 'shortening of the animation duration should ' + + 'resolve the finished promise'); + assert_equals(animation.currentTime, currentTimeBeforeShortening, + 'currentTime should be unchanged when duration shortened'); + var previousFinishedPromise = animation.finished; + animation.effect.timing.duration = 100 * MS_PER_SEC; + assert_not_equals(animation.finished, previousFinishedPromise, + 'Finished promise should change after lengthening the ' + + 'duration causes the animation to become active'); + }); +}, 'Test finished promise changes for animation duration changes'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var retPromise = animation.ready.then(function() { + animation.playbackRate = 0; + animation.currentTime = 100 * MS_PER_SEC + 1000; + return waitForAnimationFrames(2); + }); + + animation.finished.then(t.step_func(function() { + assert_unreached('finished promise should not resolve when playbackRate ' + + 'is zero'); + })); + + return retPromise; +}, 'Test finished promise changes when playbackRate == 0'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + return animation.ready.then(function() { + animation.playbackRate = -1; + return animation.finished; + }); +}, 'Test finished promise resolves when reaching to the natural boundary.'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var previousFinishedPromise = animation.finished; + animation.finish(); + return animation.finished.then(function() { + animation.currentTime = 0; + assert_not_equals(animation.finished, previousFinishedPromise, + 'Finished promise should change once a prior ' + + 'finished promise resolved and the animation ' + + 'falls out finished state'); + }); +}, 'Test finished promise changes when a prior finished promise resolved ' + + 'and the animation falls out finished state'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var previousFinishedPromise = animation.finished; + animation.currentTime = 100 * MS_PER_SEC; + animation.currentTime = 100 * MS_PER_SEC / 2; + assert_equals(animation.finished, previousFinishedPromise, + 'No new finished promise generated when finished state ' + + 'is checked asynchronously'); +}, 'Test no new finished promise generated when finished state ' + + 'is checked asynchronously'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var previousFinishedPromise = animation.finished; + animation.finish(); + animation.currentTime = 100 * MS_PER_SEC / 2; + assert_not_equals(animation.finished, previousFinishedPromise, + 'New finished promise generated when finished state ' + + 'is checked synchronously'); +}, 'Test new finished promise generated when finished state ' + + 'is checked synchronously'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var resolvedFinished = false; + animation.finished.then(function() { + resolvedFinished = true; + }); + return animation.ready.then(function() { + animation.finish(); + animation.currentTime = 100 * MS_PER_SEC / 2; + }).then(function() { + assert_true(resolvedFinished, + 'Animation.finished should be resolved even if ' + + 'the finished state is changed soon'); + }); + +}, 'Test synchronous finished promise resolved even if finished state ' + + 'is changed soon'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var resolvedFinished = false; + animation.finished.then(function() { + resolvedFinished = true; + }); + + return animation.ready.then(function() { + animation.currentTime = 100 * MS_PER_SEC; + animation.finish(); + }).then(function() { + assert_true(resolvedFinished, + 'Animation.finished should be resolved soon after finish() is ' + + 'called even if there are other asynchronous promises just before it'); + }); +}, 'Test synchronous finished promise resolved even if asynchronous ' + + 'finished promise happens just before synchronous promise'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.finished.then(t.step_func(function() { + assert_unreached('Animation.finished should not be resolved'); + })); + + return animation.ready.then(function() { + animation.currentTime = 100 * MS_PER_SEC; + animation.currentTime = 100 * MS_PER_SEC / 2; + }); +}, 'Test finished promise is not resolved when the animation ' + + 'falls out finished state immediately'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + return animation.ready.then(function() { + animation.currentTime = 100 * MS_PER_SEC; + animation.finished.then(t.step_func(function() { + assert_unreached('Animation.finished should not be resolved'); + })); + animation.currentTime = 0; + }); + +}, 'Test finished promise is not resolved once the animation ' + + 'falls out finished state even though the current finished ' + + 'promise is generated soon after animation state became finished'); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/id.html b/testing/web-platform/tests/web-animations/interfaces/Animation/id.html new file mode 100644 index 000000000..2fadd5623 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/id.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.id</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-id"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +"use strict"; + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + assert_equals(animation.id, '', 'id for Animation is initially empty'); +}, 'Animation.id initial value'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.id = 'anim'; + + assert_equals(animation.id, 'anim', 'animation.id reflects the value set'); +}, 'Animation.id setter'); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/oncancel.html b/testing/web-platform/tests/web-animations/interfaces/Animation/oncancel.html new file mode 100644 index 000000000..b8d9ced61 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/oncancel.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.oncancel</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-oncancel"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +"use strict"; + +async_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var finishedTimelineTime; + animation.finished.then().catch(function() { + finishedTimelineTime = animation.timeline.currentTime; + }); + + animation.oncancel = t.step_func_done(function(event) { + assert_equals(event.currentTime, null, + 'event.currentTime should be null'); + assert_equals(event.timelineTime, finishedTimelineTime, + 'event.timelineTime should equal to the animation timeline ' + + 'when finished promise is rejected'); + }); + + animation.cancel(); +}, 'oncancel event is fired when animation.cancel() is called.'); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/onfinish.html b/testing/web-platform/tests/web-animations/interfaces/Animation/onfinish.html new file mode 100644 index 000000000..50e5bed6b --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/onfinish.html @@ -0,0 +1,121 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.onfinish</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-onfinish"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +"use strict"; + +async_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var finishedTimelineTime; + animation.finished.then(function() { + finishedTimelineTime = animation.timeline.currentTime; + }); + + animation.onfinish = t.step_func_done(function(event) { + assert_equals(event.currentTime, 0, + 'event.currentTime should be zero'); + assert_equals(event.timelineTime, finishedTimelineTime, + 'event.timelineTime should equal to the animation timeline ' + + 'when finished promise is resolved'); + }); + + animation.playbackRate = -1; +}, 'onfinish event is fired when the currentTime < 0 and ' + + 'the playbackRate < 0'); + +async_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + + var finishedTimelineTime; + animation.finished.then(function() { + finishedTimelineTime = animation.timeline.currentTime; + }); + + animation.onfinish = t.step_func_done(function(event) { + assert_equals(event.currentTime, 100 * MS_PER_SEC, + 'event.currentTime should be the effect end'); + assert_equals(event.timelineTime, finishedTimelineTime, + 'event.timelineTime should equal to the animation timeline ' + + 'when finished promise is resolved'); + }); + + animation.currentTime = 100 * MS_PER_SEC; +}, 'onfinish event is fired when the currentTime > 0 and ' + + 'the playbackRate > 0'); + +async_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + + var finishedTimelineTime; + animation.finished.then(function() { + finishedTimelineTime = animation.timeline.currentTime; + }); + + animation.onfinish = t.step_func_done(function(event) { + assert_equals(event.currentTime, 100 * MS_PER_SEC, + 'event.currentTime should be the effect end'); + assert_equals(event.timelineTime, finishedTimelineTime, + 'event.timelineTime should equal to the animation timeline ' + + 'when finished promise is resolved'); + }); + + animation.finish(); +}, 'onfinish event is fired when animation.finish() is called'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + + animation.onfinish = function(event) { + assert_unreached('onfinish event should not be fired'); + }; + + animation.currentTime = 100 * MS_PER_SEC / 2; + animation.pause(); + + return animation.ready.then(function() { + animation.currentTime = 100 * MS_PER_SEC; + return waitForAnimationFrames(2); + }); +}, 'onfinish event is not fired when paused'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.onfinish = function(event) { + assert_unreached('onfinish event should not be fired'); + }; + + return animation.ready.then(function() { + animation.playbackRate = 0; + animation.currentTime = 100 * MS_PER_SEC; + return waitForAnimationFrames(2); + }); +}, 'onfinish event is not fired when the playbackRate is zero'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.onfinish = function(event) { + assert_unreached('onfinish event should not be fired'); + }; + + return animation.ready.then(function() { + animation.currentTime = 100 * MS_PER_SEC; + animation.currentTime = 100 * MS_PER_SEC / 2; + return waitForAnimationFrames(2); + }); +}, 'onfinish event is not fired when the animation falls out ' + + 'finished state immediately'); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/pause.html b/testing/web-platform/tests/web-animations/interfaces/Animation/pause.html new file mode 100644 index 000000000..bcfaf4a9b --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/pause.html @@ -0,0 +1,98 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.pause()</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-pause"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +"use strict"; + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 1000 * MS_PER_SEC); + var previousCurrentTime = animation.currentTime; + + return animation.ready.then(waitForAnimationFrames(1)).then(function() { + assert_true(animation.currentTime >= previousCurrentTime, + 'currentTime is initially increasing'); + animation.pause(); + return animation.ready; + }).then(function() { + previousCurrentTime = animation.currentTime; + return waitForAnimationFrames(1); + }).then(function() { + assert_equals(animation.currentTime, previousCurrentTime, + 'currentTime does not increase after calling pause()'); + }); +}, 'pause() a running animation'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 1000 * MS_PER_SEC); + + // Go to idle state then pause + animation.cancel(); + animation.pause(); + + assert_equals(animation.currentTime, 0, 'currentTime is set to 0'); + assert_equals(animation.startTime, null, 'startTime is not set'); + assert_equals(animation.playState, 'pending', 'initially pause-pending'); + + // Check it still resolves as expected + return animation.ready.then(function() { + assert_equals(animation.playState, 'paused', + 'resolves to paused state asynchronously'); + assert_equals(animation.currentTime, 0, + 'keeps the initially set currentTime'); + }); +}, 'pause() from idle'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 1000 * MS_PER_SEC); + animation.cancel(); + animation.playbackRate = -1; + animation.pause(); + + assert_equals(animation.currentTime, 1000 * MS_PER_SEC, + 'currentTime is set to the effect end'); + + return animation.ready.then(function() { + assert_equals(animation.currentTime, 1000 * MS_PER_SEC, + 'keeps the initially set currentTime'); + }); +}, 'pause() from idle with a negative playbackRate'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, {duration: 1000 * MS_PER_SEC, + iterations: Infinity}); + animation.cancel(); + animation.playbackRate = -1; + + assert_throws('InvalidStateError', + function () { animation.pause(); }, + 'Expect InvalidStateError exception on calling pause() ' + + 'from idle with a negative playbackRate and ' + + 'infinite-duration animation'); +}, 'pause() from idle with a negative playbackRate and endless effect'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 1000 * MS_PER_SEC); + return animation.ready + .then(function(animation) { + animation.finish(); + animation.pause(); + return animation.ready; + }).then(function(animation) { + assert_equals(animation.currentTime, 1000 * MS_PER_SEC, + 'currentTime after pausing finished animation'); + }); +}, 'pause() on a finished animation'); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/play.html b/testing/web-platform/tests/web-animations/interfaces/Animation/play.html new file mode 100644 index 000000000..767d8df17 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/play.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.play()</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-play"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +'use strict'; + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({ transform: ['none', 'translate(10px)']}, + { duration : 100 * MS_PER_SEC, + iterations : Infinity}); + return animation.ready.then(function() { + // Seek to a time outside the active range so that play() will have to + // snap back to the start + animation.currentTime = -5 * MS_PER_SEC; + animation.playbackRate = -1; + + assert_throws('InvalidStateError', + function () { animation.play(); }, + 'Expected InvalidStateError exception on calling play() ' + + 'with a negative playbackRate and infinite-duration ' + + 'animation'); + }); +}, 'play() throws when seeking an infinite-duration animation played in ' + + 'reverse'); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/playState.html b/testing/web-platform/tests/web-animations/interfaces/Animation/playState.html new file mode 100644 index 000000000..15af526cd --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/playState.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.playState</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-playstate"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +'use strict'; + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + + assert_equals(animation.playState, 'pending'); + return animation.ready.then(function() { + assert_equals(animation.playState, 'running'); + }); +}, 'Animation.playState reports \'pending\'->\'running\' when initially ' + + 'played'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.pause(); + + assert_equals(animation.playState, 'pending'); + return animation.ready.then(function() { + assert_equals(animation.playState, 'paused'); + }); +}, 'Animation.playState reports \'pending\'->\'paused\' when pausing'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.cancel(); + assert_equals(animation.playState, 'idle'); +}, 'Animation.playState is \'idle\' when canceled.'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.cancel(); + animation.currentTime = 50 * MS_PER_SEC; + assert_equals(animation.playState, 'paused', + 'After seeking an idle animation, it is effectively paused'); +}, 'Animation.playState is \'paused\' after cancelling an animation, ' + + 'seeking it makes it paused'); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/playbackRate.html b/testing/web-platform/tests/web-animations/interfaces/Animation/playbackRate.html new file mode 100644 index 000000000..c923df6b4 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/playbackRate.html @@ -0,0 +1,86 @@ +<!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> +<body> +<div id="log"></div> +<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); +} + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate(null, 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(null, 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(null, 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> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/ready.html b/testing/web-platform/tests/web-animations/interfaces/Animation/ready.html new file mode 100644 index 000000000..815fe3da7 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/ready.html @@ -0,0 +1,96 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.ready</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-ready"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +"use strict"; + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + var originalReadyPromise = animation.ready; + var pauseReadyPromise; + + return animation.ready.then(function() { + assert_equals(animation.ready, originalReadyPromise, + 'Ready promise is the same object when playing completes'); + animation.pause(); + assert_not_equals(animation.ready, originalReadyPromise, + 'A new ready promise is created when pausing'); + pauseReadyPromise = animation.ready; + // Wait for the promise to fulfill since if we abort the pause the ready + // promise object is reused. + return animation.ready; + }).then(function() { + animation.play(); + assert_not_equals(animation.ready, pauseReadyPromise, + 'A new ready promise is created when playing'); + }); +}, 'A new ready promise is created when play()/pause() is called'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + + return animation.ready.then(function() { + var promiseBeforeCallingPlay = animation.ready; + animation.play(); + assert_equals(animation.ready, promiseBeforeCallingPlay, + 'Ready promise has same object identity after redundant call' + + ' to play()'); + }); +}, 'Redundant calls to play() do not generate new ready promise objects'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + + return animation.ready.then(function(resolvedAnimation) { + assert_equals(resolvedAnimation, animation, + 'Object identity of Animation passed to Promise callback' + + ' matches the Animation object owning the Promise'); + }); +}, 'The ready promise is fulfilled with its Animation'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + + var retPromise = animation.ready.then(function() { + assert_unreached('ready promise was fulfilled'); + }).catch(function(err) { + assert_equals(err.name, 'AbortError', + 'ready promise is rejected with AbortError'); + }); + + animation.cancel(); + + return retPromise; +}, 'ready promise is rejected when a pause-pending animation is cancelled by' + + ' calling cancel()'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + return animation.ready.then(function() { + animation.pause(); + // Set up listeners on pause-pending ready promise + var retPromise = animation.ready.then(function() { + assert_unreached('ready promise was fulfilled'); + }).catch(function(err) { + assert_equals(err.name, 'AbortError', + 'ready promise is rejected with AbortError'); + }); + animation.cancel(); + return retPromise; + }); +}, 'ready promise is rejected when a pause-pending animation is cancelled by' + + ' calling cancel()'); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/reverse.html b/testing/web-platform/tests/web-animations/interfaces/Animation/reverse.html new file mode 100644 index 000000000..555226111 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/reverse.html @@ -0,0 +1,158 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.reverse()</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-reverse"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +"use strict"; + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, {duration: 100 * MS_PER_SEC, + iterations: Infinity}); + + // Wait a frame because if currentTime is still 0 when we call + // reverse(), it will throw (per spec). + return animation.ready.then(waitForAnimationFrames(1)).then(function() { + assert_greater_than_equal(animation.currentTime, 0, + 'currentTime expected to be greater than 0, one frame after starting'); + animation.currentTime = 50 * MS_PER_SEC; + var previousPlaybackRate = animation.playbackRate; + animation.reverse(); + assert_equals(animation.playbackRate, -previousPlaybackRate, + 'playbackRate should be inverted'); + }); +}, 'reverse() inverts playbackRate'); + +promise_test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, {duration: 100 * MS_PER_SEC, + iterations: Infinity}); + animation.currentTime = 50 * MS_PER_SEC; + animation.pause(); + + return animation.ready.then(function() { + animation.reverse(); + return animation.ready; + }).then(function() { + assert_equals(animation.playState, 'running', + 'Animation.playState should be "running" after reverse()'); + }); +}, 'reverse() starts to play when pausing animation'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.currentTime = 50 * MS_PER_SEC; + animation.reverse(); + + assert_equals(animation.currentTime, 50 * MS_PER_SEC, + 'reverse() should not change the currentTime ' + + 'if the currentTime is in the middle of animation duration'); +}, 'reverse() maintains the same currentTime'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.currentTime = 200 * MS_PER_SEC; + animation.reverse(); + + assert_equals(animation.currentTime, 100 * MS_PER_SEC, + 'reverse() should start playing from the animation effect end ' + + 'if the playbackRate > 0 and the currentTime > effect end'); +}, 'reverse() when playbackRate > 0 and currentTime > effect end'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + + animation.currentTime = -200 * MS_PER_SEC; + animation.reverse(); + + assert_equals(animation.currentTime, 100 * MS_PER_SEC, + 'reverse() should start playing from the animation effect end ' + + 'if the playbackRate > 0 and the currentTime < 0'); +}, 'reverse() when playbackRate > 0 and currentTime < 0'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.playbackRate = -1; + animation.currentTime = -200 * MS_PER_SEC; + animation.reverse(); + + assert_equals(animation.currentTime, 0, + 'reverse() should start playing from the start of animation time ' + + 'if the playbackRate < 0 and the currentTime < 0'); +}, 'reverse() when playbackRate < 0 and currentTime < 0'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.playbackRate = -1; + animation.currentTime = 200 * MS_PER_SEC; + animation.reverse(); + + assert_equals(animation.currentTime, 0, + 'reverse() should start playing from the start of animation time ' + + 'if the playbackRate < 0 and the currentTime > effect end'); +}, 'reverse() when playbackRate < 0 and currentTime > effect end'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, {duration: 100 * MS_PER_SEC, + iterations: Infinity}); + animation.currentTime = -200 * MS_PER_SEC; + + assert_throws('InvalidStateError', + function () { animation.reverse(); }, + 'reverse() should throw InvalidStateError ' + + 'if the playbackRate > 0 and the currentTime < 0 ' + + 'and the target effect is positive infinity'); +}, 'reverse() when playbackRate > 0 and currentTime < 0 ' + + 'and the target effect end is positive infinity'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, {duration: 100 * MS_PER_SEC, + iterations: Infinity}); + animation.playbackRate = -1; + animation.currentTime = -200 * MS_PER_SEC; + animation.reverse(); + + assert_equals(animation.currentTime, 0, + 'reverse() should start playing from the start of animation time ' + + 'if the playbackRate < 0 and the currentTime < 0 ' + + 'and the target effect is positive infinity'); +}, 'reverse() when playbackRate < 0 and currentTime < 0 ' + + 'and the target effect end is positive infinity'); + +test(function(t) { + var div = createDiv(t); + var animation = div.animate({}, 100 * MS_PER_SEC); + animation.playbackRate = 0; + animation.currentTime = 50 * MS_PER_SEC; + animation.reverse(); + + assert_equals(animation.playbackRate, 0, + 'reverse() should preserve playbackRate if the playbackRate == 0'); + assert_equals(animation.currentTime, 50 * MS_PER_SEC, + 'reverse() should not affect the currentTime if the playbackRate == 0'); + t.done(); +}, 'reverse() when playbackRate == 0'); + +test(function(t) { + var div = createDiv(t); + var animation = + new Animation(new KeyframeEffect(div, null, 100 * MS_PER_SEC), null); + + assert_throws('InvalidStateError', function() { animation.reverse(); }); +}, 'Reversing an animation without an active timeline throws an ' + + 'InvalidStateError'); + +</script> +</body> diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/startTime.html b/testing/web-platform/tests/web-animations/interfaces/Animation/startTime.html new file mode 100644 index 000000000..6dfd7cf29 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/startTime.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.startTime tests</title> +<link rel="help" +href="https://w3c.github.io/web-animations/#dom-animation-starttime"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +'use strict'; + +test(function(t) { + var animation = new Animation(new KeyframeEffect(createDiv(t), null), + document.timeline); + assert_equals(animation.startTime, null, 'startTime is unresolved'); +}, 'startTime of a newly created (idle) animation is unresolved'); + +test(function(t) { + var animation = new Animation(new KeyframeEffect(createDiv(t), null), + document.timeline); + animation.play(); + assert_equals(animation.startTime, null, 'startTime is unresolved'); +}, 'startTime of a play-pending animation is unresolved'); + +test(function(t) { + var animation = new Animation(new KeyframeEffect(createDiv(t), null), + document.timeline); + animation.pause(); + assert_equals(animation.startTime, null, 'startTime is unresolved'); +}, 'startTime of a pause-pending animation is unresolved'); + +test(function(t) { + var animation = createDiv(t).animate(null); + assert_equals(animation.startTime, null, 'startTime is unresolved'); +}, 'startTime of a play-pending animation created using Element.animate' + + ' shortcut is unresolved'); + +promise_test(function(t) { + var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); + return animation.ready.then(function() { + assert_greater_than(animation.startTime, 0, 'startTime when running'); + }); +}, 'startTime is resolved when running'); + +test(function(t) { + var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); + animation.cancel(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, null); +}, 'startTime and currentTime are unresolved when animation is cancelled'); + +</script> +</body> |