Bug 1274944 - Part 3: Test for setting spacing. draft
authorBoris Chiou <boris.chiou@gmail.com>
Thu, 01 Sep 2016 16:51:39 +0800
changeset 409870 9f26c76530ebaf8588623ba67deaee0f48e83492
parent 409800 f91c53dbd01c96c5d397ab9f97cbc388ea560d72
child 409871 2862e8eeee3e43bf7835ee49e0c9e12ba60f04d6
child 409872 2caf8c2edff4e8ea3530e797b3a19d46bebaa9df
push id28591
push userbmo:boris.chiou@gmail.com
push dateMon, 05 Sep 2016 11:06:39 +0000
bugs1274944
milestone51.0a1
Bug 1274944 - Part 3: Test for setting spacing. MozReview-Commit-ID: 5pMhC00vNIh
dom/animation/test/mochitest.ini
dom/animation/test/style/file_animation-setting-spacing.html
dom/animation/test/style/test_animation-setting-spacing.html
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/web-animations/animation-model/keyframe-effects/spacing-keyframes.html
testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/spacing.html
--- a/dom/animation/test/mochitest.ini
+++ b/dom/animation/test/mochitest.ini
@@ -43,16 +43,17 @@ support-files =
   mozilla/file_hide_and_show.html
   mozilla/file_partial_keyframes.html
   mozilla/file_spacing_property_order.html
   mozilla/file_transform_limits.html
   mozilla/file_underlying-discrete-value.html
   style/file_animation-seeking-with-current-time.html
   style/file_animation-seeking-with-start-time.html
   style/file_animation-setting-effect.html
+  style/file_animation-setting-spacing.html
   testcommon.js
 
 [css-animations/test_animations-dynamic-changes.html]
 [css-animations/test_animation-cancel.html]
 [css-animations/test_animation-computed-timing.html]
 [css-animations/test_animation-currenttime.html]
 [css-animations/test_animation-finish.html]
 [css-animations/test_animation-finished.html]
@@ -96,8 +97,9 @@ skip-if = (toolkit == 'gonk' && debug)
 [mozilla/test_partial_keyframes.html]
 [mozilla/test_set-easing.html]
 [mozilla/test_spacing_property_order.html]
 [mozilla/test_transform_limits.html]
 [mozilla/test_underlying-discrete-value.html]
 [style/test_animation-seeking-with-current-time.html]
 [style/test_animation-seeking-with-start-time.html]
 [style/test_animation-setting-effect.html]
+[style/test_animation-setting-spacing.html]
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/style/file_animation-setting-spacing.html
@@ -0,0 +1,111 @@
+<!doctype html>
+<head>
+<meta charset=utf-8>
+<title>Tests for setting spacing by using KeyframeEffect.spacing</title>
+<script src='../testcommon.js'></script>
+</head>
+<body>
+<script>
+'use strict';
+
+function calculateInterpolation(pacedDistances, values, progress) {
+  if (progress == 0.0) {
+    return values[0];
+  } else if (progress == 1.0) {
+    return values[valus.length - 1];
+  }
+
+  const cumDist = pacedDistances.reduce( (prev, curr) => {
+    prev.push(prev.length == 0 ? curr : curr + prev[prev.length - 1]);
+    return prev;
+  }, []);
+
+  const last = cumDist[cumDist.length - 1];
+  const offsets = cumDist.map( (curr) => { return curr / last; } );
+
+  let idx = 0;
+  for (let i = 0; i < offsets.length - 1; ++i) {
+    if (progress >= offsets[i] && progress < offsets[i + 1]) {
+      idx = i;
+      break;
+    }
+  }
+
+  const ratio = (progress - offsets[idx]) / (offsets[idx + 1] - offsets[idx]);
+  return values[idx] + ratio * (values[idx + 1] - values[idx]) + 'px';
+}
+
+promise_test(function(t) {
+  var target = addDiv(t);
+  var anim = target.animate([ { marginLeft: '0px' },
+                              { marginLeft: '-20px' },
+                              { marginLeft: '100px' },
+                              { marginLeft: '50px' } ],
+                            100 * MS_PER_SEC);
+
+  return anim.ready.then(function() {
+    anim.currentTime = 50 * MS_PER_SEC;
+    assert_equals(getComputedStyle(target).marginLeft, '40px',
+                  'computed value before setting a new spacing');
+
+    var dist = [0, 20, 120, 50];
+    var marginLeftValues = [0, -20, 100, 50];
+    anim.effect.spacing = 'paced(margin-left)';
+    assert_equals(getComputedStyle(target).marginLeft,
+                  calculateInterpolation(dist, marginLeftValues, 0.5),
+                  'computed value after setting a new spacing');
+  });
+}, 'Test for setting spacing from distribute to paced');
+
+promise_test(function(t) {
+  var target = addDiv(t);
+  var anim = target.animate([ { marginLeft: '0px' },
+                              { marginLeft: '-20px' },
+                              { marginLeft: '100px' },
+                              { marginLeft: '50px' } ],
+                            { duration: 100 * MS_PER_SEC,
+                              spacing: 'paced(margin-left)' });
+
+  return anim.ready.then(function() {
+    var dist = [0, 20, 120, 50];
+    var marginLeftValues = [0, -20, 100, 50];
+    anim.currentTime = 50 * MS_PER_SEC;
+    assert_equals(getComputedStyle(target).marginLeft,
+                  calculateInterpolation(dist, marginLeftValues, 0.5),
+                  'computed value before setting a new spacing');
+
+    anim.effect.spacing = 'distribute';
+    assert_equals(getComputedStyle(target).marginLeft, '40px',
+                  'computed value after setting a new spacing');
+  });
+}, 'Test for setting spacing from paced to distribute');
+
+promise_test(function(t) {
+  var target = addDiv(t);
+  var anim =
+    target.animate([ { marginLeft: '0px', borderRadius: '0%' },
+                     { marginLeft: '-20px', borderRadius: '50%' },
+                     { marginLeft: '100px', borderRadius: '25%' },
+                     { marginLeft: '50px', borderRadius: '100%' } ],
+                   { duration: 100 * MS_PER_SEC,
+                     spacing: 'paced(margin-left)' });
+
+  return anim.ready.then(function() {
+    var dist = [0, 20, 120, 50];
+    var marginLeftValues = [0, -20, 100, 50];
+    anim.currentTime = 50 * MS_PER_SEC;
+    assert_equals(getComputedStyle(target).marginLeft,
+                  calculateInterpolation(dist, marginLeftValues, 0.5),
+                  'computed value before setting a new spacing');
+
+    dist = [0, 50, 25, 75];
+    anim.effect.spacing = 'paced(border-radius)';
+    assert_equals(getComputedStyle(target).marginLeft,
+                  calculateInterpolation(dist, marginLeftValues, 0.5),
+                  'computed value after setting a new spacing');
+  });
+}, 'Test for setting spacing from paced to a different paced');
+
+done();
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/style/test_animation-setting-spacing.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<div id='log'></div>
+<script>
+'use strict';
+setup({explicit_done: true});
+SpecialPowers.pushPrefEnv(
+  { 'set': [['dom.animations-api.core.enabled', true]]},
+  function() {
+    window.open('file_animation-setting-spacing.html');
+  });
+</script>
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -37851,16 +37851,22 @@
           }
         ],
         "web-animations/interfaces/Animation/effect.html": [
           {
             "path": "web-animations/interfaces/Animation/effect.html",
             "url": "/web-animations/interfaces/Animation/effect.html"
           }
         ],
+        "web-animations/interfaces/KeyframeEffect/spacing.html": [
+          {
+            "path": "web-animations/interfaces/KeyframeEffect/spacing.html",
+            "url": "/web-animations/interfaces/KeyframeEffect/spacing.html"
+          }
+        ],
         "web-animations/timing-model/animation-effects/phases-and-states.html": [
           {
             "path": "web-animations/timing-model/animation-effects/phases-and-states.html",
             "url": "/web-animations/timing-model/animation-effects/phases-and-states.html"
           }
         ],
         "web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html": [
           {
--- a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/spacing-keyframes.html
+++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/spacing-keyframes.html
@@ -317,12 +317,75 @@ test(function(t) {
                 '2nd frame offset using distribute spacing');
   assert_equals(frames[3].computedOffset, 0.5 + 0.5 * 1 / 2,
                 '4th frame offset using distribute spacing because it is the ' +
                 'first paceable keyframe from a non-null offset keyframe');
 }, 'Test paced spacing only for keyframes specifying all some components, ' +
    'and falling back to distribute spacing for the reset with some specific ' +
    'offsets');
 
-// Bug 1276193: Test for mixing percent and pixel values.
+// Tests for setting spacing by KeyframeEffect.spacing.
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { marginLeft: '0px' },
+                                    { marginLeft: '-20px' },
+                                    { marginLeft: '100px' },
+                                    { marginLeft: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC });
+
+  anim.effect.spacing = 'paced(margin-left)';
+
+  var frames = anim.effect.getKeyframes();
+  var cumDist = [0, 20, 140, 190];
+  assert_equals(frames[0].computedOffset, 0.0,
+                '1st frame offset');
+  assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
+                '2nd frame offset');
+  assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
+                '3rd frame offset');
+  assert_equals(frames[3].computedOffset, 1.0,
+                'last frame offset');
+}, 'Test paced spacing by setter');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { marginLeft: '0px' },
+                                    { marginLeft: '-20px' },
+                                    { marginLeft: '100px' },
+                                    { marginLeft: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin-left)' });
+
+  anim.effect.spacing = 'distribute';
+
+  var frames = anim.effect.getKeyframes();
+  var slots = frames.length - 1;
+  assert_equals(frames[0].computedOffset, 0.0, '1st frame offset');
+  assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset');
+  assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset');
+  assert_equals(frames[3].computedOffset, 1.0, 'last frame offset');
+}, 'Test distribute spacing by setter');
+
+test(function(t) {
+  var anim =
+    createDiv(t).animate([ { marginLeft: '0px', borderRadius: '0%' },
+                           { marginLeft: '-20px', borderRadius: '50%' },
+                           { marginLeft: '100px', borderRadius: '25%' },
+                           { marginLeft: '50px', borderRadius: '100%' } ],
+                         { duration: 100 * MS_PER_SEC,
+                           spacing: 'paced(margin-left)' });
+
+  anim.effect.spacing = 'paced(border-radius)';
+
+  var frames = anim.effect.getKeyframes();
+  var cumDist = [0, 50, 50 + 25, 50 + 25 + 75];
+
+  assert_equals(frames[0].computedOffset, 0.0,
+                '1st frame offset');
+  assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
+                '2nd frame offset');
+  assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
+                '3rd frame offset');
+  assert_equals(frames[3].computedOffset, 1.0,
+                'last frame offset');
+}, 'Test paced spacing by changing the paced property');
 
 </script>
 </body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/spacing.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>KeyframeEffect spacing attribute tests</title>
+<link rel="help"
+      href="https://w3c.github.io/web-animations/#dom-keyframeeffect-spacing">
+<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 anim = createDiv(t).animate(null);
+  assert_throws(new TypeError, function() {
+    anim.effect.spacing = '';
+  });
+}, 'Test throwing TypeError if using empty string');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null);
+  assert_throws(new TypeError, function() {
+    anim.effect.spacing = 'dist';
+  });
+}, 'Test throwing TypeError if not using the correct keyword');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null);
+  anim.effect.spacing = 'paced(A)';
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test falling back to distribute spacing if using a unrecognized property');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null);
+  anim.effect.spacing = 'paced(--bg-color)';
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test falling back to distribute spacing if using CSS variables');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null);
+  anim.effect.spacing = 'paced(animation-duration)';
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test falling back to distribute spacing if using a non-animatable ' +
+   'property');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null);
+  anim.effect.spacing = 'distribute';
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test spacing value if setting distribute');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null);
+  anim.effect.spacing = 'paced(transform)';
+  assert_equals(anim.effect.spacing, 'paced(transform)', 'spacing mode');
+}, 'Test spacing value if setting paced');
+
+</script>
+</body>