--- a/dom/animation/test/chrome.ini
+++ b/dom/animation/test/chrome.ini
@@ -7,11 +7,12 @@ support-files =
[chrome/test_animate_xrays.html]
# file_animate_xrays.html needs to go in mochitest.ini since it is served
# over HTTP
[chrome/test_animation_observers.html]
[chrome/test_animation_performance_warning.html]
[chrome/test_animation_properties.html]
[chrome/test_generated_content_getAnimations.html]
+[chrome/test_observers_for_script_animation.html]
[chrome/test_restyles.html]
[chrome/test_running_on_compositor.html]
skip-if = buildapp == 'b2g'
--- a/dom/animation/test/chrome/test_animation_observers.html
+++ b/dom/animation/test/chrome/test_animation_observers.html
@@ -1517,193 +1517,55 @@ addAsyncAnimTest("tree_ordering", { obse
div.classList.remove("before");
div.classList.remove("after");
div.style = "";
childA.remove();
childB.remove();
extraStyle.remove();
});
-[ div, pseudoTarget ].forEach(function(target) {
- addAsyncAnimTest("change_duration_and_currenttime",
- { observe: div, subtree: true }, function*() {
- var anim = target.animate({ opacity: [ 0, 1 ] }, 200 * MS_PER_SEC);
-
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.effect.timing.duration = 100 * MS_PER_SEC;
- yield waitForFrame();
- assert_records([{ added: [], changed: [anim], removed: [] }],
- "records after duration is changed");
-
- anim.effect.timing.duration = 100 * MS_PER_SEC;
- yield waitForFrame();
- assert_records([], "records after assigning same value");
-
- anim.currentTime = anim.effect.timing.duration * 2;
- anim.finish();
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after animation end");
-
- anim.effect.timing.duration = anim.effect.timing.duration * 3;
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation restarted");
-
- anim.effect.timing.duration = "auto";
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after duration set \"auto\"");
-
- anim.effect.timing.duration = "auto";
- yield waitForFrame();
- assert_records([], "records after assigning same value \"auto\"");
-
- anim.cancel();
- yield waitForFrame();
- });
-});
-
-addAsyncAnimTest("change_enddelay_and_currenttime",
+addAsyncAnimTest("change_duration_and_currenttime",
{ observe: div, subtree: true }, function*() {
- var anim = div.animate({ opacity: [ 0, 1 ] }, { duration: 100 * MS_PER_SEC });
+ var anim = pseudoTarget.animate({ opacity: [ 0, 1 ] }, 200 * MS_PER_SEC);
yield waitForFrame();
assert_records([{ added: [anim], changed: [], removed: [] }],
"records after animation is added");
- anim.effect.timing.endDelay = 10 * MS_PER_SEC;
+ anim.effect.timing.duration = 100 * MS_PER_SEC;
yield waitForFrame();
assert_records([{ added: [], changed: [anim], removed: [] }],
- "records after endDelay is changed");
+ "records after duration is changed");
- anim.effect.timing.endDelay = 10 * MS_PER_SEC;
+ anim.effect.timing.duration = 100 * MS_PER_SEC;
yield waitForFrame();
assert_records([], "records after assigning same value");
- anim.currentTime = 109 * MS_PER_SEC;
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after currentTime during endDelay");
-
- anim.effect.timing.endDelay = -110 * MS_PER_SEC;
- yield waitForFrame();
- assert_records([], "records after assigning negative value");
-
- anim.cancel();
- yield waitForFrame();
-});
-
-addAsyncAnimTest("change_enddelay_and_currenttime",
- { observe: div, subtree: true }, function*() {
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 100 * MS_PER_SEC,
- endDelay: -100 * MS_PER_SEC });
- yield waitForFrame();
- assert_records([], "records after animation is added");
-});
-
-addAsyncAnimTest("change_iterations",
- { observe: div, subtree: true }, function*() {
- var anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
-
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.effect.timing.iterations = 2;
- yield waitForFrame();
- assert_records([{ added: [], changed: [anim], removed: [] }],
- "records after iterations is changed");
-
- anim.effect.timing.iterations = 2;
- yield waitForFrame();
- assert_records([], "records after assigning same value");
-
- anim.effect.timing.iterations = 0;
+ anim.currentTime = anim.effect.timing.duration * 2;
+ anim.finish();
yield waitForFrame();
assert_records([{ added: [], changed: [], removed: [anim] }],
"records after animation end");
- anim.effect.timing.iterations = Infinity;
+ anim.effect.timing.duration = anim.effect.timing.duration * 3;
yield waitForFrame();
assert_records([{ added: [anim], changed: [], removed: [] }],
"records after animation restarted");
- anim.cancel();
+ anim.effect.timing.duration = "auto";
yield waitForFrame();
assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after animation end");
-});
+ "records after duration set \"auto\"");
-addAsyncAnimTest("change_delay",
- { observe: div, subtree: true }, function*() {
- var anim = div.animate({ opacity: [ 0, 1 ] }, 100000);
-
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.effect.timing.delay = 100;
+ anim.effect.timing.duration = "auto";
yield waitForFrame();
- assert_records([{ added: [], changed: [anim], removed: [] }],
- "records after delay is changed");
-
- anim.effect.timing.delay = 100;
- yield waitForFrame();
- assert_records([], "records after assigning same value");
-
- anim.effect.timing.delay = -100000;
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after animation end");
-
- anim.effect.timing.delay = 0;
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation restarted");
+ assert_records([], "records after assigning same value \"auto\"");
anim.cancel();
yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after animation end");
-});
-
-addAsyncAnimTest("change_easing",
- { observe: div, subtree: true }, function*() {
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 100 * MS_PER_SEC,
- easing: "steps(2, start)" });
-
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.effect.timing.easing = "steps(2, end)";
- yield waitForFrame();
- assert_records([{ added: [], changed: [anim], removed: [] }],
- "records after easing is changed");
-
- anim.effect.timing.easing = "steps(2, end)";
- yield waitForFrame();
- assert_records([], "records after assigning same value");
-
- anim.cancel();
- yield waitForFrame();
-});
-
-addAsyncAnimTest("negative_delay_in_constructor",
- { observe: div, subtree: true }, function*() {
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 100, delay: -100 });
- yield waitForFrame();
- assert_records([], "records after assigning negative value");
});
addAsyncAnimTest("exclude_animations_targeting_pseudo_elements",
{ observe: div, subtree: false }, function*() {
var anim = div.animate({ opacity: [ 0, 1 ] },
{ duration: 100 * MS_PER_SEC });
var pAnim = pseudoTarget.animate({ opacity: [ 0, 1 ] },
{ duration: 100 * MS_PER_SEC });
@@ -1714,260 +1576,16 @@ addAsyncAnimTest("exclude_animations_tar
anim.finish();
pAnim.finish();
yield waitForFrame();
assert_records([{ added: [], changed: [], removed: [anim] }],
"records after animation is finished");
});
-addAsyncAnimTest("create_animation_without_target",
- { observe: document, subtree: true }, function*() {
- var effect = new KeyframeEffectReadOnly(null,
- { opacity: [ 0, 1 ] },
- { duration: 10000 });
- var anim = new Animation(effect, document.timeline);
- anim.play();
- yield waitForFrame();
- assert_records([], "no records after animation is added");
-
- anim.cancel();
- yield waitForFrame();
- assert_records([], "no records after animation is removed");
-});
-
-addAsyncAnimTest("set_animation_target",
- { observe: document, subtree: true }, function*() {
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 100 * MS_PER_SEC });
-
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.effect.target = null;
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after setting null");
-
- anim.effect.target = div;
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after setting a target");
-
- var newTarget = document.createElement("div");
- document.body.appendChild(newTarget);
- anim.effect.target = newTarget;
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] },
- { added: [anim], changed: [], removed: [] }],
- "records after setting a different target");
-
- anim.cancel();
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after animation ends");
-
- newTarget.remove();
-});
-
-addAsyncAnimTest("set_redundant_animation_target",
- { observe: div, subtree: true }, function*() {
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 100 * MS_PER_SEC });
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.effect.target = div;
- yield waitForFrame();
- assert_records([], "no records after setting the same target");
-
- anim.effect.target = null;
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after setting null");
-
- anim.effect.target = null;
- yield waitForFrame();
- assert_records([], "records after setting redundant null");
-
- anim.cancel();
- yield waitForFrame();
-});
-
-addAsyncAnimTest("set_null_animation_effect",
- { observe: div, subtree: true }, function*() {
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 100 * MS_PER_SEC });
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.effect = null;
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after animation is removed");
-
- anim.cancel();
- yield waitForFrame();
-});
-
-addAsyncAnimTest("set_effect_on_null_effect_animation",
- { observe: div, subtree: true }, function*() {
- var anim = new Animation();
- anim.play();
- anim.effect = new KeyframeEffect(div, { opacity: [ 0, 1 ] },
- 100 * MS_PER_SEC);
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.cancel();
- yield waitForFrame();
-});
-
-addAsyncAnimTest("replace_effect_targeting_on_the_same_element",
- { observe: div, subtree: true }, function*() {
- var anim = div.animate({ marginLeft: [ "0px", "100px" ] },
- 100 * MS_PER_SEC);
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.effect = new KeyframeEffect(div, { opacity: [ 0, 1 ] },
- 100 * MS_PER_SEC);
- yield waitForFrame();
- assert_records([{ added: [], changed: [anim], removed: [] }],
- "records after replace effects");
-
- anim.cancel();
- yield waitForFrame();
-});
-
-addAsyncAnimTest("replace_effect_targeting_on_the_same_element_not_in_effect",
- { observe: div, subtree: true }, function*() {
- var anim = div.animate({ marginLeft: [ "0px", "100px" ] },
- 100 * MS_PER_SEC);
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.currentTime = 60 * MS_PER_SEC;
- yield waitForFrame();
- assert_records([{ added: [], changed: [anim], removed: [] }],
- "records after animation is changed");
-
- anim.effect = new KeyframeEffect(div, { opacity: [ 0, 1 ] },
- 50 * MS_PER_SEC);
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after replacing effects");
-
- anim.cancel();
- yield waitForFrame();
-});
-
-addAsyncAnimTest("set_effect_with_previous_animation",
- { observe: div, subtree: true }, function*() {
- var child = document.createElement("div");
- div.appendChild(child);
-
- var anim1 = div.animate({ marginLeft: [ "0px", "50px" ] },
- 100 * MS_PER_SEC);
- var anim2 = child.animate({ marginLeft: [ "0px", "100px" ] },
- 50 * MS_PER_SEC);
- yield waitForFrame();
- assert_records([{ added: [anim1], changed: [], removed: [] },
- { added: [anim2], changed: [], removed: [] }],
- "records after animation is added");
-
- // After setting a new effect, we remove the current animation, anim1, because
- // it is no longer attached to |div|, and then remove the previous animation,
- // anim2. Finally, add back the anim1 which is in effect on |child| now.
- // In addition, we sort them by tree order and they are batched.
- anim1.effect = anim2.effect;
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim1] }, // div
- { added: [anim1], changed: [], removed: [anim2] }], // child
- "records after animation effects are changed");
-
- anim1.cancel();
- anim2.cancel();
- child.remove();
- yield waitForFrame();
-});
-
-addAsyncAnimTest("set_spacing",
- { observe: div, subtree: true }, function*() {
- var anim = div.animate([ { marginLeft: "0px" },
- { marginLeft: "-20px" },
- { marginLeft: "100px" },
- { marginLeft: "50px" } ],
- { duration: 100 * MS_PER_SEC });
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.effect.spacing = "paced(margin-left)";
- yield waitForFrame();
- assert_records([{ added: [], changed: [anim], removed: [] }],
- "records after animation is changed");
-
- anim.cancel();
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after animation end");
-});
-
-addAsyncAnimTest("set_spacing_on_a_non-animatable_property",
- { observe: div, subtree: true }, function*() {
- var anim = div.animate([ { marginLeft: "0px" },
- { marginLeft: "-20px" },
- { marginLeft: "100px" },
- { marginLeft: "50px" } ],
- { duration: 100 * MS_PER_SEC,
- spacing: "paced(margin-left)" });
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.effect.spacing = "paced(animation-duration)";
- yield waitForFrame();
- assert_records([{ added: [], changed: [anim], removed: [] }],
- "records after setting a non-animatable paced property");
-
- anim.cancel();
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after animation end");
-});
-
-addAsyncAnimTest("set_the_same_spacing",
- { observe: div, subtree: true }, function*() {
- var anim = div.animate([ { marginLeft: "0px" },
- { marginLeft: "-20px" },
- { marginLeft: "100px" },
- { marginLeft: "50px" } ],
- { duration: 100 * MS_PER_SEC,
- spacing: "paced(margin-left)" });
- yield waitForFrame();
- assert_records([{ added: [anim], changed: [], removed: [] }],
- "records after animation is added");
-
- anim.effect.spacing = "paced(margin-left)";
- yield waitForFrame();
- assert_records([], "no record after setting the same spacing");
-
- anim.cancel();
- yield waitForFrame();
- assert_records([{ added: [], changed: [], removed: [anim] }],
- "records after animation end");
-});
-
// Run the tests.
SimpleTest.requestLongerTimeout(2);
SimpleTest.waitForExplicitFinish();
runAllAsyncTests().then(function() {
SimpleTest.finish();
}, function(aError) {
ok(false, "Something failed: " + aError);
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/chrome/test_observers_for_script_animation.html
@@ -0,0 +1,433 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>
+Test chrome-only MutationObserver animation notifications for script
+animations
+</title>
+<script type="application/javascript" src="../testharness.js"></script>
+<script type="application/javascript" src="../testharnessreport.js"></script>
+<script type="application/javascript" src="../testcommon.js"></script>
+<div id="log"></div>
+<script>
+
+function assert_record_list(actual, expected, desc, index, listName) {
+ assert_equals(actual.length, expected.length,
+ `${desc} - record[${index}].${listName} length`);
+ if (actual.length != expected.length) {
+ return;
+ }
+ for (var i = 0; i < actual.length; i++) {
+ assert_not_equals(actual.indexOf(expected[i]), -1,
+ `${desc} - record[${index}].${listName} contains expected Animation`);
+ }
+}
+
+function assert_equals_records(actual, expected, desc) {
+ assert_equals(actual.length, expected.length, `${desc} - number of records`);
+ if (actual.length != expected.length) {
+ return;
+ }
+ for (var i = 0; i < actual.length; i++) {
+ assert_record_list(actual[i].addedAnimations,
+ expected[i].added, desc, i, "addedAnimations");
+ assert_record_list(actual[i].changedAnimations,
+ expected[i].changed, desc, i, "changedAnimations");
+ assert_record_list(actual[i].removedAnimations,
+ expected[i].removed, desc, i, "removedAnimations");
+ }
+}
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate({ opacity: [ 0, 1 ] }, 200 * MS_PER_SEC);
+
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.effect.timing.duration = 100 * MS_PER_SEC;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [anim], removed: [] }],
+ "records after duration is changed");
+
+ anim.effect.timing.duration = 100 * MS_PER_SEC;
+ assert_equals_records(observer.takeRecords(),
+ [], "records after assigning same value");
+
+ anim.currentTime = anim.effect.timing.duration * 2;
+ anim.finish();
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [], removed: [anim] }],
+ "records after animation end");
+
+ anim.effect.timing.duration = anim.effect.timing.duration * 3;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation restarted");
+
+ anim.effect.timing.duration = "auto";
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [], removed: [anim] }],
+ "records after duration set \"auto\"");
+
+ anim.effect.timing.duration = "auto";
+ assert_equals_records(observer.takeRecords(),
+ [], "records after assigning same value \"auto\"");
+}, "change_duration_and_currenttime");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
+
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.effect.timing.endDelay = 10 * MS_PER_SEC;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [anim], removed: [] }],
+ "records after endDelay is changed");
+
+ anim.effect.timing.endDelay = 10 * MS_PER_SEC;
+ assert_equals_records(observer.takeRecords(),
+ [], "records after assigning same value");
+
+ anim.currentTime = 109 * MS_PER_SEC;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [], removed: [anim] }],
+ "records after currentTime during endDelay");
+
+ anim.effect.timing.endDelay = -110 * MS_PER_SEC;
+ assert_equals_records(observer.takeRecords(),
+ [], "records after assigning negative value");
+}, "change_enddelay_and_currenttime");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate({ opacity: [ 0, 1 ] },
+ { duration: 100 * MS_PER_SEC,
+ endDelay: -100 * MS_PER_SEC });
+ assert_equals_records(observer.takeRecords(),
+ [], "records after animation is added");
+}, "zero_end_time");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
+
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.effect.timing.iterations = 2;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [anim], removed: [] }],
+ "records after iterations is changed");
+
+ anim.effect.timing.iterations = 2;
+ assert_equals_records(observer.takeRecords(),
+ [], "records after assigning same value");
+
+ anim.effect.timing.iterations = 0;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [], removed: [anim] }],
+ "records after animation end");
+
+ anim.effect.timing.iterations = Infinity;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation restarted");
+}, "change_iterations");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
+
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.effect.timing.delay = 100;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [anim], removed: [] }],
+ "records after delay is changed");
+
+ anim.effect.timing.delay = 100;
+ assert_equals_records(observer.takeRecords(),
+ [], "records after assigning same value");
+
+ anim.effect.timing.delay = -100 * MS_PER_SEC;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [], removed: [anim] }],
+ "records after animation end");
+
+ anim.effect.timing.delay = 0;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation restarted");
+}, "change_delay");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate({ opacity: [ 0, 1 ] },
+ { duration: 100 * MS_PER_SEC,
+ easing: "steps(2, start)" });
+
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.effect.timing.easing = "steps(2, end)";
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [anim], removed: [] }],
+ "records after easing is changed");
+
+ anim.effect.timing.easing = "steps(2, end)";
+ assert_equals_records(observer.takeRecords(),
+ [], "records after assigning same value");
+}, "change_easing");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate({ opacity: [ 0, 1 ] },
+ { duration: 100, delay: -100 });
+ assert_equals_records(observer.takeRecords(),
+ [], "records after assigning negative value");
+}, "negative_delay_in_constructor");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var effect = new KeyframeEffectReadOnly(null,
+ { opacity: [ 0, 1 ] },
+ { duration: 100 * MS_PER_SEC });
+ var anim = new Animation(effect, document.timeline);
+ anim.play();
+ assert_equals_records(observer.takeRecords(),
+ [], "no records after animation is added");
+}, "create_animation_without_target");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, document, true);
+
+ var anim = div.animate({ opacity: [ 0, 1 ] },
+ { duration: 100 * MS_PER_SEC });
+
+ var newTarget = document.createElement("div");
+
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.effect.target = null;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [], removed: [anim] }],
+ "records after setting null");
+
+ anim.effect.target = div;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after setting a target");
+
+ anim.effect.target = addDiv(t);
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [], removed: [anim] },
+ { added: [anim], changed: [], removed: [] }],
+ "records after setting a different target");
+}, "set_animation_target");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate({ opacity: [ 0, 1 ] },
+ { duration: 100 * MS_PER_SEC });
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.effect.target = div;
+ assert_equals_records(observer.takeRecords(),
+ [], "no records after setting the same target");
+
+ anim.effect.target = null;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [], removed: [anim] }],
+ "records after setting null");
+
+ anim.effect.target = null;
+ assert_equals_records(observer.takeRecords(),
+ [], "records after setting redundant null");
+}, "set_redundant_animation_target");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate({ opacity: [ 0, 1 ] },
+ { duration: 100 * MS_PER_SEC });
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.effect = null;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [], removed: [anim] }],
+ "records after animation is removed");
+}, "set_null_animation_effect");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = new Animation();
+ anim.play();
+ anim.effect = new KeyframeEffect(div, { opacity: [ 0, 1 ] },
+ 100 * MS_PER_SEC);
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+}, "set_effect_on_null_effect_animation");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate({ marginLeft: [ "0px", "100px" ] },
+ 100 * MS_PER_SEC);
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.effect = new KeyframeEffect(div, { opacity: [ 0, 1 ] },
+ 100 * MS_PER_SEC);
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [anim], removed: [] }],
+ "records after replace effects");
+}, "replace_effect_targeting_on_the_same_element");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate({ marginLeft: [ "0px", "100px" ] },
+ 100 * MS_PER_SEC);
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.currentTime = 60 * MS_PER_SEC;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [anim], removed: [] }],
+ "records after animation is changed");
+
+ anim.effect = new KeyframeEffect(div, { opacity: [ 0, 1 ] },
+ 50 * MS_PER_SEC);
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [], removed: [anim] }],
+ "records after replacing effects");
+}, "replace_effect_targeting_on_the_same_element_not_in_effect");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, true);
+
+ var child = document.createElement("div");
+ div.appendChild(child);
+
+ var anim1 = div.animate({ marginLeft: [ "0px", "50px" ] },
+ 100 * MS_PER_SEC);
+ var anim2 = child.animate({ marginLeft: [ "0px", "100px" ] },
+ 50 * MS_PER_SEC);
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim1], changed: [], removed: [] },
+ { added: [anim2], changed: [], removed: [] }],
+ "records after animation is added");
+
+ // After setting a new effect, we remove the current animation, anim1,
+ // because it is no longer attached to |div|, and then remove the previous
+ // animation, anim2. Finally, add back the anim1 which is in effect on
+ // |child| now. In addition, we sort them by tree order and they are
+ // batched.
+ anim1.effect = anim2.effect;
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [], removed: [anim1] }, // div
+ { added: [anim1], changed: [], removed: [anim2] }], // child
+ "records after animation effects are changed");
+}, "set_effect_with_previous_animation");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate([ { marginLeft: "0px" },
+ { marginLeft: "-20px" },
+ { marginLeft: "100px" },
+ { marginLeft: "50px" } ],
+ { duration: 100 * MS_PER_SEC });
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.effect.spacing = "paced(margin-left)";
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [anim], removed: [] }],
+ "records after animation is changed");
+}, "set_spacing");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate([ { marginLeft: "0px" },
+ { marginLeft: "-20px" },
+ { marginLeft: "100px" },
+ { marginLeft: "50px" } ],
+ { duration: 100 * MS_PER_SEC,
+ spacing: "paced(margin-left)" });
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.effect.spacing = "paced(animation-duration)";
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [], changed: [anim], removed: [] }],
+ "records after setting a non-animatable paced property");
+}, "set_spacing_on_a_non-animatable_property");
+
+test(t => {
+ var div = addDiv(t);
+ var observer = setupSynchronousObserver(t, div, false);
+
+ var anim = div.animate([ { marginLeft: "0px" },
+ { marginLeft: "-20px" },
+ { marginLeft: "100px" },
+ { marginLeft: "50px" } ],
+ { duration: 100 * MS_PER_SEC,
+ spacing: "paced(margin-left)" });
+ assert_equals_records(observer.takeRecords(),
+ [{ added: [anim], changed: [], removed: [] }],
+ "records after animation is added");
+
+ anim.effect.spacing = "paced(margin-left)";
+ assert_equals_records(observer.takeRecords(),
+ [], "no record after setting the same spacing");
+}, "set_the_same_spacing");
+
+</script>