Bug 1370123 - Add tests for Element.animate when used on an element in a document without a browsing context; r?xidorn
MozReview-Commit-ID: FL37UKP6s3k
--- a/dom/animation/test/mochitest.ini
+++ b/dom/animation/test/mochitest.ini
@@ -35,27 +35,29 @@ support-files =
css-transitions/file_document-get-animations.html
css-transitions/file_effect-target.html
css-transitions/file_element-get-animations.html
css-transitions/file_event-dispatch.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/xhr_doc.html
mozilla/file_cubic_bezier_limits.html
mozilla/file_deferred_start.html
mozilla/file_disabled_properties.html
mozilla/file_disable_animations_api_core.html
mozilla/file_discrete-animations.html
mozilla/file_document-timeline-origin-time-range.html
mozilla/file_hide_and_show.html
+ mozilla/file_restyling_xhr_doc.html
+ mozilla/file_set-easing.html
mozilla/file_transform_limits.html
mozilla/file_transition_finish_on_compositor.html
mozilla/file_underlying-discrete-value.html
- mozilla/file_set-easing.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_composite.html
style/file_missing-keyframe.html
style/file_missing-keyframe-on-compositor.html
../../../layout/style/test/property_database.js
testcommon.js
@@ -101,16 +103,17 @@ support-files =
[mozilla/test_cubic_bezier_limits.html]
[mozilla/test_deferred_start.html]
[mozilla/test_disable_animations_api_core.html]
[mozilla/test_disabled_properties.html]
[mozilla/test_discrete-animations.html]
[mozilla/test_document-timeline-origin-time-range.html]
[mozilla/test_hide_and_show.html]
[mozilla/test_moz-prefixed-properties.html]
+[mozilla/test_restyling_xhr_doc.html]
[mozilla/test_set-easing.html]
[mozilla/test_transform_limits.html]
[mozilla/test_transition_finish_on_compositor.html]
skip-if = toolkit == 'android'
[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/mozilla/file_restyling_xhr_doc.html
@@ -0,0 +1,86 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="../testcommon.js"></script>
+<script>
+'use strict';
+
+// This test supplements the web-platform-tests in:
+//
+// web-animations/interfaces/Animatable/animate-no-browsing-context.html
+//
+// Specifically, it covers the case where we have a running animation
+// targetting an element in a document without a browsing context.
+//
+// Currently the behavior in this case is not well-defined. For example,
+// if we were to simply take an element from such a document, and do:
+//
+// const xdoc = xhr.responseXML;
+// const div = xdoc.getElementById('test');
+// div.style.opacity = '0';
+// alert(getComputedStyle(div).opacity);
+//
+// We'd get '0' in Firefox and Edge, but an empty string in Chrome.
+//
+// However, if instead of using the style attribute, we set style in a <style>
+// element in *either* the document we're calling from *or* the XHR doc and
+// do the same we get '1' in Firefox and Edge, but an empty string in Chrome.
+//
+// That is, no browser appears to apply styles to elements in a document without
+// a browsing context unless the styles are defined using the style attribute,
+// and even then Chrome does not.
+//
+// There is some prose in CSSOM which says,
+//
+// Note: This means that even if obj is in a different document (e.g. one
+// fetched via XMLHttpRequest) it will still use the style rules associated
+// with the document that is associated with the global object on which
+// getComputedStyle() was invoked to compute the CSS declaration block.[1]
+//
+// However, this text has been around since at least 2013 and does not appear
+// to be implemented.
+//
+// As a result, it's not really possible to write a cross-browser test for the
+// behavior for animations in this context since it's not clear what the result
+// should be. That said, we still want to exercise this particular code path so
+// we make this case a Mozilla-specific test. The other similar tests cases for
+// which the behavior is well-defined are covered by web-platform-tests.
+//
+// [1] https://drafts.csswg.org/cssom/#extensions-to-the-window-interface
+
+function getXHRDoc(t) {
+ return new Promise(resolve => {
+ const xhr = new XMLHttpRequest();
+ xhr.open('GET', 'xhr_doc.html');
+ xhr.responseType = 'document';
+ xhr.onload = t.step_func(() => {
+ assert_equals(xhr.readyState, xhr.DONE,
+ 'Request should complete successfully');
+ assert_equals(xhr.status, 200,
+ 'Response should be OK');
+ resolve(xhr.responseXML);
+ });
+ xhr.send();
+ });
+}
+
+promise_test(t => {
+ let anim;
+ return getXHRDoc(t).then(xhrdoc => {
+ const div = xhrdoc.getElementById('test');
+ anim = div.animate({ opacity: [ 0, 1 ] }, 1000);
+ // Give the animation an active timeline and kick-start it.
+ anim.timeline = document.timeline;
+ anim.startTime = document.timeline.currentTime;
+ assert_equals(anim.playState, 'running',
+ 'The animation should be running');
+ // Gecko currently skips applying animation styles to elements in documents
+ // without browsing contexts.
+ assert_not_equals(getComputedStyle(div).opacity, '0',
+ 'Style should NOT be updated');
+ });
+}, 'Forcing an animation targetting an element in a document without a'
+ + ' browsing context to play does not cause style to update');
+
+done();
+
+</script>
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/mozilla/test_restyling_xhr_doc.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_restyling_xhr_doc.html");
+ });
+</script>
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/mozilla/xhr_doc.html
@@ -0,0 +1,2 @@
+<!doctype html>
+<div id=test></div>
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -67081,16 +67081,21 @@
{}
]
],
"web-animations/resources/keyframe-utils.js": [
[
{}
]
],
+ "web-animations/resources/xhr-doc.py": [
+ [
+ {}
+ ]
+ ],
"web-animations/testcommon.js": [
[
{}
]
],
"web-nfc/OWNERS": [
[
{}
@@ -129920,16 +129925,22 @@
]
],
"web-animations/animation-model/keyframe-effects/effect-value-visibility.html": [
[
"/web-animations/animation-model/keyframe-effects/effect-value-visibility.html",
{}
]
],
+ "web-animations/interfaces/Animatable/animate-no-browsing-context.html": [
+ [
+ "/web-animations/interfaces/Animatable/animate-no-browsing-context.html",
+ {}
+ ]
+ ],
"web-animations/interfaces/Animatable/animate.html": [
[
"/web-animations/interfaces/Animatable/animate.html",
{}
]
],
"web-animations/interfaces/Animatable/getAnimations.html": [
[
@@ -220345,16 +220356,20 @@
"web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html": [
"a0f0dc7d2f4833a68c6f8a5f908c498b05c6b22e",
"testharness"
],
"web-animations/animation-model/keyframe-effects/effect-value-visibility.html": [
"b01c7c5145c183fdca80dec4ca1966b0f72a7003",
"testharness"
],
+ "web-animations/interfaces/Animatable/animate-no-browsing-context.html": [
+ "3a5538db728127970721e20e3b2eaea59fac3afc",
+ "testharness"
+ ],
"web-animations/interfaces/Animatable/animate.html": [
"5f50ca1e8ab1fecdc6594310b4e386eec4738c6b",
"testharness"
],
"web-animations/interfaces/Animatable/getAnimations.html": [
"92503fce725fcffce188df9c8e1da9d9ca281213",
"testharness"
],
@@ -220513,16 +220528,20 @@
"web-animations/resources/easing-tests.js": [
"5ef1183a4d3e12ad3edfe678c9fa002e7edce888",
"support"
],
"web-animations/resources/keyframe-utils.js": [
"2903e56e508f7034e1918b5688c8a605db9bae51",
"support"
],
+ "web-animations/resources/xhr-doc.py": [
+ "de68c45fc1d38a49946f9046f34031e9278a1531",
+ "support"
+ ],
"web-animations/testcommon.js": [
"d057ad66c4561ef32f83770e4948f2019da89d48",
"support"
],
"web-animations/timing-model/animation-effects/active-time.html": [
"42eb1a23e89ae60ccd0a3664a9a583df1eb30d49",
"testharness"
],
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/web-animations/interfaces/Animatable/animate-no-browsing-context.html
@@ -0,0 +1,108 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Animatable.animate tests in combination with elements in documents
+ without a browsing context</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animatable-animate">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<div id="log"></div>
+<script>
+'use strict';
+
+//
+// The following tests relate to animations on elements in documents without
+// a browsing context. This is NOT the same as documents that are not bound to
+// a document tree.
+//
+
+function getXHRDoc(t) {
+ return new Promise(resolve => {
+ const xhr = new XMLHttpRequest();
+ xhr.open('GET', '../../resources/xhr-doc.py');
+ xhr.responseType = 'document';
+ xhr.onload = t.step_func(() => {
+ assert_equals(xhr.readyState, xhr.DONE,
+ 'Request should complete successfully');
+ assert_equals(xhr.status, 200,
+ 'Response should be OK');
+ resolve(xhr.responseXML);
+ });
+ xhr.send();
+ });
+}
+
+promise_test(t => {
+ return getXHRDoc(t).then(xhrdoc => {
+ const div = xhrdoc.getElementById('test');
+ const anim = div.animate(null);
+ assert_class_string(anim.timeline, 'DocumentTimeline',
+ 'Animation should have a timeline');
+ assert_equals(anim.timeline, xhrdoc.timeline,
+ 'Animation timeline should be the default document timeline'
+ + ' of the XHR doc');
+ assert_not_equals(anim.timeline, document.timeline,
+ 'Animation timeline should NOT be the same timeline as'
+ + ' the default document timeline for the current'
+ + ' document');
+
+ });
+}, 'Element.animate() creates an animation with the correct timeline'
+ + ' when called on an element in a document without a browsing context');
+
+//
+// The following tests are cross-cutting tests that are not specific to the
+// Animatable.animate() interface. Instead, they draw on assertions from
+// various parts of the spec. These assertions are tested in other tests
+// but are repeated here to confirm that user agents are not doing anything
+// different in the particular case of document without a browsing context.
+//
+
+promise_test(t => {
+ return getXHRDoc(t).then(xhrdoc => {
+ const div = xhrdoc.getElementById('test');
+ const anim = div.animate(null);
+ // Since a document from XHR will not be active by itself, its document
+ // timeline will also be inactive.
+ assert_equals(anim.timeline.currentTime, null,
+ 'Document timeline time should be null');
+ });
+}, 'The timeline associated with an animation trigger on an element in'
+ + ' a document without a browsing context is inactive');
+
+promise_test(t => {
+ let anim;
+ return getXHRDoc(t).then(xhrdoc => {
+ const div = xhrdoc.getElementById('test');
+ anim = div.animate(null);
+ anim.timeline = document.timeline;
+ assert_equals(anim.playState, 'pending',
+ 'The animation should be initially pending');
+ return waitForAnimationFrames(2);
+ }).then(() => {
+ // Because the element is in a document without a browsing context, it will
+ // not be rendered and hence the user agent will never deem it ready to
+ // animate.
+ assert_equals(anim.playState, 'pending',
+ 'The animation should still be pending after replacing'
+ + ' the document timeline');
+ });
+}, 'Replacing the timeline of an animation targetting an element in a'
+ + ' document without a browsing context leaves it in the pending state');
+
+promise_test(t => {
+ let anim;
+ return getXHRDoc(t).then(xhrdoc => {
+ const div = xhrdoc.getElementById('test');
+ anim = div.animate({ opacity: [ 0, 1 ] }, 1000);
+ anim.timeline = document.timeline;
+ document.body.appendChild(div);
+ assert_equals(getComputedStyle(div).opacity, '0',
+ 'Style should be updated');
+ });
+}, 'Replacing the timeline of an animation targetting an element in a'
+ + ' document without a browsing context and then adopting that element'
+ + ' causes it to start updating style');
+
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/web-animations/resources/xhr-doc.py
@@ -0,0 +1,5 @@
+def main(request, response):
+ headers = [("Content-type", "text/html;charset=utf-8")]
+ content = "<!doctype html><div id=test></div>"
+
+ return headers, content