summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/scroll-animations/css/animation-timeline-named-scroll-progress-timeline.tentative.html
diff options
context:
space:
mode:
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.html431
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>