diff options
Diffstat (limited to 'testing/web-platform/tests/scroll-animations/scroll-timelines/scroll-timeline-invalidation.html')
-rw-r--r-- | testing/web-platform/tests/scroll-animations/scroll-timelines/scroll-timeline-invalidation.html | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/testing/web-platform/tests/scroll-animations/scroll-timelines/scroll-timeline-invalidation.html b/testing/web-platform/tests/scroll-animations/scroll-timelines/scroll-timeline-invalidation.html new file mode 100644 index 0000000000..a26500989e --- /dev/null +++ b/testing/web-platform/tests/scroll-animations/scroll-timelines/scroll-timeline-invalidation.html @@ -0,0 +1,133 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>ScrollTimeline invalidation</title> +<link rel="help" href="https://wicg.github.io/scroll-animations/#current-time-algorithm"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/web-animations/testcommon.js"></script> +<script src="testcommon.js"></script> +<style> + .scroller { + overflow: auto; + height: 100px; + width: 100px; + will-change: transform; + } + .contents { + height: 1000px; + width: 100%; + } +</style> +<div id="log"></div> + +<script> +'use strict'; + +promise_test(async t => { + const animation = createScrollLinkedAnimation(t); + const effect_duration = 350; + animation.effect.updateTiming({ duration: effect_duration }); + const scroller = animation.timeline.source; + let maxScroll = scroller.scrollHeight - scroller.clientHeight; + scroller.scrollTop = 0.2 * maxScroll; + const initial_progress = (scroller.scrollTop / maxScroll) * 100; + + animation.play(); + await animation.ready; + + // Animation current time is at 20% because scroller was scrolled to 20% + assert_percents_equal(animation.currentTime, 20); + assert_equals(scroller.scrollTop, 180); + assert_equals(maxScroll, 900); + + // Shrink scroller content size (from 1000 to 500). + // scroller.scrollTop maintains the same offset, which means shrinking the + // content has the effect of skipping the animation forward. + scroller.firstChild.style.height = "500px"; + maxScroll = scroller.scrollHeight - scroller.clientHeight; + + assert_equals(scroller.scrollTop, 180); + assert_equals(maxScroll, 400); + await waitForNextFrame(); + + const expected_progress = (scroller.scrollTop / maxScroll) * 100; + assert_true(expected_progress > initial_progress) + // @ 45% + assert_percents_equal(animation.currentTime, expected_progress); + assert_percents_equal(animation.timeline.currentTime, expected_progress); + assert_percents_equal(animation.effect.getComputedTiming().localTime, expected_progress); +}, 'Animation current time and effect local time are updated after scroller ' + + 'content size changes.'); + +promise_test(async t => { + const animation = createScrollLinkedAnimation(t); + animation.effect.updateTiming({ duration: 350 }); + const scroller = animation.timeline.source; + let maxScroll = scroller.scrollHeight - scroller.clientHeight; + const scrollOffset = 0.2 * maxScroll + scroller.scrollTop = scrollOffset; + const initial_progress = (scroller.scrollTop / maxScroll) * 100; + + animation.play(); + await animation.ready; + + // Animation current time is at 20% because scroller was scrolled to 20% + // assert_equals(animation.currentTime.value, 20); + assert_percents_equal(animation.currentTime, 20); + assert_equals(scroller.scrollTop, scrollOffset); + assert_equals(maxScroll, 900); + + // Change scroller size. + scroller.style.height = "500px"; + maxScroll = scroller.scrollHeight - scroller.clientHeight; + + assert_equals(scroller.scrollTop, scrollOffset); + assert_equals(maxScroll, 500); + await waitForNextFrame(); + + const expected_progress = (scroller.scrollTop / maxScroll) * 100; + assert_true(expected_progress > initial_progress); + // @ 45% + assert_percents_equal(animation.currentTime, expected_progress); + assert_percents_equal(animation.timeline.currentTime, expected_progress); + assert_percents_equal(animation.effect.getComputedTiming().localTime, + expected_progress); +}, 'Animation current time and effect local time are updated after scroller ' + + 'size changes.'); + +promise_test(async t => { + await waitForNextFrame(); + + const timeline = createScrollTimeline(t); + const scroller = timeline.source; + const maxScroll = scroller.scrollHeight - scroller.clientHeight; + // Instantiate scroll animation that resizes its scroll timeline scroller. + const animation = new Animation( + new KeyframeEffect( + timeline.source.firstChild, + [{ height: '1000px', easing: 'steps(2, jump-none)'}, + { height: '2000px' }], + ), timeline); + + animation.play(); + await animation.ready; + + assert_percents_equal(timeline.currentTime, 0); + assert_equals(scroller.scrollHeight, 1000); + + await runAndWaitForFrameUpdate(() => { + scroller.scrollTop = 0.6 * maxScroll; + }); + + // Applying the animation effect alters the height of the scroll content and + // makes the scroll timeline stale. + // https://github.com/w3c/csswg-drafts/issues/8694 + + // With a single layout, timeline current time would be at 60%, but the + // timeline would be stale. + const expected_progress = 60 * maxScroll / (maxScroll + 1000); + assert_approx_equals(timeline.currentTime.value, expected_progress, 0.1); + +}, 'If scroll animation resizes its scroll timeline scroller, ' + + 'layout reruns once per frame.'); +</script> |