| <!doctype html> | 
 | <meta charset=utf-8> | 
 | <title>CSSTransition.currentTime</title> | 
 | <!-- TODO: Add a more specific link for this once it is specified. --> | 
 | <link rel="help" href="https://drafts.csswg.org/css-transitions-2/#csstransition"> | 
 | <script src="/resources/testharness.js"></script> | 
 | <script src="/resources/testharnessreport.js"></script> | 
 | <script src="support/helper.js"></script> | 
 | <div id="log"></div> | 
 | <script> | 
 |  | 
 | 'use strict'; | 
 |  | 
 | const marginLeft = div => parseFloat(getComputedStyle(div).marginLeft); | 
 |  | 
 | promise_test(async t => { | 
 |   const div = addDiv(t, { | 
 |     style: 'margin-left: 100px; transition: margin-left 100s linear 100s', | 
 |   }); | 
 |   getComputedStyle(div).marginLeft; | 
 |   div.style.marginLeft = '200px'; | 
 |  | 
 |   const animation = div.getAnimations()[0]; | 
 |   assert_equals( | 
 |     animation.currentTime, | 
 |     0, | 
 |     'currentTime should initially be zero' | 
 |   ); | 
 |  | 
 |   await animation.ready; | 
 |  | 
 |   const seekTime = 150 * MS_PER_SEC; | 
 |   animation.currentTime = seekTime; | 
 |  | 
 |   assert_time_equals_literal( | 
 |     animation.currentTime, | 
 |     seekTime, | 
 |     'currentTime is updated' | 
 |   ); | 
 |   assert_equals(getComputedStyle(div).marginLeft, '150px'); | 
 | }, 'currentTime can be used to seek a CSS transition'); | 
 |  | 
 | promise_test(async t => { | 
 |   const div = addDiv(t, { | 
 |     style: 'margin-left: 100px; transition: margin-left 100s linear 100s', | 
 |   }); | 
 |   const eventWatcher = new EventWatcher(t, div, 'transitionend'); | 
 |   getComputedStyle(div).marginLeft; | 
 |   div.style.marginLeft = '200px'; | 
 |  | 
 |   const animation = div.getAnimations()[0]; | 
 |   await animation.ready; | 
 |  | 
 |   const marginLeft = () => parseFloat(getComputedStyle(div).marginLeft); | 
 |   assert_equals(marginLeft(div), 100); | 
 |  | 
 |   animation.currentTime = 100 * MS_PER_SEC; | 
 |   assert_equals(marginLeft(div), 100); | 
 |  | 
 |   animation.currentTime = 150 * MS_PER_SEC; | 
 |   assert_equals(marginLeft(div), 150); | 
 |  | 
 |   animation.currentTime = 200 * MS_PER_SEC; | 
 |   await eventWatcher.wait_for('transitionend'); | 
 |   assert_equals(marginLeft(div), 200); | 
 | }, 'Skipping forwards through transition'); | 
 |  | 
 | promise_test(async t => { | 
 |   const div = addDiv(t, { | 
 |     style: 'margin-left: 100px; transition: margin-left 100s linear 100s', | 
 |   }); | 
 |   const eventWatcher = new EventWatcher(t, div, 'transitionend'); | 
 |   getComputedStyle(div).marginLeft; | 
 |   div.style.marginLeft = '200px'; | 
 |  | 
 |   const animation = div.getAnimations()[0]; | 
 |   await animation.ready; | 
 |  | 
 |   // 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.currentTime = 150 * MS_PER_SEC; | 
 |   assert_equals(marginLeft(div), 150); | 
 |  | 
 |   animation.currentTime = 100 * MS_PER_SEC; | 
 |   assert_equals(marginLeft(div), 100); | 
 | }, 'Skipping backwards through transition'); | 
 |  | 
 | promise_test(async t => { | 
 |   const div = addDiv(t, { | 
 |     style: 'margin-left: 100px; transition: margin-left 100s linear 100s', | 
 |   }); | 
 |   getComputedStyle(div).marginLeft; | 
 |   div.style.marginLeft = '200px'; | 
 |   const animation = div.getAnimations()[0]; | 
 |  | 
 |   await animation.ready; | 
 |  | 
 |   assert_throws_js( | 
 |     TypeError, | 
 |     () => { | 
 |       animation.currentTime = null; | 
 |     }, | 
 |     'Expect TypeError exception on trying to set Animation.currentTime to null' | 
 |   ); | 
 | }, 'Setting currentTime to null on a CSS transition throws'); | 
 |  | 
 | test(t => { | 
 |   const div = addDiv(t); | 
 |  | 
 |   div.style.left = '0px'; | 
 |   getComputedStyle(div).transitionProperty; | 
 |   div.style.transition = 'left 100s ease-in'; | 
 |   div.style.left = '100px'; | 
 |  | 
 |   const transition = div.getAnimations()[0]; | 
 |  | 
 |   // Seek to the middle. Note, this is not equivalent to 50% progress since the | 
 |   // timing-function is non-linear. | 
 |   transition.currentTime = 50 * MS_PER_SEC; | 
 |   const portion = transition.effect.getComputedTiming().progress; | 
 |  | 
 |   // Reverse the transition. | 
 |   div.style.left = '0px'; | 
 |   const reversedTransition = div.getAnimations()[0]; | 
 |  | 
 |   // If the transition reversing behavior does not advance the previous | 
 |   // transition to the time set by currentTime, start and end values will both | 
 |   // be 0px and no transition will be produced. | 
 |   assert_not_equals(reversedTransition, undefined, | 
 |                     "A reversed transition is produced"); | 
 |  | 
 |   const expectedDuration = 100 * MS_PER_SEC * portion; | 
 |   assert_approx_equals( | 
 |     reversedTransition.effect.getComputedTiming().activeDuration, | 
 |     expectedDuration, | 
 |     1, | 
 |     "The reversed transition has correctly reduced duration" | 
 |   ); | 
 | }, "Transition reversing behavior respects currentTime and uses the " + | 
 |    "transition's current position."); | 
 |  | 
 | </script> |