<!doctype html>
<meta charset=utf-8>
<title>AnimationEffect.updateTiming() for CSS animations</title>
<!-- TODO: Add a more specific link for this once it is specified. -->
<link rel="help" href="https://drafts.csswg.org/css-animations-2/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/testcommon.js"></script>
<style>
@keyframes anim-empty { }
</style>
<body>
<div id="log"></div>
<script>
"use strict";

test(t => {
  const div = addDiv(t);
  div.style.animation = 'anim-empty 100s';

  const animation = div.getAnimations()[0];
  animation.effect.updateTiming({ duration: 2 * MS_PER_SEC });

  div.style.animationDuration = '4s';
  div.style.animationDelay = '6s';

  assert_equals(
    animation.effect.getTiming().duration,
    2 * MS_PER_SEC,
    'Duration should be the value set by the API'
  );
  assert_equals(
    animation.effect.getTiming().delay,
    6 * MS_PER_SEC,
    'Delay should be the value set by style'
  );
}, 'AnimationEffect.updateTiming({ duration }) causes changes to the'
   + ' animation-duration to be ignored');

// The above test covers duration (with delay as a control). The remaining
// properties are:
//
//   iterations - animation-iteration-count
//   direction - animation-direction
//   delay - animation-delay
//   fill - animation-fill-mode
//
// Which we test in two batches, overriding two properties each time and using
// the remaining two properties as control values to check they are NOT
// overridden.

test(t => {
  const div = addDiv(t);
  div.style.animation = 'anim-empty 100s';

  const animation = div.getAnimations()[0];
  animation.effect.updateTiming({ iterations: 2, direction: 'reverse' });

  div.style.animationIterationCount = '4';
  div.style.animationDirection = 'alternate';
  div.style.animationDelay = '6s';
  div.style.animationFillMode = 'both';

  assert_equals(
    animation.effect.getTiming().iterations,
    2,
    'Iterations should be the value set by the API'
  );
  assert_equals(
    animation.effect.getTiming().direction,
    'reverse',
    'Direction should be the value set by the API'
  );
  assert_equals(
    animation.effect.getTiming().delay,
    6 * MS_PER_SEC,
    'Delay should be the value set by style'
  );
  assert_equals(
    animation.effect.getTiming().fill,
    'both',
    'Fill should be the value set by style'
  );
}, 'AnimationEffect.updateTiming({ iterations, direction }) causes changes to'
   + ' the animation-iteration-count and animation-direction to be ignored');

test(t => {
  const div = addDiv(t);
  div.style.animation = 'anim-empty 100s';

  const animation = div.getAnimations()[0];
  animation.effect.updateTiming({ delay: 2 * MS_PER_SEC, fill: 'both' });

  div.style.animationDelay = '4s';
  div.style.animationFillMode = 'forwards';
  div.style.animationIterationCount = '6';
  div.style.animationDirection = 'reverse';

  assert_equals(
    animation.effect.getTiming().delay,
    2 * MS_PER_SEC,
    'Delay should be the value set by the API'
  );
  assert_equals(
    animation.effect.getTiming().fill,
    'both',
    'Fill should be the value set by the API'
  );
  assert_equals(
    animation.effect.getTiming().iterations,
    6,
    'Iterations should be the value set by style'
  );
  assert_equals(
    animation.effect.getTiming().direction,
    'reverse',
    'Direction should be the value set by style'
  );
}, 'AnimationEffect.updateTiming({ delay, fill }) causes changes to'
   + ' the animation-delay and animation-fill-mode to be ignored');

test(t => {
  const div = addDiv(t);
  div.style.animation = 'anim-empty 100s';

  const animation = div.getAnimations()[0];
  assert_throws_js(TypeError, () => {
    animation.effect.updateTiming({ duration: 2 * MS_PER_SEC, iterations: -1 });
  }, 'Negative iteration count should cause an error to be thrown');

  div.style.animationDuration = '4s';

  assert_equals(
    animation.effect.getTiming().duration,
    4 * MS_PER_SEC,
    'Duration should be the value set by style'
  );
}, 'AnimationEffect.updateTiming() does override to changes from animation-*'
   + ' properties if there is an error');

test(t => {
  const div = addDiv(t);
  div.style.animation = 'anim-empty 100s';

  const animation = div.getAnimations()[0];
  animation.effect.updateTiming({
    easing: 'steps(4)',
    endDelay: 2 * MS_PER_SEC,
    iterationStart: 4,
  });

  div.style.animationDuration = '6s';
  div.style.animationTimingFunction = 'ease-in';

  assert_equals(
    animation.effect.getTiming().easing,
    'steps(4)',
    'endDelay should be the value set by the API'
  );
  assert_equals(
    animation.effect.getTiming().endDelay,
    2 * MS_PER_SEC,
    'endDelay should be the value set by the API'
  );
  assert_equals(
    animation.effect.getTiming().iterationStart,
    4,
    'iterationStart should be the value set by style'
  );
}, 'AnimationEffect properties that do not map to animation-* properties'
   + ' should not be changed when animation-* style is updated');

</script>
</body>
