Bug 1049975 - Part 10: Test for writable effect. draft
authorBoris Chiou <boris.chiou@gmail.com>
Thu, 14 Jul 2016 17:16:18 +0800
changeset 405238 1411cca0001f4fc6acf2856255ff884b5d69b426
parent 405237 eba2506e124b88c35fd327f8f5b5d58bc0d247cf
child 405239 a7d08821c6bdcd19c5855a46dbe35339b664f0ad
push id27442
push userbmo:boris.chiou@gmail.com
push dateThu, 25 Aug 2016 04:26:27 +0000
bugs1049975
milestone51.0a1
Bug 1049975 - Part 10: Test for writable effect. MozReview-Commit-ID: 2hMY2barRb9
dom/animation/test/css-transitions/file_setting-effect.html
dom/animation/test/css-transitions/test_setting-effect.html
dom/animation/test/mochitest.ini
dom/animation/test/style/file_animation-setting-effect.html
dom/animation/test/style/test_animation-setting-effect.html
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/web-animations/interfaces/Animation/effect.html
testing/web-platform/tests/web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/css-transitions/file_setting-effect.html
@@ -0,0 +1,91 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src='../testcommon.js'></script>
+<body>
+<script>
+'use strict';
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.left = '0px';
+
+  div.style.transition = 'left 100s';
+  flushComputedStyle(div);
+  div.style.left = '100px';
+
+  var transition = div.getAnimations()[0];
+  return transition.ready.then(function() {
+    transition.currentTime = 50 * MS_PER_SEC;
+    transition.effect = null;
+    assert_equals(transition.transitionProperty, 'left');
+    assert_equals(transition.playState, 'finished');
+    assert_equals(window.getComputedStyle(div).left, '100px');
+  });
+}, 'Test for removing a transition effect');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.left = '0px';
+
+  div.style.transition = 'left 100s';
+  flushComputedStyle(div);
+  div.style.left = '100px';
+
+  var transition = div.getAnimations()[0];
+  return transition.ready.then(function() {
+    transition.currentTime = 50 * MS_PER_SEC;
+    transition.effect = new KeyframeEffect(div,
+                                           { marginLeft: [ '0px' , '100px'] },
+                                           100 * MS_PER_SEC);
+    assert_equals(transition.transitionProperty, 'left');
+    assert_equals(transition.playState, 'running');
+    assert_equals(window.getComputedStyle(div).left, '100px');
+    assert_equals(window.getComputedStyle(div).marginLeft, '50px');
+  });
+}, 'Test for replacing the transition effect by a new keyframe effect');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.left = '0px';
+  div.style.width = '0px';
+
+  div.style.transition = 'left 100s';
+  flushComputedStyle(div);
+  div.style.left = '100px';
+
+  var transition = div.getAnimations()[0];
+  return transition.ready.then(function() {
+    transition.currentTime = 50 * MS_PER_SEC;
+    transition.effect = new KeyframeEffect(div,
+                                           { marginLeft: [ '0px' , '100px'] },
+                                           20 * MS_PER_SEC);
+    assert_equals(transition.playState, 'finished');
+  });
+}, 'Test for setting a new keyframe effect with a shorter duration');
+
+promise_test(function(t) {
+  var div = addDiv(t);
+  div.style.left = '0px';
+  div.style.width = '0px';
+
+  div.style.transition = 'left 100s';
+  flushComputedStyle(div);
+  div.style.left = '100px';
+
+  var transition = div.getAnimations()[0];
+  assert_equals(transition.playState, 'pending');
+
+  transition.effect = new KeyframeEffect(div,
+                                         { marginLeft: [ '0px' , '100px'] },
+                                         100 * MS_PER_SEC);
+  assert_equals(transition.transitionProperty, 'left');
+  assert_equals(transition.playState, 'pending');
+
+  return transition.ready.then(function() {
+    assert_equals(transition.playState, 'running');
+  });
+}, 'Test for setting a new keyframe effect to a pending transition');
+
+done();
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/css-transitions/test_setting-effect.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_setting-effect.html');
+  });
+</script>
--- a/dom/animation/test/mochitest.ini
+++ b/dom/animation/test/mochitest.ini
@@ -29,28 +29,30 @@ support-files =
   css-transitions/file_animation-ready.html
   css-transitions/file_animation-starttime.html
   css-transitions/file_csstransition-transitionproperty.html
   css-transitions/file_document-get-animations.html
   css-transitions/file_effect-target.html
   css-transitions/file_element-get-animations.html
   css-transitions/file_keyframeeffect-getkeyframes.html
   css-transitions/file_pseudoElement-get-animations.html
+  css-transitions/file_setting-effect.html
   document-timeline/file_document-timeline.html
   mozilla/file_cubic_bezier_limits.html
   mozilla/file_deferred_start.html
   mozilla/file_disabled_properties.html
   mozilla/file_document-timeline-origin-time-range.html
   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
   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]
@@ -76,24 +78,26 @@ skip-if = buildapp == 'mulet'
 [css-transitions/test_animation-starttime.html]
 [css-transitions/test_csstransition-transitionproperty.html]
 [css-transitions/test_document-get-animations.html]
 [css-transitions/test_effect-target.html]
 [css-transitions/test_element-get-animations.html]
 skip-if = buildapp == 'mulet'
 [css-transitions/test_keyframeeffect-getkeyframes.html]
 [css-transitions/test_pseudoElement-get-animations.html]
+[css-transitions/test_setting-effect.html]
 [document-timeline/test_document-timeline.html]
 [document-timeline/test_request_animation_frame.html]
 skip-if = buildapp == 'mulet'
 [mozilla/test_cubic_bezier_limits.html]
 [mozilla/test_deferred_start.html]
 skip-if = (toolkit == 'gonk' && debug)
 [mozilla/test_disabled_properties.html]
 [mozilla/test_document-timeline-origin-time-range.html]
 [mozilla/test_hide_and_show.html]
 [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]
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/style/file_animation-setting-effect.html
@@ -0,0 +1,125 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset=utf-8>
+    <title>Tests for setting effects by using Animation.effect</title>
+    <script src='../testcommon.js'></script>
+  </head>
+  <body>
+    <script type='text/javascript'>
+
+'use strict';
+
+test(function(t) {
+  var target = addDiv(t);
+  var anim = new Animation();
+  anim.effect = new KeyframeEffectReadOnly(target,
+                                           { marginLeft: [ '0px', '100px' ] },
+                                           100 * MS_PER_SEC);
+  anim.currentTime = 50 * MS_PER_SEC;
+  assert_equals(getComputedStyle(target).marginLeft, '50px');
+}, 'After setting target effect on an animation with null effect, the ' +
+   'animation still works');
+
+test(function(t) {
+  var target = addDiv(t);
+  target.style.marginLeft = '10px';
+  var anim = target.animate({ marginLeft: [ '0px', '100px' ] },
+                            100 * MS_PER_SEC);
+  anim.currentTime = 50 * MS_PER_SEC;
+  assert_equals(getComputedStyle(target).marginLeft, '50px');
+
+  anim.effect = null;
+  assert_equals(getComputedStyle(target).marginLeft, '10px');
+}, 'After setting null target effect, the computed style of the target ' +
+   'element becomes the initial value');
+
+test(function(t) {
+  var target = addDiv(t);
+  var animA = target.animate({ marginLeft: [ '0px', '100px' ] },
+                             100 * MS_PER_SEC);
+  var animB = new Animation();
+  animA.currentTime = 50 * MS_PER_SEC;
+  animB.currentTime = 20 * MS_PER_SEC;
+  assert_equals(getComputedStyle(target).marginLeft, '50px',
+                'original computed style of the target element');
+
+  animB.effect = animA.effect;
+  assert_equals(getComputedStyle(target).marginLeft, '20px',
+                'new computed style of the target element');
+}, 'After setting the target effect from an existing animation, the computed ' +
+   'style of the target effect should reflect the time of the updated ' +
+   'animation.');
+
+test(function(t) {
+  var target = addDiv(t);
+  target.style.marginTop = '-10px';
+  var animA = target.animate({ marginLeft: [ '0px', '100px' ] },
+                             100 * MS_PER_SEC);
+  var animB = target.animate({ marginTop: [ '0px', '100px' ] },
+                             50 * MS_PER_SEC);
+  animA.currentTime = 50 * MS_PER_SEC;
+  animB.currentTime = 10 * MS_PER_SEC;
+  assert_equals(getComputedStyle(target).marginLeft, '50px',
+                'original margin-left of the target element');
+  assert_equals(getComputedStyle(target).marginTop, '20px',
+                'original margin-top of the target element');
+
+  animB.effect = animA.effect;
+  assert_equals(getComputedStyle(target).marginLeft, '10px',
+                'new margin-left of the target element');
+  assert_equals(getComputedStyle(target).marginTop, '-10px',
+                'new margin-top of the target element');
+}, 'After setting target effect with an animation to another animation which ' +
+   'also has an target effect and both animation effects target to the same ' +
+   'element, the computed style of this element should reflect the time and ' +
+   'effect of the animation that was set');
+
+test(function(t) {
+  var targetA = addDiv(t);
+  var targetB = addDiv(t);
+  targetB.style.marginLeft = '-10px';
+  var animA = targetA.animate({ marginLeft: [ '0px', '100px' ] },
+                              100 * MS_PER_SEC);
+  var animB = targetB.animate({ marginLeft: [ '0px', '100px' ] },
+                              50 * MS_PER_SEC);
+  animA.currentTime = 50 * MS_PER_SEC;
+  animB.currentTime = 10 * MS_PER_SEC;
+  assert_equals(getComputedStyle(targetA).marginLeft, '50px',
+                'original margin-left of the first element');
+  assert_equals(getComputedStyle(targetB).marginLeft, '20px',
+                'original margin-left of the second element');
+
+  animB.effect = animA.effect;
+  assert_equals(getComputedStyle(targetA).marginLeft, '10px',
+                'new margin-left of the first element');
+  assert_equals(getComputedStyle(targetB).marginLeft, '-10px',
+                'new margin-left of the second element');
+}, 'After setting target effect with an animation to another animation which ' +
+   'also has an target effect and these animation effects target to ' +
+   'different elements, the computed styles of the two elements should ' +
+   'reflect the time and effect of the animation that was set');
+
+test(function(t) {
+  var target = addDiv(t);
+  var animA = target.animate({ marginLeft: [ '0px', '100px' ] },
+                             50 * MS_PER_SEC);
+  var animB = target.animate({ marginTop: [ '0px', '50px' ] },
+                             100 * MS_PER_SEC);
+  animA.currentTime = 20 * MS_PER_SEC;
+  animB.currentTime = 30 * MS_PER_SEC;
+  assert_equals(getComputedStyle(target).marginLeft, '40px');
+  assert_equals(getComputedStyle(target).marginTop, '15px');
+
+  var effectA = animA.effect;
+  animA.effect = animB.effect;
+  animB.effect = effectA;
+  assert_equals(getComputedStyle(target).marginLeft, '60px');
+  assert_equals(getComputedStyle(target).marginTop, '10px');
+}, 'After swapping effects of two playing animations, both animations are ' +
+   'still running with the same current time');
+
+done();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/style/test_animation-setting-effect.html
@@ -0,0 +1,15 @@
+<!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-effect.html');
+  });
+</script>
+</html>
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -37663,22 +37663,34 @@
           }
         ],
         "html/semantics/forms/the-form-element/form-submission-sandbox.html": [
           {
             "path": "html/semantics/forms/the-form-element/form-submission-sandbox.html",
             "url": "/html/semantics/forms/the-form-element/form-submission-sandbox.html"
           }
         ],
+        "web-animations/interfaces/Animation/effect.html": [
+          {
+            "path": "web-animations/interfaces/Animation/effect.html",
+            "url": "/web-animations/interfaces/Animation/effect.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": [
+          {
+            "path": "web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html",
+            "url": "/web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html"
+          }
+        ],
         "web-animations/timing-model/animations/updating-the-finished-state.html": [
           {
             "path": "web-animations/timing-model/animations/updating-the-finished-state.html",
             "url": "/web-animations/timing-model/animations/updating-the-finished-state.html"
           }
         ]
       }
     },
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/web-animations/interfaces/Animation/effect.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animation.effect tests</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-effect">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+"use strict";
+
+test(function(t) {
+  var anim = new Animation();
+  assert_equals(anim.effect, null, "initial effect is null");
+
+  var newEffect = new KeyframeEffectReadOnly(createDiv(t), null);
+  anim.effect = newEffect;
+  assert_equals(anim.effect, newEffect, "new effect is set");
+}, "effect is set correctly.");
+
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Setting the target effect tests</title>
+<link rel='help' href='https://w3c.github.io/web-animations/#setting-the-target-effect'>
+<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';
+
+promise_test(function(t) {
+  var anim = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] },
+                                  100 * MS_PER_SEC);
+  assert_equals(anim.playState, 'pending');
+
+  var retPromise = anim.ready.then(function() {
+    assert_unreached('ready promise is fulfilled');
+  }).catch(function(err) {
+    assert_equals(err.name, 'AbortError',
+                  'ready promise is rejected with AbortError');
+  });
+
+  anim.effect = null;
+  assert_equals(anim.playState, 'paused');
+
+  return retPromise;
+}, 'If new effect is null and old effect is not null, we reset the pending ' +
+   'tasks and ready promise is rejected');
+
+promise_test(function(t) {
+  var anim = new Animation();
+  anim.pause();
+  assert_equals(anim.playState, 'pending');
+
+  anim.effect = new KeyframeEffectReadOnly(createDiv(t),
+                                           { marginLeft: [ '0px', '100px' ] },
+                                           100 * MS_PER_SEC);
+  assert_equals(anim.playState, 'pending');
+
+  return anim.ready.then(function() {
+    assert_equals(anim.playState, 'paused');
+  });
+}, 'If animation has a pending pause task, reschedule that task to run ' +
+   'as soon as animation is ready.');
+
+promise_test(function(t) {
+  var anim = new Animation();
+  anim.play();
+  assert_equals(anim.playState, 'pending');
+
+  anim.effect = new KeyframeEffectReadOnly(createDiv(t),
+                                           { marginLeft: [ '0px', '100px' ] },
+                                           100 * MS_PER_SEC);
+  assert_equals(anim.playState, 'pending');
+
+  return anim.ready.then(function() {
+    assert_equals(anim.playState, 'running');
+  });
+}, 'If animation has a pending play task, reschedule that task to run ' +
+   'as soon as animation is ready to play new effect.');
+
+promise_test(function(t) {
+  var animA = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] },
+                                   100 * MS_PER_SEC);
+  var animB = new Animation();
+
+  return animA.ready.then(function() {
+    animB.effect = animA.effect;
+    assert_equals(animA.effect, null);
+    assert_equals(animA.playState, 'finished');
+  });
+}, 'When setting the effect of an animation to the effect of an existing ' +
+   'animation, the existing animation\'s target effect should be set to null.');
+
+test(function(t) {
+  var animA = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] },
+                                   100 * MS_PER_SEC);
+  var animB = new Animation();
+  var effect = animA.effect;
+  animA.currentTime = 50 * MS_PER_SEC;
+  animB.currentTime = 20 * MS_PER_SEC;
+  assert_equals(effect.getComputedTiming().progress, 0.5,
+                'Original timing comes from first animation');
+  animB.effect = effect;
+  assert_equals(effect.getComputedTiming().progress, 0.2,
+                'After setting the effect on a different animation, ' +
+                'it uses the new animation\'s timing');
+}, 'After setting the target effect of animation to the target effect of an ' +
+   'existing animation, the target effect\'s timing is updated to reflect ' +
+   'the current time of the new animation.');
+
+</script>
+</body>