<!DOCTYPE html>
<meta charset=utf-8>
<meta name="assert"
content="This test checks the output of step timing functions" />
<title>Tests for the output of step timing functions</title>
<link rel="help"
href="https://drafts.csswg.org/css-easing/#step-timing-functions">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="testcommon.js"></script>
<body>
<div id="log"></div>
<script>
'use strict';

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'step-start' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, 1.5, 1, 1.5)' });

  // The bezier function produces values greater than 1 (but always less than 2)
  // in (0.23368794, 1)
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '100px');
  anim.currentTime = 230;
  assert_equals(getComputedStyle(target).left, '100px');
  anim.currentTime = 250;
  assert_equals(getComputedStyle(target).left, '200px');
  anim.currentTime = 1000;
  assert_equals(getComputedStyle(target).left, '100px');
}, 'step-start easing with input progress greater than 1');

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'step-start' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, 3, 1, 3)' });

  // The bezier function produces values:
  // Input           ->  Output
  // 0.0                 0.0
  // 0.114 ~ 0.245       1.5~2.0, so current step is 2, jumps is 1 => 2.0
  // 0.245 ~ 0.6         2.0~2.4, so current step is 3, jumps is 1 => 3.0
  // 0.6   ~ 0.882       2.4~2.0, so current step is 3, jumps is 1 => 3.0
  // 0.882 ~ 0.976       2.0~1.5, so current step is 2, jumps is 1 => 2.0
  // 1.0                 1.0
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '100px');
  anim.currentTime = 114;
  assert_equals(getComputedStyle(target).left, '200px');
  anim.currentTime = 500;
  assert_equals(getComputedStyle(target).left, '300px');
  anim.currentTime = 900;
  assert_equals(getComputedStyle(target).left, '200px');
}, 'step-start easing with input progress greater than 2');

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'step-start' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, -0.5, 1, -0.5)' });

  // The bezier function produces negative values (but always greater than -1)
  // in (0, 0.766312060)
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '100px');
  anim.currentTime = 750;
  assert_equals(getComputedStyle(target).left, '0px');
  anim.currentTime = 800;
  assert_equals(getComputedStyle(target).left, '100px');
  anim.currentTime = 1000;
  assert_equals(getComputedStyle(target).left, '100px');
}, 'step-start easing with input progress less than 0');

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'step-start' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, -2, 1, -2)' });

  // The bezier function produces values less than -1 (but always greater than
  // -2) in the range (~0.118, ~0.755)
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '100px');
  anim.currentTime = 100;
  assert_equals(getComputedStyle(target).left, '0px');
  anim.currentTime = 500;
  assert_equals(getComputedStyle(target).left, '-100px');
  anim.currentTime = 1000;
  assert_equals(getComputedStyle(target).left, '100px');
}, 'step-start easing with input progress less than -1');

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'step-end' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, 1.5, 1, 1.5)' });

  // The bezier function produces values greater than 1 (but always less than 2)
  // in (0.23368794, 1)
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '0px');
  anim.currentTime = 230;
  assert_equals(getComputedStyle(target).left, '0px');
  anim.currentTime = 250;
  assert_equals(getComputedStyle(target).left, '100px');
  anim.currentTime = 1000;
  assert_equals(getComputedStyle(target).left, '100px');
}, 'step-end easing with input progress greater than 1');

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'step-end' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, 3, 1, 3)' });

  // The bezier function produces values:
  // Input           ->  Output
  // 0.0                 0.0
  // 0.114 ~ 0.245       1.5~2.0, so current step is 1, jumps is 1 => 1.0
  // 0.245 ~ 0.6         2.0~2.4, so current step is 2, jumps is 1 => 2.0
  // 0.6   ~ 0.882       2.4~2.0, so current step is 2, jumps is 1 => 2.0
  // 0.882 ~ 0.976       2.0~1.5, so current step is 1, jumps is 1 => 1.0
  // 1.0                 1.0
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '0px');
  anim.currentTime = 114;
  assert_equals(getComputedStyle(target).left, '100px');
  anim.currentTime = 500;
  assert_equals(getComputedStyle(target).left, '200px');
  anim.currentTime = 900;
  assert_equals(getComputedStyle(target).left, '100px');
}, 'step-end easing with input progress greater than 2');

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'step-end' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, -0.5, 1, -0.5)' });

  // The bezier function produces negative values (but always greater than -1)
  // in (0, 0.766312060)
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '0px');
  anim.currentTime = 750;
  assert_equals(getComputedStyle(target).left, '-100px');
  anim.currentTime = 800;
  assert_equals(getComputedStyle(target).left, '0px');
  anim.currentTime = 1000;
  assert_equals(getComputedStyle(target).left, '100px');
}, 'step-end easing with input progress less than 0');

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'steps(1, jump-both)' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, 1.5, 1, 1.5)' });

  // The bezier function produces values greater than 1 (but always less than 2)
  // in (0.23368794, 1)
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '50px');
  anim.currentTime = 230;
  assert_equals(getComputedStyle(target).left, '50px');
  anim.currentTime = 250;
  assert_equals(getComputedStyle(target).left, '100px');
  anim.currentTime = 1000;
  assert_equals(getComputedStyle(target).left, '100px');
}, 'steps(1, jump-both) easing with input progress greater than 1');

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'steps(1, jump-both)' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, 3, 1, 3)' });

  // The bezier function produces values:
  // Input           ->  Output
  // 0.0                 0.0,     so current step is 1, jumps is 2 => 0.5
  // 0.114 ~ 0.245       1.5~2.0, so current step is 2, jumps is 2 => 1.0
  // 0.245 ~ 0.6         2.0~2.4, so current step is 3, jumps is 2 => 1.5
  // 0.6   ~ 0.882       2.4~2.0, so current step is 3, jumps is 2 => 1.5
  // 0.882 ~ 0.976       2.0~1.5, so current step is 2, jumps is 2 => 1.0
  // 1.0                 1.0
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '50px');
  anim.currentTime = 114;
  assert_equals(getComputedStyle(target).left, '100px');
  anim.currentTime = 500;
  assert_equals(getComputedStyle(target).left, '150px');
  anim.currentTime = 900;
  assert_equals(getComputedStyle(target).left, '100px');
}, 'steps(1, jump-both) easing with input progress greater than 2');

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'steps(1, jump-both)' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, -0.5, 1, -0.5)' });

  // The bezier function produces negative values (but always greater than -0.5)
  // in (0, 0.766312060).
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '50px');
  anim.currentTime = 750;
  // current step is 0, jumps is 2.
  assert_equals(getComputedStyle(target).left, '0px');
  anim.currentTime = 800;
  assert_equals(getComputedStyle(target).left, '50px');
  anim.currentTime = 1000;
  assert_equals(getComputedStyle(target).left, '100px');
}, 'steps(1, jump-both) easing with input progress less than 0');

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'steps(2, jump-none)' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, 1.5, 1, 1.5)' });

  // The bezier function produces values between 0.5 and 1 in
  // (~0.0442, 0.23368), and values between 1 and 2 in (0.23368794, 1).
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '0px');
  anim.currentTime = 45;
  assert_equals(getComputedStyle(target).left, '100px');
  anim.currentTime = 230;
  assert_equals(getComputedStyle(target).left, '100px');
  anim.currentTime = 250;
  assert_equals(getComputedStyle(target).left, '200px');
  anim.currentTime = 1000;
  assert_equals(getComputedStyle(target).left, '100px');
}, 'steps(2, jump-none) easing with input progress greater than 1');

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'steps(2, jump-none)' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, 3, 1, 3)' });

  // The bezier function produces values:
  // Input           ->  Output
  // 0.0                 0.0,     so current step is 0, jumps is 1 => 0.0
  // 0.114 ~ 0.245       1.5~2.0, so current step is 3, jumps is 1 => 3.0
  // 0.245 ~ 0.6         2.0~2.4, so current step is 4, jumps is 1 => 4.0
  // 0.6   ~ 0.882       2.4~2.0, so current step is 4, jumps is 1 => 4.0
  // 0.882 ~ 0.976       2.0~1.5, so current step is 3, jumps is 1 => 3.0
  // 1.0                 1.0
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '0px');
  anim.currentTime = 114;
  assert_equals(getComputedStyle(target).left, '300px');
  anim.currentTime = 500;
  assert_equals(getComputedStyle(target).left, '400px');
  anim.currentTime = 900;
  assert_equals(getComputedStyle(target).left, '300px');
}, 'steps(2, jump-none) easing with input progress greater than 2');

test(function(t) {
  var target = createDiv(t);
  target.style.position = 'absolute';
  var anim = target.animate([ { left: '0px', easing: 'steps(2, jump-none)' },
                              { left: '100px' } ],
                            { duration: 1000,
                              fill: 'forwards',
                              easing: 'cubic-bezier(0, -0.5, 1, -0.5)' });

  // The bezier function produces negative values (but always greater than -0.5)
  // in (0, 0.766312060).
  anim.currentTime = 0;
  assert_equals(getComputedStyle(target).left, '0px');
  anim.currentTime = 750;
  // current step is -1, jumps is 1.
  assert_equals(getComputedStyle(target).left, '-100px');
  anim.currentTime = 800;
  assert_equals(getComputedStyle(target).left, '0px');
  anim.currentTime = 1000;
  assert_equals(getComputedStyle(target).left, '100px');
}, 'steps(2, jump-none) easing with input progress less than 0');

</script>
</body>
