diff options
Diffstat (limited to 'dom/animation/test/css-transitions')
30 files changed, 2275 insertions, 0 deletions
diff --git a/dom/animation/test/css-transitions/file_animation-cancel.html b/dom/animation/test/css-transitions/file_animation-cancel.html new file mode 100644 index 000000000..6094b383f --- /dev/null +++ b/dom/animation/test/css-transitions/file_animation-cancel.html @@ -0,0 +1,165 @@ +<!doctype html> +<meta charset=utf-8> +<script src="../testcommon.js"></script> +<body> +<script> +'use strict'; + +promise_test(function(t) { + var div = addDiv(t, { style: 'margin-left: 0px' }); + flushComputedStyle(div); + + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '1000px'; + flushComputedStyle(div); + + var animation = div.getAnimations()[0]; + return animation.ready.then(waitForFrame).then(function() { + assert_not_equals(getComputedStyle(div).marginLeft, '1000px', + 'transform style is animated before cancelling'); + animation.cancel(); + assert_equals(getComputedStyle(div).marginLeft, div.style.marginLeft, + 'transform style is no longer animated after cancelling'); + }); +}, 'Animated style is cleared after cancelling a running CSS transition'); + +promise_test(function(t) { + var div = addDiv(t, { style: 'margin-left: 0px' }); + flushComputedStyle(div); + + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '1000px'; + flushComputedStyle(div); + + div.addEventListener('transitionend', function() { + assert_unreached('Got unexpected end event on cancelled transition'); + }); + + var animation = div.getAnimations()[0]; + return animation.ready.then(function() { + // Seek to just before the end then cancel + animation.currentTime = 99.9 * 1000; + animation.cancel(); + + // Then wait a couple of frames and check that no event was dispatched + return waitForAnimationFrames(2); + }); +}, 'Cancelled CSS transitions do not dispatch events'); + +promise_test(function(t) { + var div = addDiv(t, { style: 'margin-left: 0px' }); + flushComputedStyle(div); + + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '1000px'; + flushComputedStyle(div); + + var animation = div.getAnimations()[0]; + return animation.ready.then(function() { + animation.cancel(); + assert_equals(getComputedStyle(div).marginLeft, '1000px', + 'margin-left style is not animated after cancelling'); + animation.play(); + assert_equals(getComputedStyle(div).marginLeft, '0px', + 'margin-left style is animated after re-starting transition'); + return animation.ready; + }).then(function() { + assert_equals(animation.playState, 'running', + 'Transition succeeds in running after being re-started'); + }); +}, 'After cancelling a transition, it can still be re-used'); + +promise_test(function(t) { + var div = addDiv(t, { style: 'margin-left: 0px' }); + flushComputedStyle(div); + + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '1000px'; + flushComputedStyle(div); + + var animation = div.getAnimations()[0]; + return animation.ready.then(function() { + animation.finish(); + animation.cancel(); + assert_equals(getComputedStyle(div).marginLeft, '1000px', + 'margin-left style is not animated after cancelling'); + animation.play(); + assert_equals(getComputedStyle(div).marginLeft, '0px', + 'margin-left style is animated after re-starting transition'); + return animation.ready; + }).then(function() { + assert_equals(animation.playState, 'running', + 'Transition succeeds in running after being re-started'); + }); +}, 'After cancelling a finished transition, it can still be re-used'); + +test(function(t) { + var div = addDiv(t, { style: 'margin-left: 0px' }); + flushComputedStyle(div); + + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '1000px'; + flushComputedStyle(div); + + var animation = div.getAnimations()[0]; + animation.cancel(); + assert_equals(getComputedStyle(div).marginLeft, '1000px', + 'margin-left style is not animated after cancelling'); + + // Trigger a change to a transition property and check that this + // doesn't cause the animation to become live again + div.style.transitionDuration = '200s'; + flushComputedStyle(div); + assert_equals(getComputedStyle(div).marginLeft, '1000px', + 'margin-left style is still not animated after updating' + + ' transition-duration'); + assert_equals(animation.playState, 'idle', + 'Transition is still idle after updating transition-duration'); +}, 'After cancelling a transition, updating transition properties doesn\'t make' + + ' it live again'); + +promise_test(function(t) { + var div = addDiv(t, { style: 'margin-left: 0px' }); + flushComputedStyle(div); + + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '1000px'; + flushComputedStyle(div); + + var animation = div.getAnimations()[0]; + return animation.ready.then(function() { + assert_equals(animation.playState, 'running'); + div.style.display = 'none'; + return waitForFrame(); + }).then(function() { + assert_equals(animation.playState, 'idle'); + assert_equals(getComputedStyle(div).marginLeft, '1000px'); + }); +}, 'Setting display:none on an element cancels its transitions'); + +promise_test(function(t) { + var parentDiv = addDiv(t); + var childDiv = document.createElement('div'); + parentDiv.appendChild(childDiv); + childDiv.setAttribute('style', 'margin-left: 0px'); + + flushComputedStyle(childDiv); + + childDiv.style.transition = 'margin-left 100s'; + childDiv.style.marginLeft = '1000px'; + flushComputedStyle(childDiv); + + var animation = childDiv.getAnimations()[0]; + return animation.ready.then(function() { + assert_equals(animation.playState, 'running'); + parentDiv.style.display = 'none'; + return waitForFrame(); + }).then(function() { + assert_equals(animation.playState, 'idle'); + assert_equals(getComputedStyle(childDiv).marginLeft, '1000px'); + }); +}, 'Setting display:none cancels transitions on a child element'); + +done(); +</script> +</body> diff --git a/dom/animation/test/css-transitions/file_animation-computed-timing.html b/dom/animation/test/css-transitions/file_animation-computed-timing.html new file mode 100644 index 000000000..2dac82d75 --- /dev/null +++ b/dom/animation/test/css-transitions/file_animation-computed-timing.html @@ -0,0 +1,315 @@ +<!doctype html> +<meta charset=utf-8> +<script src="../testcommon.js"></script> +<style> + +.animated-div { + margin-left: 100px; +} + +</style> +<body> +<script> + +'use strict'; + +// -------------------- +// delay +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().delay, 0, + 'Initial value of delay'); +}, 'delay of a new tranisition'); + +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s 10s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().delay, 10000, + 'Initial value of delay'); +}, 'Positive delay of a new transition'); + +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s -5s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().delay, -5000, + 'Initial value of delay'); +}, 'Negative delay of a new transition'); + + +// -------------------- +// endDelay +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().endDelay, 0, + 'Initial value of endDelay'); +}, 'endDelay of a new transition'); + + +// -------------------- +// fill +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().fill, 'backwards', + 'Fill backwards'); +}, 'fill of a new transition'); + + +// -------------------- +// iterationStart +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().iterationStart, 0, + 'Initial value of iterationStart'); +}, 'iterationStart of a new transition'); + + +// -------------------- +// iterations +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().iterations, 1, + 'Initial value of iterations'); +}, 'iterations of a new transition'); + + +// -------------------- +// duration +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().duration, 10000, + 'Initial value of duration'); +}, 'duration of a new transition'); + + +// -------------------- +// direction +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().direction, 'normal', + 'Initial value of direction'); +}, 'direction of a new transition'); + + +// -------------------- +// easing +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().easing, 'linear', + 'Initial value of easing'); +}, 'easing of a new transition'); + + +// ------------------------------ +// endTime +// = max(start delay + active duration + end delay, 0) +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 100s -5s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + var answer = 100000 - 5000; // ms + assert_equals(effect.getComputedTiming().endTime, answer, + 'Initial value of endTime'); +}, 'endTime of a new transition'); + + +// -------------------- +// activeDuration +// = iteration duration * iteration count(==1) +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 100s -5s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().activeDuration, 100000, + 'Initial value of activeDuration'); +}, 'activeDuration of a new transition'); + + +// -------------------- +// localTime +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 100s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().localTime, 0, + 'Initial value of localTime'); +}, 'localTime of a new transition'); + +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 100s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var anim = div.getAnimations()[0]; + anim.currentTime = 5000; + assert_equals(anim.effect.getComputedTiming().localTime, anim.currentTime, + 'current localTime after setting currentTime'); +}, 'localTime is always equal to currentTime'); + +async_test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 100s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var anim = div.getAnimations()[0]; + anim.playbackRate = 2; // 2 times faster + + anim.ready.then(t.step_func(function() { + assert_equals(anim.effect.getComputedTiming().localTime, anim.currentTime, + 'localTime is equal to currentTime'); + return waitForFrame(); + })).then(t.step_func_done(function() { + assert_equals(anim.effect.getComputedTiming().localTime, anim.currentTime, + 'localTime is equal to currentTime'); + })); +}, 'localTime reflects playbackRate immediately'); + + +// -------------------- +// progress +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10.5s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().progress, 0.0, + 'Initial value of progress'); +}, 'progress of a new transition'); + +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10.5s 2s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().progress, 0.0, + 'Initial value of progress'); +}, 'progress of a new transition with positive delay in before phase'); + +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10.5s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var anim = div.getAnimations()[0]; + anim.finish() + assert_equals(anim.effect.getComputedTiming().progress, null, + 'finished progress'); +}, 'progress of a finished transition'); + + +// -------------------- +// currentIteration +// -------------------- +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().currentIteration, 0, + 'Initial value of currentIteration'); +}, 'currentIteration of a new transition'); + +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s 2s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var effect = div.getAnimations()[0].effect; + assert_equals(effect.getComputedTiming().currentIteration, 0, + 'Initial value of currentIteration'); +}, 'currentIteration of a new transition with positive delay in before phase'); + +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + div.style.transition = 'margin-left 10s'; + flushComputedStyle(div); + div.style.marginLeft = '10px'; + + var anim = div.getAnimations()[0]; + anim.finish(); + assert_equals(anim.effect.getComputedTiming().currentIteration, null, + 'finished currentIteration'); +}, 'currentIteration of a finished transition'); + +done(); +</script> +</body> diff --git a/dom/animation/test/css-transitions/file_animation-currenttime.html b/dom/animation/test/css-transitions/file_animation-currenttime.html new file mode 100644 index 000000000..2a0f105d2 --- /dev/null +++ b/dom/animation/test/css-transitions/file_animation-currenttime.html @@ -0,0 +1,307 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Tests for the effect of setting a CSS transition's + Animation.currentTime</title> + <style> + +.animated-div { + margin-left: 100px; + transition: margin-left 1000s linear 1000s; +} + + </style> + <script src="../testcommon.js"></script> + </head> + <body> + <script type="text/javascript"> + +'use strict'; + +// 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 ANIM_DELAY_MS = 1000000; // 1000s +const ANIM_DUR_MS = 1000000; // 1000s + +/** + * These helpers get the value that the currentTime needs to be set to, to put + * an animation that uses the above ANIM_DELAY_MS and ANIM_DUR_MS values into + * the middle of various phases or points through the active duration. + */ +function currentTimeForBeforePhase() { + return ANIM_DELAY_MS / 2; +} +function currentTimeForActivePhase() { + return ANIM_DELAY_MS + ANIM_DUR_MS / 2; +} +function currentTimeForAfterPhase() { + return ANIM_DELAY_MS + ANIM_DUR_MS + ANIM_DELAY_MS / 2; +} +function currentTimeForStartOfActiveInterval() { + return ANIM_DELAY_MS; +} +function currentTimeForFiftyPercentThroughActiveInterval() { + return ANIM_DELAY_MS + ANIM_DUR_MS * 0.5; +} +function currentTimeForEndOfActiveInterval() { + return ANIM_DELAY_MS + ANIM_DUR_MS; +} + + +// Expected computed 'margin-left' values at points during the active interval: +// When we assert_between_inclusive using these values we could in theory cause +// intermittent failure due to very long delays between paints, but since the +// active duration is 1000s long, a delay would need to be around 100s to cause +// that. If that's happening then there are likely other issues that should be +// fixed, so a failure to make us look into that seems like a good thing. +const INITIAL_POSITION = 100; +const TEN_PCT_POSITION = 110; +const FIFTY_PCT_POSITION = 150; +const END_POSITION = 200; + + +// The terms used for the naming of the following helper functions refer to +// terms used in the Web Animations specification for specific phases of an +// animation. The terms can be found here: +// +// http://w3c.github.io/web-animations/#animation-effect-phases-and-states + +// Called when currentTime is set to zero (the beginning of the start delay). +function checkStateOnSettingCurrentTimeToZero(animation) +{ + // We don't test animation.currentTime since our caller just set it. + + assert_equals(animation.playState, 'running', + 'Animation.playState should be "running" at the start of ' + + 'the start delay'); + + assert_equals(animation.effect.target.style.animationPlayState, 'running', + 'Animation.effect.target.style.animationPlayState should be ' + + '"running" at the start of the start delay'); + + var div = animation.effect.target; + var marginLeft = parseFloat(getComputedStyle(div).marginLeft); + assert_equals(marginLeft, UNANIMATED_POSITION, + 'the computed value of margin-left should be unaffected ' + + 'at the beginning of the start delay'); +} + +// Called when the ready Promise's callbacks should happen +function checkStateOnReadyPromiseResolved(animation) +{ + // the 0.0001 here is for rounding error + assert_less_than_equal(animation.currentTime, + animation.timeline.currentTime - animation.startTime + 0.0001, + 'Animation.currentTime should be less than the local time ' + + 'equivalent of the timeline\'s currentTime on the first paint tick ' + + 'after animation creation'); + + assert_equals(animation.playState, 'running', + 'Animation.playState should be "running" on the first paint ' + + 'tick after animation creation'); + + var div = animation.effect.target; + var marginLeft = parseFloat(getComputedStyle(div).marginLeft); + assert_equals(marginLeft, INITIAL_POSITION, + 'the computed value of margin-left should be unaffected ' + + 'by an animation with a delay on ready Promise resolve'); +} + +// Called when currentTime is set to the time the active interval starts. +function checkStateAtActiveIntervalStartTime(animation) +{ + // We don't test animation.currentTime since our caller just set it. + + assert_equals(animation.playState, 'running', + 'Animation.playState should be "running" at the start of ' + + 'the active interval'); + + var div = animation.effect.target; + var marginLeft = parseFloat(getComputedStyle(div).marginLeft); + assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION, + 'the computed value of margin-left should be close to the value at the ' + + 'beginning of the animation'); +} + +function checkStateAtFiftyPctOfActiveInterval(animation) +{ + // We don't test animation.currentTime since our caller just set it. + + var div = animation.effect.target; + var marginLeft = parseFloat(getComputedStyle(div).marginLeft); + assert_equals(marginLeft, FIFTY_PCT_POSITION, + 'the computed value of margin-left should be half way through the ' + + 'animation at the midpoint of the active interval'); +} + +// Called when currentTime is set to the time the active interval ends. +function checkStateAtActiveIntervalEndTime(animation) +{ + // We don't test animation.currentTime since our caller just set it. + + assert_equals(animation.playState, 'finished', + 'Animation.playState should be "finished" at the end of ' + + 'the active interval'); + + var div = animation.effect.target; + var marginLeft = parseFloat(getComputedStyle(div).marginLeft); + assert_equals(marginLeft, END_POSITION, + 'the computed value of margin-left should be the final transitioned-to ' + + 'value at the end of the active duration'); +} + +test(function(t) +{ + var div = addDiv(t, {'class': 'animated-div'}); + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + assert_equals(animation.currentTime, 0, 'currentTime should be zero'); +}, 'currentTime of a newly created transition is zero'); + + +test(function(t) +{ + var div = addDiv(t, {'class': 'animated-div'}); + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + + // So that animation is running instead of paused when we set currentTime: + animation.startTime = animation.timeline.currentTime; + + animation.currentTime = 10; + assert_equals(animation.currentTime, 10, + 'Check setting of currentTime actually works'); +}, 'Sanity test to check round-tripping assigning to new animation\'s ' + + 'currentTime'); + + +async_test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + var eventWatcher = new EventWatcher(t, div, 'transitionend'); + + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + + animation.ready.then(t.step_func(function() { + checkStateOnReadyPromiseResolved(animation); + + animation.currentTime = currentTimeForStartOfActiveInterval(); + checkStateAtActiveIntervalStartTime(animation); + + animation.currentTime = currentTimeForFiftyPercentThroughActiveInterval(); + checkStateAtFiftyPctOfActiveInterval(animation); + + animation.currentTime = currentTimeForEndOfActiveInterval(); + return eventWatcher.wait_for('transitionend'); + })).then(t.step_func(function() { + checkStateAtActiveIntervalEndTime(animation); + })).catch(t.step_func(function(reason) { + assert_unreached(reason); + })).then(function() { + t.done(); + }); +}, 'Skipping forward through transition'); + + +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + var eventWatcher = new EventWatcher(t, div, 'transitionend'); + + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + + // Unlike in the case of CSS animations, we cannot skip to the end and skip + // backwards since when we reach the end the transition effect is removed and + // changes to the Animation object no longer affect the element. For + // this reason we only skip forwards as far as the 50% through point. + + animation.ready.then(t.step_func(function() { + animation.currentTime = currentTimeForFiftyPercentThroughActiveInterval(); + checkStateAtFiftyPctOfActiveInterval(animation); + + animation.currentTime = currentTimeForStartOfActiveInterval(); + + // Despite going backwards from being in the active interval to being + // before it, we now expect a 'transitionend' event because the transition + // should go from being active to inactive. + // + // Calling checkStateAtActiveIntervalStartTime will check computed style, + // causing computed style to be updated and the 'transitionend' event to + // be dispatched synchronously. We need to call wait_for first + // otherwise eventWatcher will assert that the event was unexpected. + eventWatcher.wait_for('transitionend').then(function() { + t.done(); + }); + checkStateAtActiveIntervalStartTime(animation); + })); +}, 'Skipping backwards through transition'); + + +async_test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + + animation.ready.then(t.step_func(function() { + var exception; + try { + animation.currentTime = null; + } catch (e) { + exception = e; + } + assert_equals(exception.name, 'TypeError', + 'Expect TypeError exception on trying to set ' + + 'Animation.currentTime to null'); + })).catch(t.step_func(function(reason) { + assert_unreached(reason); + })).then(function() { + t.done(); + }); +}, 'Setting currentTime to null'); + + +async_test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + var pauseTime; + + animation.ready.then(t.step_func(function() { + assert_not_equals(animation.currentTime, null, + 'Animation.currentTime not null on ready Promise resolve'); + animation.pause(); + return animation.ready; + })).then(t.step_func(function() { + pauseTime = animation.currentTime; + return waitForFrame(); + })).then(t.step_func(function() { + assert_equals(animation.currentTime, pauseTime, + 'Animation.currentTime is unchanged after pausing'); + })).catch(t.step_func(function(reason) { + assert_unreached(reason); + })).then(function() { + t.done(); + }); +}, 'Animation.currentTime after pausing'); + +done(); + </script> + </body> +</html> diff --git a/dom/animation/test/css-transitions/file_animation-finished.html b/dom/animation/test/css-transitions/file_animation-finished.html new file mode 100644 index 000000000..2f6bcf47d --- /dev/null +++ b/dom/animation/test/css-transitions/file_animation-finished.html @@ -0,0 +1,61 @@ +<!doctype html> +<meta charset=utf-8> +<script src="../testcommon.js"></script> +<style> + +.animated-div { + margin-left: 100px; + transition: margin-left 1000s linear 1000s; +} + +</style> +<body> +<script> + +'use strict'; + +const ANIM_DELAY_MS = 1000000; // 1000s +const ANIM_DUR_MS = 1000000; // 1000s + +async_test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + + animation.finish(); + + animation.finished.then(t.step_func(function() { + animation.play(); + assert_equals(animation.currentTime, 0, + 'Replaying a finished transition should reset its ' + + 'currentTime'); + t.done(); + })); +}, 'Test restarting a finished transition'); + +async_test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + + animation.ready.then(function() { + animation.playbackRate = -1; + return animation.finished; + }).then(t.step_func(function() { + animation.play(); + // FIXME: once animation.effect.computedTiming.endTime is available (bug + // 1108055) we should use that here. + assert_equals(animation.currentTime, ANIM_DELAY_MS + ANIM_DUR_MS, + 'Replaying a finished reversed transition should reset ' + + 'its currentTime to the end of the effect'); + t.done(); + })); +}, 'Test restarting a reversed finished transition'); + +done(); +</script> +</body> diff --git a/dom/animation/test/css-transitions/file_animation-pausing.html b/dom/animation/test/css-transitions/file_animation-pausing.html new file mode 100644 index 000000000..b2f2d4618 --- /dev/null +++ b/dom/animation/test/css-transitions/file_animation-pausing.html @@ -0,0 +1,50 @@ +<!doctype html> +<meta charset=utf-8> +<script src="../testcommon.js"></script> +<body> +<script> +'use strict'; + +function getMarginLeft(cs) { + return parseFloat(cs.marginLeft); +} + +async_test(function(t) { + var div = addDiv(t); + var cs = window.getComputedStyle(div); + + div.style.marginLeft = '0px'; + cs.marginLeft; // Flush style to set up transition start point + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '10000px'; + cs.marginLeft; + + var animation = div.getAnimations()[0]; + assert_equals(getMarginLeft(cs), 0, + 'Initial value of margin-left is zero'); + var previousAnimVal = getMarginLeft(cs); + + animation.ready.then(waitForFrame).then(t.step_func(function() { + assert_true(getMarginLeft(cs) > previousAnimVal, + 'margin-left is initially increasing'); + animation.pause(); + return animation.ready; + })).then(t.step_func(function() { + previousAnimVal = getMarginLeft(cs); + return waitForFrame(); + })).then(t.step_func(function() { + assert_equals(getMarginLeft(cs), previousAnimVal, + 'margin-left does not increase after calling pause()'); + previousAnimVal = getMarginLeft(cs); + animation.play(); + return animation.ready.then(waitForFrame); + })).then(t.step_func(function() { + assert_true(getMarginLeft(cs) > previousAnimVal, + 'margin-left increases after calling play()'); + t.done(); + })); +}, 'pause() and play() a transition'); + +done(); +</script> +</body> diff --git a/dom/animation/test/css-transitions/file_animation-ready.html b/dom/animation/test/css-transitions/file_animation-ready.html new file mode 100644 index 000000000..f141da796 --- /dev/null +++ b/dom/animation/test/css-transitions/file_animation-ready.html @@ -0,0 +1,96 @@ +<!doctype html> +<meta charset=utf-8> +<script src="../testcommon.js"></script> +<body> +<script> +'use strict'; + +async_test(function(t) { + var div = addDiv(t); + div.style.transform = 'translate(0px)'; + window.getComputedStyle(div).transform; + div.style.transition = 'transform 100s'; + div.style.transform = 'translate(10px)'; + window.getComputedStyle(div).transform; + + var animation = div.getAnimations()[0]; + var originalReadyPromise = animation.ready; + + animation.ready.then(t.step_func(function() { + assert_equals(animation.ready, originalReadyPromise, + 'Ready promise is the same object when playing completes'); + animation.pause(); + assert_not_equals(animation.ready, originalReadyPromise, + 'Ready promise object identity differs when pausing'); + t.done(); + })); +}, 'A new ready promise is created each time play() is called' + + ' the animation property'); + +async_test(function(t) { + var div = addDiv(t); + + // Set up pending transition + div.style.transform = 'translate(0px)'; + window.getComputedStyle(div).transform; + div.style.transition = 'transform 100s'; + div.style.transform = 'translate(10px)'; + window.getComputedStyle(div).transform; + + var animation = div.getAnimations()[0]; + assert_equals(animation.playState, 'pending', 'Animation is initially pending'); + + // Set up listeners on ready promise + animation.ready.then(t.step_func(function() { + assert_unreached('ready promise was fulfilled'); + })).catch(t.step_func(function(err) { + assert_equals(err.name, 'AbortError', + 'ready promise is rejected with AbortError'); + assert_equals(animation.playState, 'idle', + 'Animation is idle after transition was cancelled'); + })).then(t.step_func(function() { + t.done(); + })); + + // Now remove transform from transition-property and flush styles + div.style.transitionProperty = 'none'; + window.getComputedStyle(div).transitionProperty; + +}, 'ready promise is rejected when a transition is cancelled by updating' + + ' transition-property'); + +async_test(function(t) { + var div = addDiv(t); + + // Set up pending transition + div.style.marginLeft = '0px'; + window.getComputedStyle(div).marginLeft; + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '100px'; + window.getComputedStyle(div).marginLeft; + + var animation = div.getAnimations()[0]; + assert_equals(animation.playState, 'pending', 'Animation is initially pending'); + + // Set up listeners on ready promise + animation.ready.then(t.step_func(function() { + assert_unreached('ready promise was fulfilled'); + })).catch(t.step_func(function(err) { + assert_equals(err.name, 'AbortError', + 'ready promise is rejected with AbortError'); + assert_equals(animation.playState, 'idle', + 'Animation is idle after transition was cancelled'); + })).then(t.step_func(function() { + t.done(); + })); + + // Now update the transition to animate to something not-interpolable + div.style.marginLeft = 'auto'; + window.getComputedStyle(div).marginLeft; + +}, 'ready promise is rejected when a transition is cancelled by changing' + + ' the transition property to something not interpolable'); + +done(); +</script> +</body> diff --git a/dom/animation/test/css-transitions/file_animation-starttime.html b/dom/animation/test/css-transitions/file_animation-starttime.html new file mode 100644 index 000000000..a156ba0a0 --- /dev/null +++ b/dom/animation/test/css-transitions/file_animation-starttime.html @@ -0,0 +1,284 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Tests for the effect of setting a CSS transition's + Animation.startTime</title> + <style> + +.animated-div { + margin-left: 100px; + transition: margin-left 1000s linear 1000s; +} + + </style> + <script src="../testcommon.js"></script> + </head> + <body> + <script type="text/javascript"> + +'use strict'; + +// 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 ANIM_DELAY_MS = 1000000; // 1000s +const ANIM_DUR_MS = 1000000; // 1000s + +/** + * These helpers get the value that the startTime needs to be set to, to put an + * animation that uses the above ANIM_DELAY_MS and ANIM_DUR_MS values into the + * middle of various phases or points through the active duration. + */ +function startTimeForBeforePhase(timeline) { + return timeline.currentTime - ANIM_DELAY_MS / 2; +} +function startTimeForActivePhase(timeline) { + return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS / 2; +} +function startTimeForAfterPhase(timeline) { + return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS - ANIM_DELAY_MS / 2; +} +function startTimeForStartOfActiveInterval(timeline) { + return timeline.currentTime - ANIM_DELAY_MS; +} +function startTimeForFiftyPercentThroughActiveInterval(timeline) { + return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS * 0.5; +} +function startTimeForEndOfActiveInterval(timeline) { + return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS; +} + + +// Expected computed 'margin-left' values at points during the active interval: +// When we assert_between_inclusive using these values we could in theory cause +// intermittent failure due to very long delays between paints, but since the +// active duration is 1000s long, a delay would need to be around 100s to cause +// that. If that's happening then there are likely other issues that should be +// fixed, so a failure to make us look into that seems like a good thing. +const INITIAL_POSITION = 100; +const TEN_PCT_POSITION = 110; +const FIFTY_PCT_POSITION = 150; +const END_POSITION = 200; + +// The terms used for the naming of the following helper functions refer to +// terms used in the Web Animations specification for specific phases of an +// animation. The terms can be found here: +// +// https://w3c.github.io/web-animations/#animation-effect-phases-and-states +// +// Note the distinction between the "animation start time" which occurs before +// the start delay and the start of the active interval which occurs after it. + +// Called when the ready Promise's callbacks should happen +function checkStateOnReadyPromiseResolved(animation) +{ + 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'); + + assert_equals(animation.playState, 'running', + 'Animation.playState should be "running" on the first paint ' + + 'tick after animation creation'); + + var div = animation.effect.target; + var marginLeft = parseFloat(getComputedStyle(div).marginLeft); + assert_equals(marginLeft, INITIAL_POSITION, + 'the computed value of margin-left should be unaffected ' + + 'by an animation with a delay on ready Promise resolve'); +} + +// Called when startTime is set to the time the active interval starts. +function checkStateAtActiveIntervalStartTime(animation) +{ + // We don't test animation.startTime since our caller just set it. + + assert_equals(animation.playState, 'running', + 'Animation.playState should be "running" at the start of ' + + 'the active interval'); + + var div = animation.effect.target; + var marginLeft = parseFloat(getComputedStyle(div).marginLeft); + assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION, + 'the computed value of margin-left should be close to the value at the ' + + 'beginning of the animation'); +} + +function checkStateAtFiftyPctOfActiveInterval(animation) +{ + // We don't test animation.startTime since our caller just set it. + + var div = animation.effect.target; + var marginLeft = parseFloat(getComputedStyle(div).marginLeft); + assert_equals(marginLeft, FIFTY_PCT_POSITION, + 'the computed value of margin-left should be half way through the ' + + 'animation at the midpoint of the active interval'); +} + +// Called when startTime is set to the time the active interval ends. +function checkStateAtActiveIntervalEndTime(animation) +{ + // We don't test animation.startTime since our caller just set it. + + assert_equals(animation.playState, 'finished', + 'Animation.playState should be "finished" at the end of ' + + 'the active interval'); + + var div = animation.effect.target; + var marginLeft = parseFloat(getComputedStyle(div).marginLeft); + assert_equals(marginLeft, END_POSITION, + 'the computed value of margin-left should be the final transitioned-to ' + + 'value at the end of the active duration'); +} + +test(function(t) +{ + var div = addDiv(t, {'class': 'animated-div'}); + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + assert_equals(animation.startTime, null, 'startTime is unresolved'); +}, 'startTime of a newly created transition is unresolved'); + + +test(function(t) +{ + var div = addDiv(t, {'class': 'animated-div'}); + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + var currentTime = animation.timeline.currentTime; + animation.startTime = currentTime; + assert_approx_equals(animation.startTime, currentTime, 0.0001, // rounding error + 'Check setting of startTime actually works'); +}, 'Sanity test to check round-tripping assigning to new animation\'s ' + + 'startTime'); + + +async_test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + var eventWatcher = new EventWatcher(t, div, 'transitionend'); + + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + + animation.ready.then(t.step_func(function() { + checkStateOnReadyPromiseResolved(animation); + + animation.startTime = startTimeForStartOfActiveInterval(animation.timeline); + checkStateAtActiveIntervalStartTime(animation); + + animation.startTime = + startTimeForFiftyPercentThroughActiveInterval(animation.timeline); + checkStateAtFiftyPctOfActiveInterval(animation); + + animation.startTime = startTimeForEndOfActiveInterval(animation.timeline); + return eventWatcher.wait_for('transitionend'); + })).then(t.step_func(function() { + checkStateAtActiveIntervalEndTime(animation); + })).catch(t.step_func(function(reason) { + assert_unreached(reason); + })).then(function() { + t.done(); + }); +}, 'Skipping forward through animation'); + + +test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + var eventWatcher = new EventWatcher(t, div, 'transitionend'); + + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + + // Unlike in the case of CSS animations, we cannot skip to the end and skip + // backwards since when we reach the end the transition effect is removed and + // changes to the Animation object no longer affect the element. For + // this reason we only skip forwards as far as the 90% through point. + + animation.startTime = + startTimeForFiftyPercentThroughActiveInterval(animation.timeline); + checkStateAtFiftyPctOfActiveInterval(animation); + + animation.startTime = startTimeForStartOfActiveInterval(animation.timeline); + + // Despite going backwards from being in the active interval to being before + // it, we now expect an 'animationend' event because the animation should go + // from being active to inactive. + // + // Calling checkStateAtActiveIntervalStartTime will check computed style, + // causing computed style to be updated and the 'transitionend' event to + // be dispatched synchronously. We need to call waitForEvent first + // otherwise eventWatcher will assert that the event was unexpected. + eventWatcher.wait_for('transitionend').then(function() { + t.done(); + }); + checkStateAtActiveIntervalStartTime(animation); +}, 'Skipping backwards through transition'); + + +async_test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + + var storedCurrentTime; + + animation.ready.then(t.step_func(function() { + storedCurrentTime = animation.currentTime; + animation.startTime = null; + return animation.ready; + })).catch(t.step_func(function(reason) { + assert_unreached(reason); + })).then(t.step_func(function() { + assert_equals(animation.currentTime, storedCurrentTime, + 'Test that hold time is correct'); + t.done(); + })); +}, 'Setting startTime to null'); + + +async_test(function(t) { + var div = addDiv(t, {'class': 'animated-div'}); + + flushComputedStyle(div); + div.style.marginLeft = '200px'; // initiate transition + + var animation = div.getAnimations()[0]; + + animation.ready.then(t.step_func(function() { + var savedStartTime = animation.startTime; + + assert_not_equals(animation.startTime, null, + 'Animation.startTime not null on ready Promise resolve'); + + animation.pause(); + return animation.ready; + })).then(t.step_func(function() { + assert_equals(animation.startTime, null, + 'Animation.startTime is null after paused'); + assert_equals(animation.playState, 'paused', + 'Animation.playState is "paused" after pause() call'); + })).catch(t.step_func(function(reason) { + assert_unreached(reason); + })).then(function() { + t.done(); + }); +}, 'Animation.startTime after paused'); + +done(); + </script> + </body> +</html> diff --git a/dom/animation/test/css-transitions/file_csstransition-events.html b/dom/animation/test/css-transitions/file_csstransition-events.html new file mode 100644 index 000000000..5011bc130 --- /dev/null +++ b/dom/animation/test/css-transitions/file_csstransition-events.html @@ -0,0 +1,223 @@ +<!doctype html> +<meta charset=utf-8> +<title>Tests for CSS-Transition events</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/#transition-events"> +<script src="../testcommon.js"></script> +<body> +<script> +'use strict'; + +/** + * Helper class to record the elapsedTime member of each event. + * The EventWatcher class in testharness.js allows us to wait on + * multiple events in a certain order but only records the event + * parameters of the most recent event. + */ +function TransitionEventHandler(target) { + this.target = target; + this.target.ontransitionrun = function(evt) { + this.transitionrun = evt.elapsedTime; + }.bind(this); + this.target.ontransitionstart = function(evt) { + this.transitionstart = evt.elapsedTime; + }.bind(this); + this.target.ontransitionend = function(evt) { + this.transitionend = evt.elapsedTime; + }.bind(this); +} + +TransitionEventHandler.prototype.clear = function() { + this.transitionrun = undefined; + this.transitionstart = undefined; + this.transitionend = undefined; +}; + +function setupTransition(t, transitionStyle) { + var div, watcher, handler, transition; + transitionStyle = transitionStyle || 'transition: margin-left 100s 100s'; + div = addDiv(t, { style: transitionStyle }); + watcher = new EventWatcher(t, div, [ 'transitionrun', + 'transitionstart', + 'transitionend' ]); + handler = new TransitionEventHandler(div); + flushComputedStyle(div); + + div.style.marginLeft = '100px'; + flushComputedStyle(div); + + transition = div.getAnimations()[0]; + + return [transition, watcher, handler]; +} + +// On the next frame (i.e. when events are queued), whether or not the +// transition is still pending depends on the implementation. +promise_test(function(t) { + var [transition, watcher, handler] = setupTransition(t); + return watcher.wait_for('transitionrun').then(function(evt) { + assert_equals(evt.elapsedTime, 0.0); + }); +}, 'Idle -> Pending or Before'); + +promise_test(function(t) { + var [transition, watcher, handler] = setupTransition(t); + // Force the transition to leave the idle phase + transition.startTime = document.timeline.currentTime; + return watcher.wait_for('transitionrun').then(function(evt) { + assert_equals(evt.elapsedTime, 0.0); + }); +}, 'Idle -> Before'); + +promise_test(function(t) { + var [transition, watcher, handler] = setupTransition(t); + // Seek to Active phase. + transition.currentTime = 100 * MS_PER_SEC; + transition.pause(); + return watcher.wait_for([ 'transitionrun', + 'transitionstart' ]).then(function(evt) { + assert_equals(handler.transitionrun, 0.0); + assert_equals(handler.transitionstart, 0.0); + }); +}, 'Idle or Pending -> Active'); + +promise_test(function(t) { + var [transition, watcher, handler] = setupTransition(t); + // Seek to After phase. + transition.finish(); + return watcher.wait_for([ 'transitionrun', + 'transitionstart', + 'transitionend' ]).then(function(evt) { + assert_equals(handler.transitionrun, 0.0); + assert_equals(handler.transitionstart, 0.0); + assert_equals(handler.transitionend, 100.0); + }); +}, 'Idle or Pending -> After'); + +promise_test(function(t) { + var [transition, watcher, handler] = setupTransition(t); + + return Promise.all([ watcher.wait_for('transitionrun'), + transition.ready ]).then(function() { + transition.currentTime = 100 * MS_PER_SEC; + return watcher.wait_for('transitionstart'); + }).then(function() { + assert_equals(handler.transitionstart, 0.0); + }); +}, 'Before -> Active'); + +promise_test(function(t) { + var [transition, watcher, handler] = setupTransition(t); + return Promise.all([ watcher.wait_for('transitionrun'), + transition.ready ]).then(function() { + // Seek to After phase. + transition.currentTime = 200 * MS_PER_SEC; + return watcher.wait_for([ 'transitionstart', 'transitionend' ]); + }).then(function(evt) { + assert_equals(handler.transitionstart, 0.0); + assert_equals(handler.transitionend, 100.0); + }); +}, 'Before -> After'); + +promise_test(function(t) { + var [transition, watcher, handler] = setupTransition(t); + // Seek to Active phase. + transition.currentTime = 100 * MS_PER_SEC; + return watcher.wait_for([ 'transitionrun', + 'transitionstart' ]).then(function(evt) { + // Seek to Before phase. + transition.currentTime = 0; + return watcher.wait_for('transitionend'); + }).then(function(evt) { + assert_equals(evt.elapsedTime, 0.0); + }); +}, 'Active -> Before'); + +promise_test(function(t) { + var [transition, watcher, handler] = setupTransition(t); + // Seek to Active phase. + transition.currentTime = 100 * MS_PER_SEC; + return watcher.wait_for([ 'transitionrun', + 'transitionstart' ]).then(function(evt) { + // Seek to After phase. + transition.currentTime = 200 * MS_PER_SEC; + return watcher.wait_for('transitionend'); + }).then(function(evt) { + assert_equals(evt.elapsedTime, 100.0); + }); +}, 'Active -> After'); + +promise_test(function(t) { + var [transition, watcher, handler] = setupTransition(t); + // Seek to After phase. + transition.finish(); + return watcher.wait_for([ 'transitionrun', + 'transitionstart', + 'transitionend' ]).then(function(evt) { + // Seek to Before phase. + transition.currentTime = 0; + return watcher.wait_for([ 'transitionstart', 'transitionend' ]); + }).then(function(evt) { + assert_equals(handler.transitionstart, 100.0); + assert_equals(handler.transitionend, 0.0); + }); +}, 'After -> Before'); + +promise_test(function(t) { + var [transition, watcher, handler] = setupTransition(t); + // Seek to After phase. + transition.finish(); + return watcher.wait_for([ 'transitionrun', + 'transitionstart', + 'transitionend' ]).then(function(evt) { + // Seek to Active phase. + transition.currentTime = 100 * MS_PER_SEC; + return watcher.wait_for('transitionstart'); + }).then(function(evt) { + assert_equals(evt.elapsedTime, 100.0); + }); +}, 'After -> Active'); + +promise_test(function(t) { + var [transition, watcher, handler] = + setupTransition(t, 'transition: margin-left 100s -50s'); + + return watcher.wait_for([ 'transitionrun', + 'transitionstart' ]).then(function() { + assert_equals(handler.transitionrun, 50.0); + assert_equals(handler.transitionstart, 50.0); + transition.finish(); + return watcher.wait_for('transitionend'); + }).then(function(evt) { + assert_equals(evt.elapsedTime, 100.0); + }); +}, 'Calculating the interval start and end time with negative start delay.'); + +promise_test(function(t) { + var [transition, watcher, handler] = setupTransition(t); + + return watcher.wait_for('transitionrun').then(function(evt) { + // We can't set the end delay via generated effect timing. + // Because CSS-Transition use the AnimationEffectTimingReadOnly. + transition.effect = new KeyframeEffect(handler.target, + { marginleft: [ '0px', '100px' ]}, + { duration: 100 * MS_PER_SEC, + endDelay: -50 * MS_PER_SEC }); + // Seek to Before and play. + transition.cancel(); + transition.play(); + return watcher.wait_for('transitionstart'); + }).then(function() { + assert_equals(handler.transitionstart, 0.0); + + // Seek to After phase. + transition.finish(); + return watcher.wait_for('transitionend'); + }).then(function(evt) { + assert_equals(evt.elapsedTime, 50.0); + }); +}, 'Calculating the interval start and end time with negative end delay.'); + +done(); +</script> +</body> +</html> diff --git a/dom/animation/test/css-transitions/file_csstransition-transitionproperty.html b/dom/animation/test/css-transitions/file_csstransition-transitionproperty.html new file mode 100644 index 000000000..176cc5a4d --- /dev/null +++ b/dom/animation/test/css-transitions/file_csstransition-transitionproperty.html @@ -0,0 +1,24 @@ +<!doctype html> +<meta charset=utf-8> +<script src="../testcommon.js"></script> +<body> +<script> +'use strict'; + +test(function(t) { + var div = addDiv(t); + + // Add a transition + div.style.left = '0px'; + window.getComputedStyle(div).transitionProperty; + div.style.transition = 'all 100s'; + div.style.left = '100px'; + + assert_equals(div.getAnimations()[0].transitionProperty, 'left', + 'The transitionProperty for the corresponds to the specific ' + + 'property being transitioned'); +}, 'CSSTransition.transitionProperty'); + +done(); +</script> +</body> diff --git a/dom/animation/test/css-transitions/file_document-get-animations.html b/dom/animation/test/css-transitions/file_document-get-animations.html new file mode 100644 index 000000000..a5d55b76c --- /dev/null +++ b/dom/animation/test/css-transitions/file_document-get-animations.html @@ -0,0 +1,93 @@ +<!doctype html> +<meta charset=utf-8> +<script src="../testcommon.js"></script> +<body> +<script> +'use strict'; + +test(function(t) { + assert_equals(document.getAnimations().length, 0, + 'getAnimations returns an empty sequence for a document' + + ' with no animations'); +}, 'getAnimations for non-animated content'); + +test(function(t) { + var div = addDiv(t); + + // Add a couple of transitions + div.style.left = '0px'; + div.style.top = '0px'; + getComputedStyle(div).transitionProperty; + + div.style.transition = 'all 100s'; + div.style.left = '100px'; + div.style.top = '100px'; + assert_equals(document.getAnimations().length, 2, + 'getAnimations returns two running CSS Transitions'); + + // Remove both + div.style.transitionProperty = 'none'; + assert_equals(document.getAnimations().length, 0, + 'getAnimations returns no running CSS Transitions'); +}, 'getAnimations for CSS Transitions'); + +test(function(t) { + addStyle(t, { '.init::after': 'content: ""; width: 0px; ' + + 'transition: all 100s;', + '.init::before': 'content: ""; width: 0px; ' + + 'transition: all 10s;', + '.change::after': 'width: 100px;', + '.change::before': 'width: 100px;' }); + // create two divs with these arrangement: + // parent + // ::before, + // ::after + // | + // child + var parent = addDiv(t); + var child = addDiv(t); + parent.appendChild(child); + + parent.style.left = '0px'; + parent.style.transition = 'left 10s'; + parent.classList.add('init'); + child.style.left = '0px'; + child.style.transition = 'left 10s'; + flushComputedStyle(parent); + + parent.style.left = '100px'; + parent.classList.add('change'); + child.style.left = '100px'; + + var anims = document.getAnimations(); + assert_equals(anims.length, 4, + 'CSS transition on both pseudo-elements and elements ' + + 'are returned'); + assert_equals(anims[0].effect.target, parent, + 'The animation targeting the parent element comes first'); + assert_equals(anims[1].effect.target.type, '::before', + 'The animation targeting the ::before element comes second'); + assert_equals(anims[2].effect.target.type, '::after', + 'The animation targeting the ::after element comes third'); + assert_equals(anims[3].effect.target, child, + 'The animation targeting the child element comes last'); +}, 'CSS Transitions targetting (pseudo-)elements should have correct order ' + + 'after sorting'); + +async_test(function(t) { + var div = addDiv(t, { style: 'left: 0px; transition: all 50ms' }); + flushComputedStyle(div); + + div.style.left = '100px'; + var animations = div.getAnimations(); + assert_equals(animations.length, 1, 'Got transition'); + animations[0].finished.then(t.step_func(function() { + assert_equals(document.getAnimations().length, 0, + 'No animations returned'); + t.done(); + })); +}, 'Transitions are not returned after they have finished'); + +done(); +</script> +</body> diff --git a/dom/animation/test/css-transitions/file_effect-target.html b/dom/animation/test/css-transitions/file_effect-target.html new file mode 100644 index 000000000..0f67b0b9a --- /dev/null +++ b/dom/animation/test/css-transitions/file_effect-target.html @@ -0,0 +1,66 @@ +<!doctype html> +<meta charset=utf-8> +<script src="../testcommon.js"></script> +<body> +<script> +'use strict'; + +test(function(t) { + var div = addDiv(t); + + div.style.left = '0px'; + window.getComputedStyle(div).transitionProperty; + div.style.transition = 'left 100s'; + div.style.left = '100px'; + + var animation = div.getAnimations()[0]; + assert_equals(animation.effect.target, div, + 'Animation.target is the animatable div'); +}, 'Returned CSS transitions have the correct Animation.target'); + +test(function(t) { + addStyle(t, { '.init::after': 'content: ""; width: 0px; height: 0px; ' + + 'transition: all 10s;', + '.change::after': 'width: 100px; height: 100px;' }); + var div = addDiv(t, { class: 'init' }); + flushComputedStyle(div); + div.classList.add('change'); + + var anims = document.getAnimations(); + assert_equals(anims.length, 2, + 'Got transitions running on ::after pseudo element'); + assert_equals(anims[0].effect.target, anims[1].effect.target, + 'Both transitions return the same target object'); +}, 'effect.target should return the same CSSPseudoElement object each time'); + +test(function(t) { + addStyle(t, { '.init::after': 'content: ""; width: 0px; transition: all 10s;', + '.change::after': 'width: 100px;' }); + var div = addDiv(t, { class: 'init' }); + flushComputedStyle(div); + div.classList.add('change'); + var pseudoTarget = document.getAnimations()[0].effect.target; + var effect = new KeyframeEffectReadOnly(pseudoTarget, + { background: ["blue", "red"] }, + 3000); + var newAnim = new Animation(effect, document.timeline); + newAnim.play(); + + var anims = document.getAnimations(); + assert_equals(anims.length, 2, + 'Got animations running on ::after pseudo element'); + assert_not_equals(anims[0], newAnim, + 'The scriped-generated animation appears last'); + assert_equals(newAnim.effect.target, pseudoTarget, + 'The effect.target of the scripted-generated animation is ' + + 'the same as the one from the argument of ' + + 'KeyframeEffectReadOnly constructor'); + assert_equals(anims[0].effect.target, newAnim.effect.target, + 'Both the transition and the scripted-generated animation ' + + 'return the same target object'); +}, 'effect.target from the script-generated animation should return the same ' + + 'CSSPseudoElement object as that from the CSS generated transition'); + +done(); +</script> +</body> diff --git a/dom/animation/test/css-transitions/file_element-get-animations.html b/dom/animation/test/css-transitions/file_element-get-animations.html new file mode 100644 index 000000000..0ce145da0 --- /dev/null +++ b/dom/animation/test/css-transitions/file_element-get-animations.html @@ -0,0 +1,147 @@ +<!doctype html> +<meta charset=utf-8> +<script src="../testcommon.js"></script> +<body> +<script> +'use strict'; + +async_test(function(t) { + var div = addDiv(t); + + // FIXME: This test does too many things. It should be split up. + + // Add a couple of transitions + div.style.left = '0px'; + div.style.top = '0px'; + window.getComputedStyle(div).transitionProperty; + + div.style.transition = 'all 100s'; + div.style.left = '100px'; + div.style.top = '100px'; + + var animations = div.getAnimations(); + assert_equals(animations.length, 2, + 'getAnimations() returns one Animation per transitioning property'); + waitForAllAnimations(animations).then(t.step_func(function() { + var startTime = animations[0].startTime; + assert_true(startTime > 0 && startTime <= document.timeline.currentTime, + 'CSS transitions have sensible start times'); + assert_equals(animations[0].startTime, animations[1].startTime, + 'CSS transitions started together have the same start time'); + // Wait a moment then add a third transition + return waitForFrame(); + })).then(t.step_func(function() { + div.style.backgroundColor = 'green'; + animations = div.getAnimations(); + assert_equals(animations.length, 3, + 'getAnimations returns Animations for all running CSS Transitions'); + return waitForAllAnimations(animations); + })).then(t.step_func(function() { + assert_less_than(animations[1].startTime, animations[2].startTime, + 'Animation for additional CSS transition starts after the original' + + ' transitions and appears later in the list'); + t.done(); + })); +}, 'getAnimations for CSS Transitions'); + +test(function(t) { + var div = addDiv(t, { style: 'left: 0px; transition: all 100s' }); + + flushComputedStyle(div); + div.style.left = '100px'; + + assert_class_string(div.getAnimations()[0], 'CSSTransition', + 'Interface of returned animation is CSSTransition'); +}, 'getAnimations returns CSSTransition objects for CSS Transitions'); + +async_test(function(t) { + var div = addDiv(t); + + // Set up event listener + div.addEventListener('transitionend', t.step_func(function() { + assert_equals(div.getAnimations().length, 0, + 'getAnimations does not return finished CSS Transitions'); + t.done(); + })); + + // Add a very short transition + div.style.left = '0px'; + window.getComputedStyle(div).left; + + div.style.transition = 'all 0.01s'; + div.style.left = '100px'; + window.getComputedStyle(div).left; +}, 'getAnimations for CSS Transitions that have finished'); + +test(function(t) { + var div = addDiv(t); + + // Try to transition non-animatable property animation-duration + div.style.animationDuration = '10s'; + window.getComputedStyle(div).animationDuration; + + div.style.transition = 'all 100s'; + div.style.animationDuration = '100s'; + + assert_equals(div.getAnimations().length, 0, + 'getAnimations returns an empty sequence for a transition' + + ' of a non-animatable property'); +}, 'getAnimations for transition on non-animatable property'); + +test(function(t) { + var div = addDiv(t); + + div.style.setProperty('-vendor-unsupported', '0px', ''); + window.getComputedStyle(div).transitionProperty; + div.style.transition = 'all 100s'; + div.style.setProperty('-vendor-unsupported', '100px', ''); + + assert_equals(div.getAnimations().length, 0, + 'getAnimations returns an empty sequence for a transition' + + ' of an unsupported property'); +}, 'getAnimations for transition on unsupported property'); + +test(function(t) { + var div = addDiv(t, { style: 'transform: translate(0px); ' + + 'opacity: 0; ' + + 'border-width: 0px; ' + // Shorthand + 'border-style: solid' }); + getComputedStyle(div).transform; + + div.style.transition = 'all 100s'; + div.style.transform = 'translate(100px)'; + div.style.opacity = '1'; + div.style.borderWidth = '1px'; + + var animations = div.getAnimations(); + assert_equals(animations.length, 6, + 'Generated expected number of transitions'); + assert_equals(animations[0].transitionProperty, 'border-bottom-width'); + assert_equals(animations[1].transitionProperty, 'border-left-width'); + assert_equals(animations[2].transitionProperty, 'border-right-width'); + assert_equals(animations[3].transitionProperty, 'border-top-width'); + assert_equals(animations[4].transitionProperty, 'opacity'); + assert_equals(animations[5].transitionProperty, 'transform'); +}, 'getAnimations sorts simultaneous transitions by name'); + +test(function(t) { + var div = addDiv(t, { style: 'transform: translate(0px); ' + + 'opacity: 0' }); + getComputedStyle(div).transform; + + div.style.transition = 'all 100s'; + div.style.transform = 'translate(100px)'; + assert_equals(div.getAnimations().length, 1, + 'Initially there is only one (transform) transition'); + div.style.opacity = '1'; + assert_equals(div.getAnimations().length, 2, + 'Then a second (opacity) transition is added'); + + var animations = div.getAnimations(); + assert_equals(animations[0].transitionProperty, 'transform'); + assert_equals(animations[1].transitionProperty, 'opacity'); +}, 'getAnimations sorts transitions by when they were generated'); + +done(); +</script> +</body> diff --git a/dom/animation/test/css-transitions/file_keyframeeffect-getkeyframes.html b/dom/animation/test/css-transitions/file_keyframeeffect-getkeyframes.html new file mode 100644 index 000000000..7bbf76fa7 --- /dev/null +++ b/dom/animation/test/css-transitions/file_keyframeeffect-getkeyframes.html @@ -0,0 +1,95 @@ +<!doctype html> +<meta charset=utf-8> +<script src="../testcommon.js"></script> +<style> +:root { + --var-100px: 100px; +} +</style> +<body> +<script> +'use strict'; + +function getKeyframes(e) { + return e.getAnimations()[0].effect.getKeyframes(); +} + +function assert_frames_equal(a, b, name) { + assert_equals(Object.keys(a).sort().toString(), + Object.keys(b).sort().toString(), + "properties on " + name); + for (var p in a) { + assert_equals(a[p], b[p], "value for '" + p + "' on " + name); + } +} + +test(function(t) { + var div = addDiv(t); + + div.style.left = '0px'; + window.getComputedStyle(div).transitionProperty; + div.style.transition = 'left 100s'; + div.style.left = '100px'; + + var frames = getKeyframes(div); + + assert_equals(frames.length, 2, "number of frames"); + + var expected = [ + { offset: 0, computedOffset: 0, easing: "ease", left: "0px" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "100px" }, + ]; + + for (var i = 0; i < frames.length; i++) { + assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i); + } +}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for a simple' + + ' transition'); + +test(function(t) { + var div = addDiv(t); + + div.style.left = '0px'; + window.getComputedStyle(div).transitionProperty; + div.style.transition = 'left 100s steps(2,end)'; + div.style.left = '100px'; + + var frames = getKeyframes(div); + + assert_equals(frames.length, 2, "number of frames"); + + var expected = [ + { offset: 0, computedOffset: 0, easing: "steps(2)", left: "0px" }, + { offset: 1, computedOffset: 1, easing: "linear", left: "100px" }, + ]; + + for (var i = 0; i < frames.length; i++) { + assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i); + } +}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for a simple' + + ' transition with a non-default easing function'); + +test(function(t) { + var div = addDiv(t); + div.style.left = '0px'; + window.getComputedStyle(div).transitionProperty; + div.style.transition = 'left 100s'; + div.style.left = 'var(--var-100px)'; + + var frames = getKeyframes(div); + + // CSS transition endpoints are based on the computed value so we + // shouldn't see the variable reference + var expected = [ + { offset: 0, computedOffset: 0, easing: 'ease', left: '0px' }, + { offset: 1, computedOffset: 1, easing: 'linear', left: '100px' }, + ]; + for (var i = 0; i < frames.length; i++) { + assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i); + } +}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for a' + + ' transition with a CSS variable endpoint'); + +done(); +</script> +</body> diff --git a/dom/animation/test/css-transitions/file_pseudoElement-get-animations.html b/dom/animation/test/css-transitions/file_pseudoElement-get-animations.html new file mode 100644 index 000000000..5683a14a1 --- /dev/null +++ b/dom/animation/test/css-transitions/file_pseudoElement-get-animations.html @@ -0,0 +1,45 @@ +<!doctype html> +<meta charset=utf-8> +<script src="../testcommon.js"></script> +<style> +.init::before { + content: ''; + height: 0px; + width: 0px; + opacity: 0; + transition: all 100s; +} +.change::before { + height: 100px; + width: 100px; + opacity: 1; +} +</style> +<body> +<script> +'use strict'; + +test(function(t) { + var div = addDiv(t, { class: 'init' }); + flushComputedStyle(div); + div.classList.add('change'); + + // Sanity checks + assert_equals(document.getAnimations().length, 3, + 'Got expected number of animations on document'); + var pseudoTarget = document.getAnimations()[0].effect.target; + assert_class_string(pseudoTarget, 'CSSPseudoElement', + 'Got pseudo-element target'); + + // Check animations returned from the pseudo element are in correct order + var anims = pseudoTarget.getAnimations(); + assert_equals(anims.length, 3, + 'Got expected number of animations on pseudo-element'); + assert_equals(anims[0].transitionProperty, 'height'); + assert_equals(anims[1].transitionProperty, 'opacity'); + assert_equals(anims[2].transitionProperty, 'width'); +}, 'getAnimations sorts simultaneous transitions by name'); + +done(); +</script> +</body> diff --git a/dom/animation/test/css-transitions/file_setting-effect.html b/dom/animation/test/css-transitions/file_setting-effect.html new file mode 100644 index 000000000..c61877194 --- /dev/null +++ b/dom/animation/test/css-transitions/file_setting-effect.html @@ -0,0 +1,91 @@ +<!doctype html> +<meta charset=utf-8> +<script src='../testcommon.js'></script> +<body> +<script> +'use strict'; + +promise_test(function(t) { + var div = addDiv(t); + div.style.left = '0px'; + + div.style.transition = 'left 100s'; + flushComputedStyle(div); + div.style.left = '100px'; + + var transition = div.getAnimations()[0]; + return transition.ready.then(function() { + transition.currentTime = 50 * MS_PER_SEC; + transition.effect = null; + assert_equals(transition.transitionProperty, 'left'); + assert_equals(transition.playState, 'finished'); + assert_equals(window.getComputedStyle(div).left, '100px'); + }); +}, 'Test for removing a transition effect'); + +promise_test(function(t) { + var div = addDiv(t); + div.style.left = '0px'; + + div.style.transition = 'left 100s'; + flushComputedStyle(div); + div.style.left = '100px'; + + var transition = div.getAnimations()[0]; + return transition.ready.then(function() { + transition.currentTime = 50 * MS_PER_SEC; + transition.effect = new KeyframeEffect(div, + { marginLeft: [ '0px' , '100px'] }, + 100 * MS_PER_SEC); + assert_equals(transition.transitionProperty, 'left'); + assert_equals(transition.playState, 'running'); + assert_equals(window.getComputedStyle(div).left, '100px'); + assert_equals(window.getComputedStyle(div).marginLeft, '50px'); + }); +}, 'Test for replacing the transition effect by a new keyframe effect'); + +promise_test(function(t) { + var div = addDiv(t); + div.style.left = '0px'; + div.style.width = '0px'; + + div.style.transition = 'left 100s'; + flushComputedStyle(div); + div.style.left = '100px'; + + var transition = div.getAnimations()[0]; + return transition.ready.then(function() { + transition.currentTime = 50 * MS_PER_SEC; + transition.effect = new KeyframeEffect(div, + { marginLeft: [ '0px' , '100px'] }, + 20 * MS_PER_SEC); + assert_equals(transition.playState, 'finished'); + }); +}, 'Test for setting a new keyframe effect with a shorter duration'); + +promise_test(function(t) { + var div = addDiv(t); + div.style.left = '0px'; + div.style.width = '0px'; + + div.style.transition = 'left 100s'; + flushComputedStyle(div); + div.style.left = '100px'; + + var transition = div.getAnimations()[0]; + assert_equals(transition.playState, 'pending'); + + transition.effect = new KeyframeEffect(div, + { marginLeft: [ '0px' , '100px'] }, + 100 * MS_PER_SEC); + assert_equals(transition.transitionProperty, 'left'); + assert_equals(transition.playState, 'pending'); + + return transition.ready.then(function() { + assert_equals(transition.playState, 'running'); + }); +}, 'Test for setting a new keyframe effect to a pending transition'); + +done(); +</script> +</body> diff --git a/dom/animation/test/css-transitions/test_animation-cancel.html b/dom/animation/test/css-transitions/test_animation-cancel.html new file mode 100644 index 000000000..949e0843e --- /dev/null +++ b/dom/animation/test/css-transitions/test_animation-cancel.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_animation-cancel.html"); + }); +</script> diff --git a/dom/animation/test/css-transitions/test_animation-computed-timing.html b/dom/animation/test/css-transitions/test_animation-computed-timing.html new file mode 100644 index 000000000..c1b40aaf3 --- /dev/null +++ b/dom/animation/test/css-transitions/test_animation-computed-timing.html @@ -0,0 +1,16 @@ +<!doctype html> +<html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_animation-computed-timing.html"); + }); +</script> +</html> diff --git a/dom/animation/test/css-transitions/test_animation-currenttime.html b/dom/animation/test/css-transitions/test_animation-currenttime.html new file mode 100644 index 000000000..30b0ed030 --- /dev/null +++ b/dom/animation/test/css-transitions/test_animation-currenttime.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_animation-currenttime.html"); + }); +</script> diff --git a/dom/animation/test/css-transitions/test_animation-finished.html b/dom/animation/test/css-transitions/test_animation-finished.html new file mode 100644 index 000000000..f2ed7f80b --- /dev/null +++ b/dom/animation/test/css-transitions/test_animation-finished.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_animation-finished.html"); + }); +</script> diff --git a/dom/animation/test/css-transitions/test_animation-pausing.html b/dom/animation/test/css-transitions/test_animation-pausing.html new file mode 100644 index 000000000..67484a2a5 --- /dev/null +++ b/dom/animation/test/css-transitions/test_animation-pausing.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_animation-pausing.html"); + }); +</script> diff --git a/dom/animation/test/css-transitions/test_animation-ready.html b/dom/animation/test/css-transitions/test_animation-ready.html new file mode 100644 index 000000000..a928ded64 --- /dev/null +++ b/dom/animation/test/css-transitions/test_animation-ready.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_animation-ready.html"); + }); +</script> diff --git a/dom/animation/test/css-transitions/test_animation-starttime.html b/dom/animation/test/css-transitions/test_animation-starttime.html new file mode 100644 index 000000000..8a8c85f2d --- /dev/null +++ b/dom/animation/test/css-transitions/test_animation-starttime.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_animation-starttime.html"); + }); +</script> diff --git a/dom/animation/test/css-transitions/test_csstransition-events.html b/dom/animation/test/css-transitions/test_csstransition-events.html new file mode 100644 index 000000000..92559ad67 --- /dev/null +++ b/dom/animation/test/css-transitions/test_csstransition-events.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_csstransition-events.html"); + }); +</script> diff --git a/dom/animation/test/css-transitions/test_csstransition-transitionproperty.html b/dom/animation/test/css-transitions/test_csstransition-transitionproperty.html new file mode 100644 index 000000000..0aa1912d9 --- /dev/null +++ b/dom/animation/test/css-transitions/test_csstransition-transitionproperty.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_csstransition-transitionproperty.html"); + }); +</script> diff --git a/dom/animation/test/css-transitions/test_document-get-animations.html b/dom/animation/test/css-transitions/test_document-get-animations.html new file mode 100644 index 000000000..dc964e62c --- /dev/null +++ b/dom/animation/test/css-transitions/test_document-get-animations.html @@ -0,0 +1,15 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_document-get-animations.html"); + }); +</script> +</html> diff --git a/dom/animation/test/css-transitions/test_effect-target.html b/dom/animation/test/css-transitions/test_effect-target.html new file mode 100644 index 000000000..f3ae72229 --- /dev/null +++ b/dom/animation/test/css-transitions/test_effect-target.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_effect-target.html"); + }); +</script> diff --git a/dom/animation/test/css-transitions/test_element-get-animations.html b/dom/animation/test/css-transitions/test_element-get-animations.html new file mode 100644 index 000000000..87abdfa73 --- /dev/null +++ b/dom/animation/test/css-transitions/test_element-get-animations.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_element-get-animations.html"); + }); +</script> diff --git a/dom/animation/test/css-transitions/test_keyframeeffect-getkeyframes.html b/dom/animation/test/css-transitions/test_keyframeeffect-getkeyframes.html new file mode 100644 index 000000000..dcc54255d --- /dev/null +++ b/dom/animation/test/css-transitions/test_keyframeeffect-getkeyframes.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_keyframeeffect-getkeyframes.html"); + }); +</script> diff --git a/dom/animation/test/css-transitions/test_pseudoElement-get-animations.html b/dom/animation/test/css-transitions/test_pseudoElement-get-animations.html new file mode 100644 index 000000000..1e0dc5c82 --- /dev/null +++ b/dom/animation/test/css-transitions/test_pseudoElement-get-animations.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { "set": [["dom.animations-api.core.enabled", true]]}, + function() { + window.open("file_pseudoElement-get-animations.html"); + }); +</script> diff --git a/dom/animation/test/css-transitions/test_setting-effect.html b/dom/animation/test/css-transitions/test_setting-effect.html new file mode 100644 index 000000000..a9654ec55 --- /dev/null +++ b/dom/animation/test/css-transitions/test_setting-effect.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<script src='/resources/testharness.js'></script> +<script src='/resources/testharnessreport.js'></script> +<div id='log'></div> +<script> +'use strict'; +setup({explicit_done: true}); +SpecialPowers.pushPrefEnv( + { 'set': [['dom.animations-api.core.enabled', true]]}, + function() { + window.open('file_setting-effect.html'); + }); +</script> |