<!doctype html>
<meta charset=utf-8>
<title>KeyframeEffect.getKeyframes() for CSS transitions</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>
<style>
:root {
  --var-100px: 100px;
}
</style>
<div id="log"></div>
<script>
'use strict';

const getKeyframes = e => {
  return e.getAnimations()[0].effect.getKeyframes();
};

const assert_frames_equal = (a, b, name) => {
  assert_equals(
    Object.keys(a).sort().toString(),
    Object.keys(b).sort().toString(),
    `properties on ${name}`
  );
  for (const p in a) {
    assert_equals(a[p], b[p], `value for '${p}' on ${name}`);
  }
};

test(t => {
  const div = addDiv(t);

  div.style.left = '0px';
  getComputedStyle(div).transitionProperty;
  div.style.transition = 'left 100s';
  div.style.left = '100px';

  const frames = getKeyframes(div);

  assert_equals(frames.length, 2, 'number of frames');

  const expected = [
    { offset: 0,
      computedOffset: 0,
      easing: 'linear',
      composite: 'auto',
      left: '0px',
    },
    {
      offset: 1,
      computedOffset: 1,
      easing: 'linear',
      composite: 'auto',
      left: '100px',
    },
  ];

  for (let i = 0; i < frames.length; i++) {
    assert_frames_equal(frames[i], expected[i], `ComputedKeyframe #${i}`);
  }
}, 'KeyframeEffect.getKeyframes() returns expected frames for a simple'
   + ' transition');

test(t => {
  const div = addDiv(t);

  div.style.left = '0px';
  getComputedStyle(div).transitionProperty;
  div.style.transition = 'left 100s steps(2,end)';
  div.style.left = '100px';

  const frames = getKeyframes(div);

  assert_equals(frames.length, 2, 'number of frames');

  const expected = [
    {
      offset: 0,
      computedOffset: 0,
      easing: 'linear',
      composite: 'auto',
      left: '0px',
    },
    {
      offset: 1,
      computedOffset: 1,
      easing: 'linear',
      composite: 'auto',
      left: '100px',
    },
  ];

  for (let i = 0; i < frames.length; i++) {
    assert_frames_equal(frames[i], expected[i], `ComputedKeyframe #${i}`);
  }
}, 'KeyframeEffect.getKeyframes() returns frames unaffected by a non-default easing function');

test(t => {
  const div = addDiv(t);
  div.style.left = '0px';
  getComputedStyle(div).transitionProperty;
  div.style.transition = 'left 100s';
  div.style.left = 'var(--var-100px)';

  const frames = getKeyframes(div);

  // CSS transition endpoints are based on the computed value so we
  // shouldn't see the variable reference
  const expected = [
    {
      offset: 0,
      computedOffset: 0,
      easing: 'linear',
      composite: 'auto',
      left: '0px',
    },
    {
      offset: 1,
      computedOffset: 1,
      easing: 'linear',
      composite: 'auto',
      left: '100px',
    },
  ];
  for (let i = 0; i < frames.length; i++) {
    assert_frames_equal(frames[i], expected[i], `ComputedKeyframe #${i}`);
  }
}, 'KeyframeEffect.getKeyframes() returns expected frames for a'
   + ' transition with a CSS variable endpoint');

test(t => {
  const div = addDiv(t);
  div.style.left = '0px';
  getComputedStyle(div).transitionProperty;
  div.style.transition = 'left 100s';
  div.style.left = '100px';

  // Resetting the effect target before retrieving the keyframes should not
  // affect the computed property values.
  const anim = div.getAnimations()[0];
  anim.effect.target = null;
  const frames = anim.effect.getKeyframes();

  const expected = [
    {
      offset: 0,
      computedOffset: 0,
      easing: 'linear',
      composite: 'auto',
      left: '0px',
    },
    {
      offset: 1,
      computedOffset: 1,
      easing: 'linear',
      composite: 'auto',
      left: '100px',
    },
  ];
  for (let i = 0; i < frames.length; i++) {
    assert_frames_equal(frames[i], expected[i], `ComputedKeyframe #${i}`);
  }
}, 'KeyframeEffect.getKeyframes() returns expected frames for a'
   + ' transition after resetting the effect target');

</script>
