summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/target.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/target.html')
-rw-r--r--testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/target.html266
1 files changed, 266 insertions, 0 deletions
diff --git a/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/target.html b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/target.html
new file mode 100644
index 0000000000..30b2ee6f0c
--- /dev/null
+++ b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/target.html
@@ -0,0 +1,266 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>KeyframeEffect.target and .pseudoElement</title>
+<link rel="help"
+ href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-target">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<style>
+ .before::before {content: 'foo'; display: inline-block;}
+ .after::after {content: 'bar'; display: inline-block;}
+ .pseudoa::before, .pseudoc::before {margin-left: 10px;}
+ .pseudob::before, .pseudoc::after {margin-left: 20px;}
+</style>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+const gKeyFrames = { 'marginLeft': ['0px', '100px'] };
+
+test(t => {
+ const div = createDiv(t);
+ const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
+ effect.target = div;
+
+ const anim = new Animation(effect, document.timeline);
+ anim.play();
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ assert_equals(getComputedStyle(div).marginLeft, '50px',
+ 'Value at 50% progress');
+}, 'Test setting target before constructing the associated animation');
+
+test(t => {
+ const div = createDiv(t);
+ div.style.marginLeft = '10px';
+ const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
+ const anim = new Animation(effect, document.timeline);
+ anim.play();
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ assert_equals(getComputedStyle(div).marginLeft, '10px',
+ 'Value at 50% progress before setting new target');
+ effect.target = div;
+ assert_equals(getComputedStyle(div).marginLeft, '50px',
+ 'Value at 50% progress after setting new target');
+}, 'Test setting target from null to a valid target');
+
+test(t => {
+ const div = createDiv(t);
+ div.style.marginLeft = '10px';
+ const anim = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ assert_equals(getComputedStyle(div).marginLeft, '50px',
+ 'Value at 50% progress before clearing the target')
+
+ anim.effect.target = null;
+ assert_equals(getComputedStyle(div).marginLeft, '10px',
+ 'Value after clearing the target')
+}, 'Test setting target from a valid target to null');
+
+test(t => {
+ const a = createDiv(t);
+ const b = createDiv(t);
+ a.style.marginLeft = '10px';
+ b.style.marginLeft = '20px';
+ const anim = a.animate(gKeyFrames, 100 * MS_PER_SEC);
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ assert_equals(getComputedStyle(a).marginLeft, '50px',
+ 'Value of 1st element (currently targeted) before ' +
+ 'changing the effect target');
+ assert_equals(getComputedStyle(b).marginLeft, '20px',
+ 'Value of 2nd element (currently not targeted) before ' +
+ 'changing the effect target');
+ anim.effect.target = b;
+ assert_equals(getComputedStyle(a).marginLeft, '10px',
+ 'Value of 1st element (currently not targeted) after ' +
+ 'changing the effect target');
+ assert_equals(getComputedStyle(b).marginLeft, '50px',
+ 'Value of 2nd element (currently targeted) after ' +
+ 'changing the effect target');
+
+ // This makes sure the animation property is changed correctly on new
+ // targeted element.
+ anim.currentTime = 75 * MS_PER_SEC;
+ assert_equals(getComputedStyle(b).marginLeft, '75px',
+ 'Value of 2nd target (currently targeted) after ' +
+ 'changing the animation current time.');
+}, 'Test setting target from a valid target to another target');
+
+promise_test(async t => {
+ const animation = createDiv(t).animate(
+ { opacity: 0 },
+ { duration: 1, fill: 'forwards' }
+ );
+
+ const foreignElement
+ = document.createElementNS('http://example.org/test', 'test');
+ document.body.appendChild(foreignElement);
+ t.add_cleanup(() => {
+ foreignElement.remove();
+ });
+
+ animation.effect.target = foreignElement;
+
+ // Wait a frame to make sure nothing bad happens when the UA tries to update
+ // style.
+ await waitForNextFrame();
+}, 'Target element can be set to a foreign element');
+
+// Pseudo-element tests
+// (testing target and pseudoElement in these cases)
+// Since blink uses separate code paths for handling pseudo-element styles
+// depending on whether content is set (putting the pseudo-element in the layout),
+// we run tests on both cases.
+for (const hasContent of [true, false]){
+ test(t => {
+ const d = createDiv(t);
+ d.classList.add('pseudoa');
+ if (hasContent) {
+ d.classList.add('before');
+ }
+
+ const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
+ const anim = new Animation(effect, document.timeline);
+ anim.play();
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ assert_equals(getComputedStyle(d, '::before').marginLeft, '10px',
+ 'Value at 50% progress before setting new target');
+ effect.target = d;
+ effect.pseudoElement = '::before';
+
+ assert_equals(effect.target, d, "Target element is set correctly");
+ assert_equals(effect.pseudoElement, '::before', "Target pseudo-element set correctly");
+ assert_equals(getComputedStyle(d, '::before').marginLeft, '50px',
+ 'Value at 50% progress after setting new target');
+ }, "Change target from null to " + (hasContent ? "an existing" : "a non-existing") +
+ " pseudoElement setting target first.");
+
+ test(t => {
+ const d = createDiv(t);
+ d.classList.add('pseudoa');
+ if (hasContent) {
+ d.classList.add('before');
+ }
+
+ const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
+ const anim = new Animation(effect, document.timeline);
+ anim.play();
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ assert_equals(getComputedStyle(d, '::before').marginLeft, '10px',
+ 'Value at 50% progress before setting new target');
+ effect.pseudoElement = '::before';
+ effect.target = d;
+
+ assert_equals(effect.target, d, "Target element is set correctly");
+ assert_equals(effect.pseudoElement, '::before', "Target pseudo-element set correctly");
+ assert_equals(getComputedStyle(d, '::before').marginLeft, '50px',
+ 'Value at 50% progress after setting new target');
+ }, "Change target from null to " + (hasContent ? "an existing" : "a non-existing") +
+ " pseudoElement setting pseudoElement first.");
+
+ test(t => {
+ const d = createDiv(t);
+ d.classList.add('pseudoa');
+ if (hasContent) {
+ d.classList.add('before');
+ }
+ const anim = d.animate(gKeyFrames, {duration: 100 * MS_PER_SEC, pseudoElement: '::before'});
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ anim.effect.pseudoElement = null;
+ assert_equals(anim.effect.target, d,
+ "Animation targets specified element (target element)");
+ assert_equals(anim.effect.pseudoElement, null,
+ "Animation targets specified element (null pseudo-selector)");
+ assert_equals(getComputedStyle(d, '::before').marginLeft, '10px',
+ 'Value of 1st element (currently not targeted) after ' +
+ 'changing the effect target');
+ assert_equals(getComputedStyle(d).marginLeft, '50px',
+ 'Value of 2nd element (currently targeted) after ' +
+ 'changing the effect target');
+ }, "Change target from " + (hasContent ? "an existing" : "a non-existing") + " pseudo-element to the originating element.");
+
+ for (const prevHasContent of [true, false]) {
+ test(t => {
+ const a = createDiv(t);
+ a.classList.add('pseudoa');
+ const b = createDiv(t);
+ b.classList.add('pseudob');
+ if (prevHasContent) {
+ a.classList.add('before');
+ }
+ if (hasContent) {
+ b.classList.add('before');
+ }
+
+ const anim = a.animate(gKeyFrames, {duration: 100 * MS_PER_SEC, pseudoElement: '::before'});
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ anim.effect.target = b;
+ assert_equals(anim.effect.target, b,
+ "Animation targets specified pseudo-element (target element)");
+ assert_equals(anim.effect.pseudoElement, '::before',
+ "Animation targets specified pseudo-element (pseudo-selector)");
+ assert_equals(getComputedStyle(a, '::before').marginLeft, '10px',
+ 'Value of 1st element (currently not targeted) after ' +
+ 'changing the effect target');
+ assert_equals(getComputedStyle(b, '::before').marginLeft, '50px',
+ 'Value of 2nd element (currently targeted) after ' +
+ 'changing the effect target');
+ }, "Change target from " + (prevHasContent ? "an existing" : "a non-existing") +
+ " to a different " + (hasContent ? "existing" : "non-existing") +
+ " pseudo-element by setting target.");
+
+ test(t => {
+ const d = createDiv(t);
+ d.classList.add('pseudoc');
+ if (prevHasContent) {
+ d.classList.add('before');
+ }
+ if (hasContent) {
+ d.classList.add('after');
+ }
+
+ const anim = d.animate(gKeyFrames, {duration: 100 * MS_PER_SEC, pseudoElement: '::before'});
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ anim.effect.pseudoElement = '::after';
+ assert_equals(anim.effect.target, d,
+ "Animation targets specified pseudo-element (target element)");
+ assert_equals(anim.effect.pseudoElement, '::after',
+ "Animation targets specified pseudo-element (pseudo-selector)");
+ assert_equals(getComputedStyle(d, '::before').marginLeft, '10px',
+ 'Value of 1st element (currently not targeted) after ' +
+ 'changing the effect target');
+ assert_equals(getComputedStyle(d, '::after').marginLeft, '50px',
+ 'Value of 2nd element (currently targeted) after ' +
+ 'changing the effect target');
+ }, "Change target from " + (prevHasContent ? "an existing" : "a non-existing") +
+ " to a different " + (hasContent ? "existing" : "non-existing") +
+ " pseudo-element by setting pseudoElement.");
+ }
+}
+
+for (const pseudo of [
+ '',
+ 'before',
+ ':abc',
+ '::abc',
+ '::placeholder',
+]) {
+ test(t => {
+ const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
+ assert_throws_dom("SyntaxError", () => effect.pseudoElement = pseudo );
+ }, `Changing pseudoElement to a non-null invalid pseudo-selector ` +
+ `'${pseudo}' throws a SyntaxError`);
+}
+
+</script>
+</body>