diff options
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.html | 266 |
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> |