diff options
Diffstat (limited to 'testing/web-platform/tests/scroll-animations/css/animation-timeline-named-scroll-progress-timeline.tentative.html')
-rw-r--r-- | testing/web-platform/tests/scroll-animations/css/animation-timeline-named-scroll-progress-timeline.tentative.html | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/testing/web-platform/tests/scroll-animations/css/animation-timeline-named-scroll-progress-timeline.tentative.html b/testing/web-platform/tests/scroll-animations/css/animation-timeline-named-scroll-progress-timeline.tentative.html new file mode 100644 index 0000000000..8dcf48c4ac --- /dev/null +++ b/testing/web-platform/tests/scroll-animations/css/animation-timeline-named-scroll-progress-timeline.tentative.html @@ -0,0 +1,431 @@ +<!DOCTYPE html> +<title>The animation-timeline: scroll-timeline-name</title> +<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1"> +<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/rewrite#scroll-timelines-named"> +<link rel="help" src="https://github.com/w3c/csswg-drafts/issues/6674"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/web-animations/testcommon.js"></script> +<script src="support/testcommon.js"></script> +<script src="/scroll-animations/scroll-timelines/testcommon.js"></script> +<style> + @keyframes anim { + from { translate: 50px; } + to { translate: 150px; } + } + @keyframes anim-2 { + from { z-index: 0; } + to { z-index: 100; } + } + + #target { + width: 100px; + height: 100px; + } + .square { + width: 100px; + height: 100px; + } + .square-container { + width: 300px; + height: 300px; + } + .scroller { + overflow: scroll; + } + .content { + inline-size: 100%; + block-size: 100%; + padding-inline-end: 100px; + padding-block-end: 100px; + } +</style> +<body> +<div id="log"></div> +<script> +"use strict"; + +setup(assert_implements_animation_timeline); + +function createScroller(t, scrollerSizeClass) { + let scroller = document.createElement('div'); + let className = scrollerSizeClass || 'square'; + scroller.className = `scroller ${className}`; + let content = document.createElement('div'); + content.className = 'content'; + + scroller.appendChild(content); + + t.add_cleanup(function() { + content.remove(); + scroller.remove(); + }); + + return scroller; +} + +function createTarget(t) { + let target = document.createElement('div'); + target.id = 'target'; + + t.add_cleanup(function() { + target.remove(); + }); + + return target; +} + +function createScrollerAndTarget(t, scrollerSizeClass) { + return [createScroller(t, scrollerSizeClass), createTarget(t)]; +} + +async function waitForScrollTop(scroller, percentage) { + const maxScroll = scroller.scrollHeight - scroller.clientHeight; + scroller.scrollTop = maxScroll * percentage / 100; + return waitForNextFrame(); +} + +async function waitForScrollLeft(scroller, percentage) { + const maxScroll = scroller.scrollWidth - scroller.clientWidth; + scroller.scrollLeft = maxScroll * percentage / 100; + return waitForNextFrame(); +} + +// ------------------------- +// Test scroll-timeline-name +// ------------------------- + +promise_test(async t => { + let target = document.createElement('div'); + target.id = 'target'; + target.className = 'scroller'; + let content = document.createElement('div'); + content.className = 'content'; + + // <div id='target' class='scroller'> + // <div id='content'></div> + // </div> + document.body.appendChild(target); + target.appendChild(content); + + target.style.scrollTimelineName = 'timeline'; + target.style.animation = "anim 10s linear"; + target.style.animationTimeline = 'timeline'; + + target.scrollTop = 50; // 50% + await waitForNextFrame(); + assert_equals(getComputedStyle(target).translate, '100px'); + + content.remove(); + target.remove(); +}, 'scroll-timeline-name is referenceable in animation-timeline on the ' + + 'declaring element itself'); + +promise_test(async t => { + let [parent, target] = createScrollerAndTarget(t, 'square-container'); + + // <div id='parent' class='scroller'> + // <div id='target'></div> + // <div id='content'></div> + // </div> + document.body.appendChild(parent); + parent.insertBefore(target, parent.firstElementChild); + + parent.style.scrollTimelineName = 'timeline'; + target.style.animation = "anim 10s linear"; + target.style.animationTimeline = 'timeline'; + + parent.scrollTop = 100; // 50% + await waitForNextFrame(); + assert_equals(getComputedStyle(target).translate, '100px'); +}, "scroll-timeline-name is referenceable in animation-timeline on that " + + "element's descendants"); + +// See https://github.com/w3c/csswg-drafts/issues/7047 +promise_test(async t => { + let [sibling, target] = createScrollerAndTarget(t); + + // <div id='sibling' class='scroller'> ... </div> + // <div id='target'></div> + document.body.appendChild(sibling); + document.body.appendChild(target); + + // Resolvable if using a deferred timeline, but otherwise can only resolve + // if an ancestor container of the target element. + sibling.style.scrollTimelineName = 'timeline'; + target.style.animation = "anim 10s linear"; + target.style.animationTimeline = 'timeline'; + + sibling.scrollTop = 50; // 50% + await waitForNextFrame(); + assert_equals(getComputedStyle(target).translate, '50px', + 'Animation with unknown timeline name holds current time at zero'); +}, "scroll-timeline-name is not referenceable in animation-timeline on that " + + "element's siblings"); + +promise_test(async t => { + let parent = document.createElement('div'); + parent.className = 'square'; + parent.style.overflowX = 'clip'; // This makes overflow-y be clip as well. + let target = document.createElement('div'); + target.id = 'target'; + + // <div id='parent' style='overflow-x: clip'>... + // <div id='target'></div> + // </div> + document.body.appendChild(parent); + parent.appendChild(target); + + parent.style.scrollTimelineName = 'timeline'; + target.style.animation = "anim 10s linear"; + target.style.animationTimeline = 'timeline'; + + await waitForNextFrame(); + assert_equals(getComputedStyle(target).translate, 'none', + 'Animation with an unresolved current time'); + + target.remove(); + parent.remove(); +}, 'scroll-timeline-name on an element which is not a scroll-container'); + +promise_test(async t => { + let [scroller, target] = createScrollerAndTarget(t); + + // <div id='scroller' class='scroller'> ... + // <div id='target'></div> + // </div> + + document.body.appendChild(scroller); + scroller.appendChild(target); + + scroller.style.scrollTimelineName = 'timeline-A'; + scroller.scrollTop = 50; // 25% + target.style.animation = "anim 10s linear"; + target.style.animationTimeline = 'timeline-B'; + + await waitForNextFrame(); + + const anim = target.getAnimations()[0]; + assert_true(!!anim, 'Failed to create animation'); + assert_equals(anim.timeline, null); + // Hold time of animation is zero. + assert_equals(getComputedStyle(target).translate, '50px'); + + scroller.style.scrollTimelineName = 'timeline-B'; + await waitForNextFrame(); + + assert_true(!!anim.timeline, 'Failed to create timeline'); + assert_equals(getComputedStyle(target).translate, '75px'); +}, 'Change in scroll-timeline-name to match animation timeline updates animation.'); + +promise_test(async t => { + let [scroller, target] = createScrollerAndTarget(t); + + // <div id='scroller' class='scroller'> ... + // <div id='target'></div> + // </div> + + document.body.appendChild(scroller); + scroller.appendChild(target); + + scroller.style.scrollTimelineName = 'timeline-A'; + scroller.scrollTop = 50; // 25% + target.style.animation = "anim 10s linear"; + target.style.animationTimeline = 'timeline-A'; + + await waitForNextFrame(); + + const anim = target.getAnimations()[0]; + assert_true(!!anim, 'Failed to create animation'); + assert_true(!!anim.timeline, 'Failed to create timeline'); + assert_equals(getComputedStyle(target).translate, '75px'); + assert_percents_equal(anim.startTime, 0); + assert_percents_equal(anim.currentTime, 25); + + scroller.style.scrollTimelineName = 'timeline-B'; + await waitForNextFrame(); + + // Switching to a null timeline pauses the animation. + assert_equals(anim.timeline, null, 'Failed to remove timeline'); + assert_equals(getComputedStyle(target).translate, '75px'); + assert_equals(anim.startTime, null); + assert_times_equal(anim.currentTime, 2500); +}, 'Change in scroll-timeline-name to no longer match animation timeline updates animation.'); + +promise_test(async t => { + let target = createTarget(t); + let scroller1 = createScroller(t); + let scroller2 = createScroller(t); + + target.style.animation = 'anim 10s linear'; + target.style.animationTimeline = 'timeline'; + scroller1.style.scrollTimelineName = 'timeline'; + scroller1.id = 'A'; + scroller2.id = 'B'; + + // <div class='scroller' id='A'> ... + // <div class='scroller' id='B'> ... + // <div id='target'></div> + // </div> + // </div> + document.body.appendChild(scroller1); + scroller1.appendChild(scroller2); + scroller2.appendChild(target); + + scroller1.style.scrollTimelineName = 'timeline'; + scroller1.scrollTop = 50; // 25% + scroller2.scrollTop = 100; // 50% + + await waitForNextFrame(); + + const anim = target.getAnimations()[0]; + + assert_true(!!anim.timeline, 'Failed to retrieve animation'); + assert_equals(anim.timeline.source.id, 'A'); + assert_equals(getComputedStyle(target).translate, '75px'); + + scroller2.style.scrollTimelineName = 'timeline'; + await waitForNextFrame(); + + // The timeline should be updated to scroller2. + assert_true(!!anim.timeline, 'Animation no longer has a timeline'); + assert_equals(anim.timeline.source.id, 'B', 'Timeline not updated'); + assert_equals(getComputedStyle(target).translate, '100px'); +}, 'Timeline lookup updates candidate when closer match available.'); + +promise_test(async t => { + let wrapper = createScroller(t); + wrapper.classList.remove('scroller'); + let target = createTarget(t); + + // <div id='wrapper'> ... + // <div id='target'></div> + // </div> + document.body.appendChild(wrapper); + wrapper.appendChild(target); + target.style.animation = "anim 10s linear"; + target.style.animationTimeline = 'timeline'; + + await waitForNextFrame(); + + // Timeline initially cannot be resolved, resulting in a null + // timeline. The animation's hold time is zero. + let anim = document.getAnimations()[0]; + assert_equals(getComputedStyle(target).translate, '50px'); + + await waitForNextFrame(); + + wrapper.classList.add('scroller'); + wrapper.style.scrollTimelineName = 'timeline'; + + // <div id='wrapper' class="scroller"> ... + // <div id='target'></div> + // </div> + wrapper.scrollTop = 50; // 25% + await waitForNextFrame(); + + // The timeline should be updated to scroller. + assert_equals(getComputedStyle(target).translate, '75px'); +}, 'Timeline lookup updates candidate when match becomes available.'); + + +// ------------------------- +// Test scroll-timeline-axis +// ------------------------- + +promise_test(async t => { + let [scroller, target] = createScrollerAndTarget(t); + scroller.style.writingMode = 'vertical-lr'; + + // <div id='scroller' class='scroller'> ... + // <div id='target'></div> + // </div> + document.body.appendChild(scroller); + scroller.appendChild(target); + + scroller.style.scrollTimeline = 'timeline block'; + target.style.animation = "anim-2 10s linear"; + target.style.animationTimeline = 'timeline'; + + await waitForScrollLeft(scroller, 50); + assert_equals(getComputedStyle(target).zIndex, '50'); +}, 'scroll-timeline-axis is block'); + +promise_test(async t => { + let [scroller, target] = createScrollerAndTarget(t); + scroller.style.writingMode = 'vertical-lr'; + + // <div id='scroller' class='scroller'> ... + // <div id='target'></div> + // </div> + document.body.appendChild(scroller); + scroller.appendChild(target); + + scroller.style.scrollTimeline = 'timeline inline'; + target.style.animation = "anim-2 10s linear"; + target.style.animationTimeline = 'timeline'; + + await waitForScrollTop(scroller, 50); + assert_equals(getComputedStyle(target).zIndex, '50'); +}, 'scroll-timeline-axis is inline'); + +promise_test(async t => { + let [scroller, target] = createScrollerAndTarget(t); + scroller.style.writingMode = 'vertical-lr'; + + // <div id='scroller' class='scroller'> ... + // <div id='target'></div> + // </div> + document.body.appendChild(scroller); + scroller.appendChild(target); + + scroller.style.scrollTimeline = 'timeline horizontal'; + target.style.animation = "anim-2 10s linear"; + target.style.animationTimeline = 'timeline'; + + await waitForScrollLeft(scroller, 50); + assert_equals(getComputedStyle(target).zIndex, '50'); +}, 'scroll-timeline-axis is horizontal'); + +promise_test(async t => { + let [scroller, target] = createScrollerAndTarget(t); + scroller.style.writingMode = 'vertical-lr'; + + // <div id='scroller' class='scroller'> ... + // <div id='target'></div> + // </div> + document.body.appendChild(scroller); + scroller.appendChild(target); + + scroller.style.scrollTimeline = 'timeline vertical'; + target.style.animation = "anim-2 10s linear"; + target.style.animationTimeline = 'timeline'; + + await waitForScrollTop(scroller, 50); + assert_equals(getComputedStyle(target).zIndex, '50'); +}, 'scroll-timeline-axis is vertical'); + +promise_test(async t => { + let [scroller, target] = createScrollerAndTarget(t); + + // <div id='scroller' class='scroller'> ... + // <div id='target'></div> + // </div> + document.body.appendChild(scroller); + scroller.appendChild(target); + + scroller.style.scrollTimeline = 'timeline block'; + target.style.animation = "anim-2 10s linear"; + target.style.animationTimeline = 'timeline'; + + await waitForScrollTop(scroller, 25); + await waitForScrollLeft(scroller, 75); + assert_equals(getComputedStyle(target).zIndex, '25'); + + scroller.style.scrollTimelineAxis = 'inline'; + await waitForNextFrame(); + assert_equals(getComputedStyle(target).zIndex, '75'); +}, 'scroll-timeline-axis is mutated'); + +</script> +</body> |