diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /testing/web-platform/tests/scroll-animations/view-timelines/timeline-offset-in-keyframe.html | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/scroll-animations/view-timelines/timeline-offset-in-keyframe.html')
-rw-r--r-- | testing/web-platform/tests/scroll-animations/view-timelines/timeline-offset-in-keyframe.html | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/testing/web-platform/tests/scroll-animations/view-timelines/timeline-offset-in-keyframe.html b/testing/web-platform/tests/scroll-animations/view-timelines/timeline-offset-in-keyframe.html new file mode 100644 index 0000000000..62a8d1387d --- /dev/null +++ b/testing/web-platform/tests/scroll-animations/view-timelines/timeline-offset-in-keyframe.html @@ -0,0 +1,263 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#named-timeline-range"> +<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> +<title>Animation range and delay</title> +</head> +<style type="text/css"> + #scroller { + border: 10px solid lightgray; + overflow-y: scroll; + overflow-x: hidden; + width: 300px; + height: 200px; + } + #target { + margin: 800px 10px; + width: 100px; + height: 100px; + z-index: -1; + background-color: green; + } +</style> +<body> + <div id=scroller> + <div id=target></div> + </div> +</body> +<script type="text/javascript"> + async function runTest() { + function assert_progress_equals(anim, expected, errorMessage) { + assert_approx_equals( + anim.effect.getComputedTiming().progress, + expected, 1e-6, errorMessage); + } + + function assert_opacity_equals(expected, errorMessage) { + assert_approx_equals( + parseFloat(getComputedStyle(target).opacity), expected, 1e-6, + errorMessage); + } + + async function runTimelineOffsetsInKeyframesTest(keyframes) { + const testcase = JSON.stringify(keyframes); + const anim = target.animate(keyframes, { + timeline: new ViewTimeline( { subject: target }), + rangeStart: { rangeName: 'contain', offset: CSS.percent(0) }, + rangeEnd: { rangeName: 'contain', offset: CSS.percent(100) }, + duration: 'auto', fill: 'both' + }); + await anim.ready; + await waitForNextFrame(); + + // @ contain 0% + scroller.scrollTop = 700; + await waitForNextFrame(); + + assert_progress_equals( + anim, 0, `Testcase '${testcase}': progress at contain 0%`); + assert_opacity_equals( + 1/3, `Testcase '${testcase}': opacity at contain 0%`); + + // @ contain 50% + scroller.scrollTop = 750; + await waitForNextFrame(); + assert_progress_equals( + anim, 0.5, `Testcase '${testcase}': progress at contain 50%`); + assert_opacity_equals( + 0.5, `Testcase '${testcase}': opacity at contain 50%`); + + // @ contain 100% + scroller.scrollTop = 800; + await waitForNextFrame(); + assert_progress_equals( + anim, 1, `Testcase '${testcase}': progress at contain 100%`); + assert_opacity_equals( + 2/3, `Testcase '${testcase}': opacity at contain 100%`); + anim.cancel(); + } + + async function runParseNumberOrPercentInKeyframesTest(keyframes) { + const anim = target.animate(keyframes, { + timeline: new ViewTimeline( { subject: target }), + rangeStart: { rangeName: 'contain', offset: CSS.percent(0) }, + rangeEnd: { rangeName: 'contain', offset: CSS.percent(100) }, + duration: 'auto', fill: 'both' + }); + await anim.ready; + await waitForNextFrame(); + + const maxScroll = scroller.scrollHeight - scroller.clientHeight; + scroller.scrollTop = maxScroll / 2; + await waitForNextFrame(); + + const testcase = JSON.stringify(keyframes); + assert_progress_equals(anim, 0.5, testcase); + assert_opacity_equals(0.5, testcase); + anim.cancel(); + } + + async function runInvalidKeyframesTest(keyframes) { + assert_throws_js(TypeError, () => { + target.animate(keyframes, { + timeline: new ViewTimeline( { subject: target }), + }); + }, `Invalid keyframes test case "${JSON.stringify(keyframes)}"`); + } + + promise_test(async t => { + // Test equivalent typed-OM and CSS representations of timeline offsets. + // Test array and object form for keyframes. + const keyframeTests = [ + // BaseKeyframe form with offsets expressed as typed-OM. + [ + { + offset: { rangeName: 'cover', offset: CSS.percent(0) }, + opacity: 0 + }, + { + offset: { rangeName: 'cover', offset: CSS.percent(100) }, + opacity: 1 + } + ], + // BaseKeyframe form with offsets expressed as CSS text. + [ + { offset: "cover 0%", opacity: 0 }, + { offset: "cover 100%", opacity: 1 } + ], + // BasePropertyIndexedKeyframe form with offsets expressed as typed-OM. + { + opacity: [0, 1], + offset: [ + { rangeName: 'cover', offset: CSS.percent(0) }, + { rangeName: 'cover', offset: CSS.percent(100) } + ] + }, + // BasePropertyIndexedKeyframe form with offsets expressed as CSS text. + { opacity: [0, 1], offset: [ "cover 0%", "cover 100%" ]} + ]; + + for (let i = 0; i < keyframeTests.length; i++) { + await runTimelineOffsetsInKeyframesTest(keyframeTests[i]); + } + + }, 'Timeline offsets in programmatic keyframes'); + + promise_test(async t => { + const keyframeTests = [ + [{offset: "0.5", opacity: 0.5 }], + [{offset: "50%", opacity: 0.5 }], + [{offset: "calc(20% + 30%)", opacity: 0.5 }] + ]; + + for (let i = 0; i < keyframeTests.length; i++) { + await runParseNumberOrPercentInKeyframesTest(keyframeTests[i]); + } + + }, 'String offsets in programmatic keyframes'); + + promise_test(async t => { + const invalidKeyframeTests = [ + // BasePropertyKefyrame: + [{ offset: { rangeName: 'somewhere', offset: CSS.percent(0) }}], + [{ offset: { rangeName: 'entry', offset: CSS.px(0) }}], + [{ offset: "here 0%" }], + [{ offset: "entry 3px" }], + // BasePropertyIndexedKeyframe with sequence: + { offset: [{ rangeName: 'somewhere', offset: CSS.percent(0) }]}, + { offset: [{ rangeName: 'entry', offset: CSS.px(0) }]}, + { offset: ["here 0%"] }, + { offset: ["entry 3px" ]}, + // BasePropertyIndexedKeyframe without sequence: + { offset: { rangeName: 'somewhere', offset: CSS.percent(0) }}, + { offset: { rangeName: 'entry', offset: CSS.px(0) }}, + { offset: "here 0%" }, + { offset: "entry 3px" }, + // <number> or <percent> as string: + [{ offset: "-1" }], + [{ offset: "2" }], + [{ offset: "-10%" }], + [{ offset: "110%" }], + { offset: ["-1"], opacity: [0.5] }, + { offset: ["2"], opacity: [0.5] }, + { offset: "-1", opacity: 0.5 }, + { offset: "2", opacity: 0.5 }, + // Extra stuff at the end. + [{ offset: "0.5 trailing nonsense" }], + [{ offset: "cover 50% eureka" }] + ]; + for( let i = 0; i < invalidKeyframeTests.length; i++) { + await runInvalidKeyframesTest(invalidKeyframeTests[i]); + } + }, 'Invalid timeline offset in programmatic keyframe throws'); + + + promise_test(async t => { + const anim = target.animate([ + { offset: "cover 0%", opacity: 0 }, + { offset: "cover 100%", opacity: 1 } + ], { + rangeStart: { rangeName: 'contain', offset: CSS.percent(0) }, + rangeEnd: { rangeName: 'contain', offset: CSS.percent(100) }, + duration: 10000, fill: 'both' + }); + + scroller.scrollTop = 750; + + await anim.ready; + assert_opacity_equals(1, `Opacity with document timeline`); + + anim.timeline = new ViewTimeline( { subject: target }); + await waitForNextFrame(); + + assert_progress_equals(anim, 0.5, `Progress at contain 50%`); + assert_opacity_equals(0.5, `Opacity at contain 50%`); + + anim.timeline = document.timeline; + await waitForNextFrame(); + assert_opacity_equals(1, `Opacity after resetting timeline`); + + anim.cancel(); + }, 'Timeline offsets in programmatic keyframes adjust for change in ' + + 'timeline'); + + promise_test(async t => { + const anim = target.animate([], { + timeline: new ViewTimeline( { subject: target }), + rangeStart: { rangeName: 'contain', offset: CSS.percent(0) }, + rangeEnd: { rangeName: 'contain', offset: CSS.percent(100) }, + duration: 'auto', fill: 'both' + }); + + await anim.ready; + await waitForNextFrame(); + + scroller.scrollTop = 750; + await waitForNextFrame(); + assert_progress_equals( + anim, 0.5, `Progress at contain 50% before effect change`); + assert_opacity_equals(1, `Opacity at contain 50% before effect change`); + + anim.effect = new KeyframeEffect(target, [ + { offset: "cover 0%", opacity: 0 }, + { offset: "cover 100%", opacity: 1 } + ], { duration: 'auto', fill: 'both' }); + await waitForNextFrame(); + assert_progress_equals( + anim, 0.5, `Progress at contain 50% after effect change`); + assert_opacity_equals(0.5, `Opacity at contain 50% after effect change`); + }, 'Timeline offsets in programmetic keyframes resolved when updating ' + + 'the animation effect'); + } + + // TODO(kevers): Add tests for getKeyframes once + // https://github.com/w3c/csswg-drafts/issues/8507 is resolved. + + window.onload = runTest; +</script> +</html> |