| <!DOCTYPE html><!-- webkit-test-runner [ enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations=true ] --> |
| <meta charset=utf-8> |
| <title>CSS Transitions</title> |
| <body> |
| <script src="../resources/testharness.js"></script> |
| <script src="../resources/testharnessreport.js"></script> |
| <script> |
| |
| 'use strict'; |
| |
| function targetTest(testCallback, description) |
| { |
| test(() => { |
| const target = document.body.appendChild(document.createElement("div")); |
| testCallback(target); |
| target.remove(); |
| }, description); |
| } |
| |
| function forceStyleUpdate(element) |
| { |
| element.offsetLeft; |
| } |
| |
| targetTest(target => { |
| target.style.left = "50px"; |
| |
| assert_array_equals(target.getAnimations(), [], "An element should not have any animations initially."); |
| |
| target.style.transitionProperty = "left"; |
| target.style.transitionDelay = "-1s"; |
| target.style.transitionDuration = "2s"; |
| target.style.transitionTimingFunction = "linear"; |
| |
| assert_array_equals(target.getAnimations(), [], "Setting CSS transitions properties should not yield a CSSTransition until a new target value is specified."); |
| |
| forceStyleUpdate(target); |
| target.style.left = "100px"; |
| |
| const animation = target.getAnimations()[0]; |
| assert_true(animation instanceof CSSTransition, "The animation is a CSSTransition."); |
| assert_true(animation instanceof Animation, "The animation is an Animation."); |
| assert_equals(animation.timeline, target.ownerDocument.timeline, "The animation's timeline is set to the element's document timeline."); |
| assert_equals(animation.playState, "running", "The animation is running as soon as it's created."); |
| assert_equals(animation.transitionProperty, "left", "The animation's transitionProperty is set."); |
| |
| const effect = animation.effect; |
| assert_true(effect instanceof KeyframeEffectReadOnly, "The animation's effect is a KeyframeEffectReadOnly."); |
| assert_false(effect instanceof KeyframeEffect, "The animation's effect is not a KeyframeEffect."); |
| assert_equals(effect.target, target, "The animation's effect is targeting the target."); |
| |
| const timing = animation.effect.timing; |
| assert_equals(timing.delay, -1000, "The animation's delay property matches the transition-delay property."); |
| assert_equals(timing.duration, 2000, "The animation's duration property matches the transition-duration property."); |
| |
| const computedTiming = animation.effect.getComputedTiming(); |
| assert_equals(computedTiming.activeDuration, 2000, "The animations's computed timing activeDuration property matches the properties set by CSS"); |
| assert_equals(computedTiming.currentIteration, 0, "The animations's computed timing currentIteration property matches the properties set by CSS"); |
| assert_equals(computedTiming.delay, -1000, "The animations's computed timing delay property matches the properties set by CSS"); |
| assert_equals(computedTiming.duration, 2000, "The animations's computed timing duration property matches the properties set by CSS"); |
| assert_equals(computedTiming.endDelay, 0, "The animations's computed timing endDelay property matches the properties set by CSS"); |
| assert_equals(computedTiming.endTime, 1000, "The animations's computed timing endTime property matches the properties set by CSS"); |
| assert_equals(computedTiming.iterationStart, 0, "The animations's computed timing iterationStart property matches the properties set by CSS"); |
| assert_equals(computedTiming.iterations, 1, "The animations's computed timing iterations property matches the properties set by CSS"); |
| assert_equals(computedTiming.localTime, 0, "The animations's computed timing localTime property matches the properties set by CSS"); |
| assert_equals(computedTiming.progress, 0.5, "The animations's computed timing progress property matches the properties set by CSS"); |
| assert_equals(computedTiming.fill, "backwards", "The animations's computed timing fill property matches the default value set for transitions"); |
| assert_equals(computedTiming.easing, "linear", "The animations's computed timing easing property matches the properties set by CSS"); |
| assert_equals(computedTiming.direction, "normal", "The animations's computed timing direction property matches the properties set by CSS"); |
| |
| const keyframes = animation.effect.getKeyframes(); |
| assert_equals(keyframes.length, 2, "The animation's effect has two keyframes."); |
| assert_equals(keyframes[0].offset, 0, "The animation's effect's first keyframe has a 0 offset."); |
| assert_equals(keyframes[0].left, "50px", "The animation's effect's first keyframe has its left property set to 50px."); |
| assert_equals(keyframes[1].offset, 1, "The animation's effect's first keyframe has a 1 offset."); |
| assert_equals(keyframes[1].left, "100px", "The animation's effect's first keyframe has its left property set to 100px."); |
| |
| assert_equals(getComputedStyle(effect.target).left, "75px", "The animation's target's computed style reflects the animation state."); |
| }, "A CSS Transition should be reflected entirely as a CSSTransition object on the timeline."); |
| |
| function transitionProperty(target, propertyName, from, to) |
| { |
| target.style[propertyName] = from; |
| forceStyleUpdate(target); |
| target.style[propertyName] = to; |
| } |
| |
| function transitionPropertyUpdateTest(testCallback, description) |
| { |
| targetTest(target => { |
| target.style.transitionProperty = "left"; |
| target.style.transitionDelay = "-500ms"; |
| target.style.transitionDuration = "2s"; |
| transitionProperty(target, "left", "50px", "100px"); |
| testCallback(target); |
| }, description); |
| } |
| |
| transitionPropertyUpdateTest(target => { |
| const initialAnimation = target.getAnimations()[0]; |
| assert_equals(initialAnimation.effect.timing.delay, -500, "The animation's delay matches the initial transition-delay property."); |
| |
| target.style.transitionDelay = 0; |
| const updatedAnimation = target.getAnimations()[0]; |
| assert_equals(updatedAnimation.effect.timing.delay, 0, "The animation's delay matches the updated transition-delay property."); |
| |
| assert_not_equals(initialAnimation, updatedAnimation, "The animations before and after updating the transition-delay property differ."); |
| }, "Web Animations should reflect the transition-delay property."); |
| |
| transitionPropertyUpdateTest(target => { |
| const initialAnimation = target.getAnimations()[0]; |
| assert_equals(initialAnimation.effect.timing.duration, 2000, "The animation's duration matches the initial transition-duration property."); |
| |
| target.style.transitionDuration = "1s"; |
| const updatedAnimation = target.getAnimations()[0]; |
| assert_equals(updatedAnimation.effect.timing.duration, 1000, "The animation's duration matches the updated transition-duration property."); |
| |
| assert_not_equals(initialAnimation, updatedAnimation, "The animations before and after updating the transition-duration property differ."); |
| }, "Web Animations should reflect the transition-duration property."); |
| |
| targetTest(target => { |
| target.style.transitionDuration = "2s"; |
| |
| target.style.transitionProperty = "left"; |
| transitionProperty(target, "left", "50px", "100px"); |
| |
| const initialAnimation = target.getAnimations()[0]; |
| assert_equals(target.getAnimations()[0].transitionProperty, "left", "The animation's property matches the initial transition-property CSS property."); |
| |
| const initialKeyframes = initialAnimation.effect.getKeyframes(); |
| assert_equals(initialKeyframes.length, 2); |
| assert_equals(initialKeyframes[0].offset, 0); |
| assert_equals(initialKeyframes[0].left, "50px"); |
| assert_equals(initialKeyframes[1].offset, 1); |
| assert_equals(initialKeyframes[1].left, "100px"); |
| |
| target.style.transitionProperty = "top"; |
| transitionProperty(target, "top", "50px", "100px"); |
| |
| const updatedAnimation = target.getAnimations()[0]; |
| assert_equals(updatedAnimation.transitionProperty, "top", "The animation's property matches the updated transition-property CSS property."); |
| |
| const updatedKeyframes = updatedAnimation.effect.getKeyframes(); |
| assert_equals(updatedKeyframes.length, 2); |
| assert_equals(updatedKeyframes[0].offset, 0); |
| assert_equals(updatedKeyframes[0].top, "50px"); |
| assert_equals(updatedKeyframes[1].offset, 1); |
| assert_equals(updatedKeyframes[1].top, "100px"); |
| |
| assert_not_equals(updatedAnimation, initialAnimation, "Changing the transition-property property generates a different CSSTransition object."); |
| }, "Web Animations should reflect the transition-property property."); |
| |
| transitionPropertyUpdateTest(target => { |
| const initialAnimation = target.getAnimations()[0]; |
| assert_equals(initialAnimation.effect.timing.easing, "linear", "The animation's easing does not match the default transition-timing-function property."); |
| |
| target.style.transitionTimingFunction = "ease-in"; |
| const updatedAnimation = target.getAnimations()[0]; |
| assert_equals(updatedAnimation.effect.timing.easing, "linear", "The animation's easing does not match the updated transition-timing-function property."); |
| |
| target.style.removeProperty("transition-timing-function"); |
| const finalAnimation = target.getAnimations()[0]; |
| assert_equals(target.getAnimations()[0].effect.timing.easing, "linear", "The animation's easing does not match the default transition-timing-function value when the property is not set."); |
| }, "Web Animations should not reflect the transition-timing-function property on the effect's timing."); |
| |
| function runAnimationCompletionTest(finalAssertionCallback, description) |
| { |
| targetTest(target => { |
| target.style.transitionProperty = "left"; |
| target.style.transitionDuration = "1s"; |
| transitionProperty(target, "left", "50px", "100px"); |
| |
| assert_equals(target.getAnimations().length, 1, "Seting the transition-duration property on top of the transition-property yields a CSSTransition."); |
| assert_equals(target.getAnimations()[0].playState, "running", "Seting the transition-duration property on top of the transition-property yields a running CSSTransition."); |
| |
| finalAssertionCallback(target.getAnimations()[0]); |
| |
| assert_array_equals(target.getAnimations(), [], `${description} no longer lists the animation.`); |
| }, `${description} no longer lists the animation after it has been running.`); |
| } |
| |
| runAnimationCompletionTest(animation => animation.finish(), "Calling finish() on the animation"); |
| runAnimationCompletionTest(animation => animation.currentTime = animation.effect.timing.duration, "Seeking the animation to its end time"); |
| runAnimationCompletionTest(animation => animation.effect.target.style.transitionProperty = "none", "Setting the target's transition-property to none"); |
| runAnimationCompletionTest(animation => animation.effect.target.style.transitionDuration = 0, "Seeking the target's transition-duration to 0"); |
| |
| </script> |
| </body> |