Bug 1049975 - Part 10: Test for writable effect. r=birtles
authorBoris Chiou <boris.chiou@gmail.com>
Thu, 14 Jul 2016 17:16:18 +0800
changeset 354594 1a3f2e5f456b63aafef1eba805eede9d00ec4a39
parent 354593 af6ce54ce3bffb797d6e932f51ed39b893d7783c
child 354595 cd68ccd6bf2de37f3cc8a73db290940268c7d199
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs1049975
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1049975 - Part 10: Test for writable effect. r=birtles 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>