Update web-platform-tests to revision b'1d9b01e2fad6af3a057d571b1e088e15fa9bc8e6'

This commit is contained in:
WPT Sync Bot 2023-04-07 01:27:34 +00:00
parent cfef75c99b
commit bb34f95b33
1683 changed files with 37170 additions and 4252 deletions

View file

@ -0,0 +1,229 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="help" src="https://www.w3.org/TR/scroll-animations-1/#named-range-animation-declaration">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/web-animations/testcommon.js"></script>
<script src="/web-animations/resources/keyframe-utils.js"></script>
<script src="support/testcommon.js"></script>
<script src="/scroll-animations/scroll-timelines/testcommon.js"></script>
<title>Programmatic API overrides animation-range-*</title>
</head>
<style type="text/css">
#scroller {
border: 10px solid lightgray;
overflow-y: scroll;
overflow-x: hidden;
width: 300px;
height: 200px;
}
@keyframes anim {
from { margin-left: 0px; }
to { margin-left: 100px; }
}
#target {
margin: 800px 0px;
width: 100px;
height: 100px;
z-index: -1;
background-color: green;
}
.animate {
animation: anim auto linear;
view-timeline: timeline;
animation-timeline: timeline;
animation-range-start: entry 0%;
animation-range-end: entry 100%;
}
</style>
<body>
<div id=scroller>
<div id=target></div>
</div>
</body>
<script type="text/javascript">
async function runTest() {
function startAnimation(t) {
target.classList.add('animate');
t.add_cleanup(async () => {
target.classList.remove('animate');
await waitForNextFrame();
});
return target.getAnimations()[0];
}
promise_test(async t => {
// Points of interest:
// entry 0% @ 600
// entry 100% / contain 0% @ 700
// exit 0% / contain 100% @ 800
// exit 100% @ 900
const anim = startAnimation(t);
await anim.ready;
await waitForNextFrame();
scroller.scrollTop = 650;
await waitForNextFrame();
// Timline time = (scroll pos - cover 0%) / (cover 100% - cover 0%) * 100%
// = (650 - 600)/(900 - 600) * 100% = 100/6%
assert_percents_equal(anim.timeline.currentTime, 100/6,
'timeline\'s current time before style change');
assert_percents_equal(anim.startTime, 0,
'animation\'s start time before style change');
// Range start of entry 0% aligns with timeline start. Thus, animation's
// and timeline's current time are equal.
assert_percents_equal(anim.currentTime, 100/6,
'animation\'s current time before style change');
// Iteration duration =
// (range end - range start) / (cover 100% - cover 0%) * 100%
// = (700 - 600) / (900 - 600) = 33.3333%
assert_percents_equal(anim.effect.getComputedTiming().duration,
100/3,
'iteration duration before first style change');
assert_equals(getComputedStyle(target).marginLeft, '50px',
'margin-left before style change');
// Step 1: Set the range end programmatically and range start via CSS.
// The start time will be respected since not previously set via the
// animation API.
anim.rangeEnd = 'contain 100%';
target.style.animationRangeStart = 'entry 50%';
await waitForNextFrame();
// Animation range does not affect timeline's currentTime.
assert_percents_equal(
anim.timeline.currentTime, 100/6,
'timeline\'s current time after first set of range updates');
assert_percents_equal(
anim.startTime, 100/6,
'animation\'s start time after first set of range updates');
// Scroll position aligns with range start.
assert_percents_equal(
anim.currentTime, 0,
'animation\'s current time after first set of range updates');
// Iteration duration =
// (range end - range start) / (cover 100% - cover 0%) * 100%
// = (800 - 650) / (900 - 600) = 50%
assert_percents_equal(
anim.effect.getComputedTiming().duration, 50,
'iteration duration after first style change');
assert_equals(getComputedStyle(target).marginLeft, '0px',
'margin-left after first set of range updates');
// Step 2: Programmatically set the range start.
// Scroll position is current at entry 50%, thus the animation's current
// time is negative.
anim.rangeStart = 'contain 0%';
// animation current time =
// (scroll pos - range start) / (cover 100% - cover 0%) * 100%
// = (650 - 700) / (900 - 600) * 100% = -100/6%
assert_percents_equal(
anim.currentTime, -100/6,
'animation\'s current time after second set of range updates');
// Iteration duration =
// (range end - range start) / (cover 100% - cover 0%) * 100%
// = (800 - 700) / (900 - 600) = 33.3333%
assert_percents_equal(
anim.effect.getComputedTiming().duration, 100/3,
'iteration duration after second style change');
assert_equals(getComputedStyle(target).marginLeft, '0px',
'margin-left after second set of range updates');
// Jump to contain / cover 50%
scroller.scrollTop = 750;
await waitForNextFrame();
// animation current time =
// (scroll pos - range start) / (cover 100% - cover 0%) * 100%
// = (750 - 700) / (900 - 600) * 100% = 100/6%
assert_percents_equal(
anim.currentTime, 100/6,
'animation\'s current time after bumping scroll position');
assert_equals(getComputedStyle(target).marginLeft, '50px');
// Step 3: Try to update the range start via CSS. This change must be
// ignored since previously set programmatically.
target.style.animationRangeStart = "entry 50%";
await waitForNextFrame();
assert_percents_equal(
anim.currentTime, 100/6,
'Current time unchanged after change to ignored CSS property');
assert_equals(
getComputedStyle(target).marginLeft, '50px',
'Margin-left unaffected by change to ignored CSS property');
}, 'Animation API call rangeStart overrides animation-range-start');
promise_test(async t => {
const anim = startAnimation(t);
await anim.ready;
await waitForNextFrame();
scroller.scrollTop = 650;
await waitForNextFrame();
// Step 1: Set the range start programmatically and range end via CSS.
// The start time will be respected since not previously set via the
// animation API.
anim.rangeStart = "entry 50%";
target.style.animationRangeEnd = "contain 100%";
await waitForNextFrame();
assert_percents_equal(
anim.timeline.currentTime, 100/6,
'timeline\'s current time after first set of range updates');
assert_percents_equal(
anim.startTime, 100/6,
'animation\'s start time after first set of range updates');
assert_percents_equal(
anim.currentTime, 0,
'animation\'s current time after first set of range updates');
assert_percents_equal(
anim.effect.getComputedTiming().duration, 50,
'iteration duration after first style change');
assert_equals(getComputedStyle(target).marginLeft, "0px",
'margin-left after first set of range updates');
// Step 2: Programmatically set the range.
// Scroll position is current at entry 50%, thus the animation's current
// time is negative.
anim.rangeStart = "contain 0%";
anim.rangeEnd = "contain 100%";
assert_percents_equal(
anim.currentTime, -100/6,
'animation\'s current time after second set of range updates');
assert_percents_equal(
anim.effect.getComputedTiming().duration, 100/3,
'iteration duration after second style change');
assert_equals(getComputedStyle(target).marginLeft, "0px",
'margin-left after second set of range updates');
// Jump to contain / cover 50%
scroller.scrollTop = 750;
await waitForNextFrame();
assert_percents_equal(
anim.currentTime, 100/6,
'animation\'s current time after bumping scroll position');
assert_equals(getComputedStyle(target).marginLeft, "50px");
// Step 3: Try to update the range end via CSS. This change must be
// ignored since previously set programmatically.
target.style.animationRangeEnd = "cover 100%";
await waitForNextFrame();
assert_percents_equal(
anim.currentTime, 100/6,
'Current time unchanged after change to ignored CSS property');
assert_equals(
getComputedStyle(target).marginLeft, '50px',
'Margin-left unaffected by change to ignored CSS property');
}, 'Animation API call rangeEnd overrides animation-range-end');
}
window.onload = runTest;
</script>

View file

@ -0,0 +1,92 @@
<!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>
<script src="/scroll-animations/scroll-timelines/testcommon.js"></script>
<title>Animation range 'normal' is equivalent to animation range 'cover'</title>
</head>
<style type="text/css">
@keyframes anim-1 {
from { background-color: blue; }
to { background-color: white; }
}
@keyframes anim-2 {
from { opacity: 0.3; }
to { opacity: 1; }
}
#scroller {
border: 10px solid lightgray;
overflow-y: scroll;
overflow-x: hidden;
width: 300px;
height: 200px;
}
#target {
margin-top: 800px;
margin-bottom: 800px;
margin-left: 10px;
margin-right: 10px;
width: 100px;
height: 100px;
z-index: -1;
background-color: green;
animation: anim-1 auto linear, anim-2 auto linear;
animation-range: normal, cover;
view-timeline: t1;
animation-timeline: t1, t1;
}
</style>
<body>
<div id="scroller">
<div id="target"></div>
</div>
</body>
<script type="text/javascript">
async function runTest() {
function assert_range_equals(actual, expected) {
if (typeof expected == 'string') {
assert_equals(actual, expected);
} else {
assert_equals(actual.rangeName, expected.rangeName);
assert_equals(actual.offset.value, expected.offset.value);
}
}
promise_test(async t => {
anims = target.getAnimations();
assert_equals(anims.length, 2, "Expecting 2 animations");
await anims[0].ready;
await anims[1].ready;
assert_range_equals(anims[0].rangeStart, "normal");
assert_range_equals(anims[0].rangeEnd, "normal");
assert_range_equals(anims[1].rangeStart,
{ rangeName: 'cover', offset: CSS.percent(0) });
assert_range_equals(anims[1].rangeEnd,
{ rangeName: 'cover', offset: CSS.percent(100) });
scroller.scrollTop = 600; // Start boundary for cover range.
await waitForNextFrame();
assert_percents_equal(anims[0].currentTime, 0,
'currentTime at start of normal range');
assert_percents_equal(anims[1].currentTime, 0,
'currentTime at cover 0%');
scroller.scrollTop = 900; // End boundary for cover range.
await waitForNextFrame();
assert_percents_equal(anims[0].currentTime, 100,
'currentTime at end of normal range');
assert_percents_equal(anims[1].currentTime, 100,
'currentTime at cover 100%');
}, 'Changing the animation range updates the play state');
}
window.onload = runTest;
</script>

View file

@ -38,7 +38,9 @@ test_shorthand_value('animation',
'animation-fill-mode': 'forwards, forwards, forwards',
'animation-play-state': 'paused, paused, paused',
'animation-name': 'anim1, anim2, anim3',
'animation-timeline': 'auto, auto, auto'
'animation-timeline': 'auto, auto, auto',
'animation-range-start': 'normal, normal, normal',
'animation-range-end': 'normal, normal, normal',
});
test((t) => {
@ -89,4 +91,52 @@ test((t) => {
assert_equals(getComputedStyle(target).animationDuration, '1s');
}, 'Animation shorthand can not represent non-initial animation-delay-end (computed)');
test((t) => {
t.add_cleanup(() => {
target.style = '';
});
target.style.animation = 'anim 1s';
target.style.animationRangeStart = 'entry';
assert_equals(target.style.animation, '');
assert_equals(target.style.animationName, 'anim');
assert_equals(target.style.animationDuration, '1s');
}, 'Animation shorthand can not represent non-initial animation-range-start (specified)');
test((t) => {
t.add_cleanup(() => {
target.style = '';
});
target.style.animation = 'anim 1s';
target.style.animationRangeStart = 'entry';
assert_equals(getComputedStyle(target).animation, '');
assert_equals(getComputedStyle(target).animationName, 'anim');
assert_equals(getComputedStyle(target).animationDuration, '1s');
}, 'Animation shorthand can not represent non-initial animation-range-start (computed)');
test((t) => {
t.add_cleanup(() => {
target.style = '';
});
target.style.animation = 'anim 1s';
target.style.animationRangeEnd = 'entry';
assert_equals(target.style.animation, '');
assert_equals(target.style.animationName, 'anim');
assert_equals(target.style.animationDuration, '1s');
}, 'Animation shorthand can not represent non-initial animation-range-end (specified)');
test((t) => {
t.add_cleanup(() => {
target.style = '';
});
target.style.animation = 'anim 1s';
target.style.animationRangeEnd = 'entry';
assert_equals(getComputedStyle(target).animation, '');
assert_equals(getComputedStyle(target).animationName, 'anim');
assert_equals(getComputedStyle(target).animationDuration, '1s');
}, 'Animation shorthand can not represent non-initial animation-range-end (computed)');
</script>

View file

@ -48,6 +48,8 @@ test_computed_value('animation-timeline', 'scroll(horizontal)');
test_computed_value('animation-timeline', 'scroll(vertical)');
test_computed_value('animation-timeline', 'scroll(root)');
test_computed_value('animation-timeline', 'scroll(nearest)', 'scroll()');
test_computed_value('animation-timeline', 'scroll(self)');
test_computed_value('animation-timeline', 'scroll(self), scroll(nearest)', 'scroll(self), scroll()');
test_computed_value('animation-timeline', 'scroll(inline nearest)', 'scroll(inline)');
test_computed_value('animation-timeline', 'scroll(vertical root)');

View file

@ -41,6 +41,7 @@ test_valid_value('animation-timeline', 'scroll(horizontal)');
test_valid_value('animation-timeline', 'scroll(vertical)');
test_valid_value('animation-timeline', 'scroll(root)');
test_valid_value('animation-timeline', 'scroll(nearest)', 'scroll()');
test_valid_value('animation-timeline', 'scroll(self)');
test_valid_value('animation-timeline', 'scroll(inline nearest)', 'scroll(inline)');
test_valid_value('animation-timeline', 'scroll(vertical root)');

View file

@ -112,6 +112,24 @@ promise_test(async t => {
await scrollTop(root, 0);
}, 'animation-timeline: scroll(root)');
promise_test(async t => {
let [container, div] = createTargetWithStuff(t, 'block-content');
container.style.animation = "anim 10s linear";
container.style.animationTimeline = "scroll(self)";
await scrollTop(container, 50);
assert_equals(getComputedStyle(container).translate, '100px');
}, 'animation-timeline: scroll(self)');
promise_test(async t => {
let [container, div] = createTargetWithStuff(t, 'block-content');
div.style.animation = "anim 10s linear";
div.style.animationTimeline = "scroll(self)";
await scrollTop(container, 50);
assert_equals(getComputedStyle(div).translate, 'none');
}, 'animation-timeline: scroll(self), on non-scroller');
promise_test(async t => {
let [container, div] = createTargetWithStuff(t, 'inline-content');
div.style.animation = "anim 10s linear";

View file

@ -0,0 +1,132 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Merge timeline offset keyframes</title>
<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="/web-animations/resources/keyframe-utils.js"></script>
</head>
<style>
@keyframes anim-1 {
entry 0% { opacity: 0 }
entry 100% { opacity: 1 }
contain 0% { opacity: 0.8 }
entry 100% { opacity: 0.5 }
}
@keyframes anim-2 {
entry 0% { opacity: 0 }
entry 100% { opacity: 1 }
contain 0% { opacity: 0.8 }
entry 100% { opacity: 0.5; animation-timing-function: ease }
}
#scroller {
border: 10px solid lightgray;
overflow-y: scroll;
overflow-x: hidden;
width: 300px;
height: 200px;
}
#target {
margin-bottom: 800px;
margin-top: 800px;
margin-left: 10px;
margin-right: 10px;
width: 100px;
height: 100px;
z-index: -1;
background-color: green;
animation-duration: auto;
animation-fill-mode: both;
animation-timing-function: linear;
view-timeline: target;
animation-timeline: target;
}
#target.anim-1 {
animation-name: anim-1;
}
#target.anim-2 {
animation-name: anim-2;
}
</style>
<body>
<div id="scroller">
<div id="target"></div>
</div>
</body>
<script>
async function runTests() {
promise_test(async t => {
target.classList.add('anim-1');
const anim = target.getAnimations()[0];
t.add_cleanup(() => {
target.classList.remove('anim-1');
});
const keyframes = anim.effect.getKeyframes();
const expected = [
{
offset: 1, easing: "linear", composite: "replace", opacity: "1",
computedOffset: 1
},
{
offset: { rangeName: "entry", offset: CSS.percent(0) },
easing: "linear", composite: "auto", opacity: "0",
computedOffset: 0
},
{
offset: { rangeName: "contain", offset: CSS.percent(0) },
easing: "linear", composite: "auto", opacity: "0.8",
computedOffset: 1/3
},
{
offset: { rangeName: "entry", offset: CSS.percent(100) },
easing: "linear", composite: "auto", opacity: "0.5",
computedOffset : 1/3
}];
assert_frame_lists_equal(keyframes, expected);
}, 'Keyframes with same easing and timeline offset are merged.');
promise_test(async t => {
target.classList.add('anim-2');
const anim = target.getAnimations()[0];
t.add_cleanup(() => {
target.classList.remove('anim-2');
});
const keyframes = anim.effect.getKeyframes();
const expected = [
{
offset: 1, easing: "linear", composite: "replace", opacity: "1",
computedOffset: 1
},
{
offset: { rangeName: "entry", offset: CSS.percent(0) },
easing: "linear", composite: "auto", opacity: "0",
computedOffset: 0
},
{
offset: { rangeName: "entry", offset: CSS.percent(100) },
easing: "linear", composite: "auto", opacity: "1",
computedOffset: 1/3
},
{
offset: { rangeName: "contain", offset: CSS.percent(0) },
easing: "linear", composite: "auto", opacity: "0.8",
computedOffset: 1/3
},
{
offset: { rangeName: "entry", offset: CSS.percent(100) },
easing: "ease", composite: "auto", opacity: "0.5",
computedOffset : 1/3
}];
assert_frame_lists_equal(keyframes, expected);
}, 'Keyframes with same timeline offset but different easing function ' +
'are not merged.');
}
window.onload = runTests();
</script>
</html>

View file

@ -76,7 +76,14 @@
// Initially using a document timeline, so the keyframes should be
// ignored.
let frames = anim.effect.getKeyframes();
let expected = [];
let expected = [
{ offset: { rangeName: 'cover', offset: CSS.percent(0) },
computedOffset: null, easing: "linear", composite: "auto",
marginLeft: "0px", opacity: "0" },
{ offset: { rangeName: 'cover', offset: CSS.percent(100) },
computedOffset: null, easing: "linear", composite: "auto",
marginRight: "0px", opacity: "1" }
];
assert_frame_lists_equal(frames, expected);
// Once a view-timeline is added, the kefyrames must update to reflect
@ -88,13 +95,15 @@
frames = anim.effect.getKeyframes();
expected = [
{ offset: -1, computedOffset: -1, easing: "linear", composite: "auto",
marginLeft: "0px", opacity: "0" },
{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace",
marginRight: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
marginLeft: "10px" },
{ offset: 2, computedOffset: 2, easing: "linear", composite: "auto",
{ offset: { rangeName: 'cover', offset: CSS.percent(0) },
computedOffset: -1, easing: "linear", composite: "auto",
marginLeft: "0px", opacity: "0" },
{ offset: { rangeName: 'cover', offset: CSS.percent(100) },
computedOffset: 2, easing: "linear", composite: "auto",
marginRight: "0px", opacity: "1" },
];
assert_frame_lists_equal(frames, expected);
@ -105,13 +114,15 @@
await waitForNextFrame();
frames = anim.effect.getKeyframes();
expected = [
{ offset: -1/3, computedOffset: -1/3, easing: "linear",
composite: "auto", marginLeft: "0px", opacity: "0" },
{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace",
marginRight: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
marginLeft: "10px" },
{ offset: 4/3, computedOffset: 4/3, easing: "linear", composite: "auto",
{ offset: { rangeName: 'cover', offset: CSS.percent(0) },
computedOffset: -1/3, easing: "linear",
composite: "auto", marginLeft: "0px", opacity: "0" },
{ offset: { rangeName: 'cover', offset: CSS.percent(100) },
computedOffset: 4/3, easing: "linear", composite: "auto",
marginRight: "0px", opacity: "1" },
];
assert_frame_lists_equal(frames, expected);
@ -120,9 +131,15 @@
assert_equals(getComputedStyle(target).animationTimeline, 'auto',
'Switch back to document timeline');
frames = anim.effect.getKeyframes();
expected = [];
expected = [
{ offset: { rangeName: 'cover', offset: CSS.percent(0) },
computedOffset: null, easing: "linear", composite: "auto",
marginLeft: "0px", opacity: "0" },
{ offset: { rangeName: 'cover', offset: CSS.percent(100) },
computedOffset: null, easing: "linear", composite: "auto",
marginRight: "0px", opacity: "1" }
];
assert_frame_lists_equal(frames, expected);
}, 'getKeyframes with timeline-offsets');
}

View file

@ -68,15 +68,17 @@
let frames = anim.effect.getKeyframes();
let expected_resolved_offsets = [
{ offset: -1/3, computedOffset: -1/3, easing: "linear",
composite: "auto", marginLeft: "0px" },
{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace",
marginRight: "10px", opacity: "1" },
{ offset: 1/2, computedOffset: 1/2, easing: "linear",
composite: "auto", opacity: "0.5" },
{ offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
marginLeft: "10px", opacity: "1" },
{ offset: 4/3, computedOffset: 4/3, easing: "linear", composite: "auto",
{ offset: { rangeName: 'cover', offset: CSS.percent(0) },
computedOffset: -1/3, easing: "linear",
composite: "auto", marginLeft: "0px" },
{ offset: { rangeName: 'cover', offset: CSS.percent(100) },
computedOffset: 4/3, easing: "linear", composite: "auto",
marginRight: "0px" },
];
assert_frame_lists_equal(frames, expected_resolved_offsets,
@ -92,7 +94,13 @@
{ offset: 0.5, computedOffset: 0.5, opacity: "0.5", easing: "linear",
composite: "auto", },
{ offset: 1, computedOffset: 1, opacity: "1", easing: "linear",
composite: "replace" }
composite: "replace" },
{ offset: { rangeName: 'cover', offset: CSS.percent(0) },
computedOffset: null, easing: "linear",
composite: "auto", marginLeft: "0px" },
{ offset: { rangeName: 'cover', offset: CSS.percent(100) },
computedOffset: null, easing: "linear", composite: "auto",
marginRight: "0px" }
];
assert_frame_lists_equal(frames, expected_unresolved_offsets,
'Keyframes with invalid view timeline');

View file

@ -12,15 +12,15 @@
</head>
<style type="text/css">
@keyframes anim {
cover 100% {
margin-right: 0px;
}
cover 0% {
margin-left: 0px;
}
50% {
opacity: 0.5;
}
cover 100% {
margin-right: 0px;
}
}
#scroller {
border: 10px solid lightgray;
@ -61,13 +61,19 @@
{ offset: 0, computedOffset: 0, opacity: "1", easing: "linear",
composite: "replace" },
{ offset: 0.5, computedOffset: 0.5, opacity: "0.5", easing: "linear",
composite: "auto", },
composite: "auto" },
{ offset: 1, computedOffset: 1, opacity: "1", easing: "linear",
composite: "replace" }
composite: "replace" },
{ offset: { rangeName: "cover", offset: CSS.percent(100) },
computedOffset: null, marginRight: "0px", composite: "auto",
easing: "linear" },
{ offset: { rangeName: "cover", offset: CSS.percent(0) },
computedOffset: null, marginLeft: "0px", composite: "auto",
easing: "linear" }
];
assert_frame_lists_equal(frames, expected);
}, 'Keyframes with timeline-offsets ignored when using document ' +
'timeline');
}, 'Keyframes with timeline-offsets reported but not reachable when ' +
'using a document timeline');
}
window.onload = runTest;

View file

@ -19,7 +19,8 @@
width: 200px;
height: 200px;
}
#target {
/* Reset specificity to allow animation-range-* from .restrict-range to win. */
:where(#target) {
margin: 800px 0px;
width: 100px;
height: 100px;

View file

@ -13,10 +13,10 @@
<div id=target></div>
</div>
<script>
test_computed_value('view-timeline-inset', 'initial', '0px');
test_computed_value('view-timeline-inset', 'initial', 'auto');
test_computed_value('view-timeline-inset', 'inherit', '1px 2px, auto 3px');
test_computed_value('view-timeline-inset', 'unset', '0px');
test_computed_value('view-timeline-inset', 'revert', '0px');
test_computed_value('view-timeline-inset', 'unset', 'auto');
test_computed_value('view-timeline-inset', 'revert', 'auto');
test_computed_value('view-timeline-inset', '1px');
test_computed_value('view-timeline-inset', '1%');
test_computed_value('view-timeline-inset', 'calc(1% + 1px)');