diff options
Diffstat (limited to 'testing/web-platform/tests/css/css-contain/content-visibility/animation-display-lock.html')
-rw-r--r-- | testing/web-platform/tests/css/css-contain/content-visibility/animation-display-lock.html | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-contain/content-visibility/animation-display-lock.html b/testing/web-platform/tests/css/css-contain/content-visibility/animation-display-lock.html new file mode 100644 index 0000000000..7960ba0f59 --- /dev/null +++ b/testing/web-platform/tests/css/css-contain/content-visibility/animation-display-lock.html @@ -0,0 +1,188 @@ +<!DOCTYPE html> +<meta charset=utf8> +<title>Test getComputedStyle on a CSS animation in a display locked subtree</title> +<link rel="help" href="https://drafts.csswg.org/css-contain-2/"> +<script src="/web-animations/testcommon.js"></script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + #container { + content-visibility: visible; + contain: style layout paint; + contain-intrinsic-size: 0 100px; + } + @keyframes fade { + from { opacity: 1; } + to { opacity: 0; } + } + #target { + background: 'green'; + height: 100px; + width: 100px; + } + .animate { + animation: fade 1s linear 2 alternate; + } + .transition { + transition: opacity 1s linear; + } +</style> +<body> + <div id="container"></div> +</body> +<script> +"use strict"; + +function reset() { + const container = document.getElementById('container'); + const target = document.getElementById('target'); + container.style = ''; + container.removeChild(target); +} + +function createAnimatingElement(test, name) { + const container = document.getElementById('container'); + const target = document.createElement('div'); + container.appendChild(target); + target.id = 'target'; + target.className = name; + test.add_cleanup(() => { + reset(); + }); + return target; +} + +promise_test(async t => { + const container = document.getElementById('container'); + const target = createAnimatingElement(t, 'animate'); + let animationIterationEvent = false; + target.addEventListener('animationiteration', () => { + animationIterationEvent = true; + }); + const animation = target.getAnimations()[0]; + await animation.ready; + await waitForAnimationFrames(1); + container.style.contentVisibility = 'hidden'; + animation.currentTime = 1500; + assert_approx_equals( + parseFloat(getComputedStyle(target).opacity), 0.5, 1e-6, + 'Computed style is updated even when the animation is running in a ' + + 'display locked subtree'); + await waitForAnimationFrames(2); + assert_false(animationIterationEvent, + 'Animation events do not fire while the animation is ' + + 'running in a display locked subtree'); + container.style.contentVisibility = 'visible'; + await waitForAnimationFrames(2); + assert_true(animationIterationEvent, + 'The animationiteration event fires once the animation is ' + + 'no longer display locked'); +}, 'Animation events do not fire for a CSS animation running in a display ' + + 'locked subtree'); + +promise_test(async t => { + const container = document.getElementById('container'); + const target = createAnimatingElement(t, 'animate'); + const animation = target.getAnimations()[0]; + await animation.ready; + let finishedWhileDisplayLocked = false; + animation.finished.then(() => { + finishedWhileDisplayLocked = + getComputedStyle(container).contentVisibility == 'hidden'; + }); + await waitForAnimationFrames(1); + container.style.contentVisibility = 'hidden'; + // Advance to just shy of the effect end. + animation.currentTime = 1999; + assert_approx_equals( + parseFloat(getComputedStyle(target).opacity), 0.999, 1e-6, + 'Computed style is updated even when the animation is ' + + 'running in a display locked subtree'); + // Advancing frames should not resolve the finished promise. + await waitForAnimationFrames(3); + container.style.contentVisibility = 'visible'; + // Now we can resolve the finished promise. + await animation.finished; + assert_equals(finishedWhileDisplayLocked, false); +}, 'The finished promise does not resolve due to the normal passage of time ' + + 'for a CSS animation in a display locked subtree'); + +promise_test(async t => { + const container = document.getElementById('container'); + await waitForAnimationFrames(1); + const target = createAnimatingElement(t, 'transition'); + await waitForAnimationFrames(1); + target.style.opacity = 0; + const animation = target.getAnimations()[0]; + await animation.ready; + let finishedWhileDisplayLocked = false; + animation.finished.then(() => { + finishedWhileDisplayLocked = + getComputedStyle(container).contentVisibility == 'hidden'; + }); + await waitForAnimationFrames(1); + container.style.contentVisibility = 'hidden'; + // Advance to just shy of the effect end. + animation.currentTime = 999; + assert_approx_equals( + parseFloat(getComputedStyle(target).opacity), 0.001, 1e-6, + 'Computed style is updated even when the animation is ' + + 'running in a display locked subtree'); + // Advancing frames should not resolve the finished promise. + await waitForAnimationFrames(3); + container.style.contentVisibility = 'visible'; + // Now we can resolve the finished promise. + await animation.finished; + assert_equals(finishedWhileDisplayLocked, false); +}, 'The finished promise does not resolve due to the normal passage of time ' + + 'for a CSS transition in a display locked subtree'); + +promise_test(async t => { + const container = document.getElementById('container'); + const target = createAnimatingElement(t, 'animate'); + const animation = target.getAnimations()[0]; + target.className = ''; + container.style.contentVisibility = 'hidden'; + assert_equals(target.getAnimations().length, 0); + + // Though originally a CSS animation, it is no longer associated with + // CSS rules and no longer has an owning element. It now behaves like a + // programmatic web animation. Animation playback events (but not CSS + // animation events) should be dispatched and promises resolved despite + // being in a display locked subtree. + + let cssAnimationEndEvent = false; + target.addEventListener('animationend', () => { + cssAnimationEndEvent = true; + }); + + let animationFinishEvent = false; + animation.addEventListener('finish', () => { + animationFinishEvent = true; + }); + + let animationFinished = false; + animation.finished.then(() => { + animationFinished = true; + }); + + animation.play(); + assert_equals(target.getAnimations().length, 1); + + animation.currentTime = 1999; + await animation.ready; + await waitForAnimationFrames(2); + + assert_true(animationFinishEvent, + 'Animation event not blocked on display locked subtree if ' + + 'no owning element'); + assert_true(animationFinished, + 'Finished promise not blocked on display locked subtrtee if ' + + 'no owning element'); + assert_false(cssAnimationEndEvent, + 'CSS animation events should not be dispatched if there is no ' + + 'owning element'); +}, 'Events and promises are handled normally for animations without an ' + + 'owning element'); + +</script> |