blob: 1abb3481938ea5089a80439d7ced66be941744b5 [file] [log] [blame]
<!DOCTYPE html>
<meta charset=utf-8>
<title>Test element-based scroll offset for scroll timeline.</title>
<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: 500px;
width: 500px;
will-change: transform;
}
.contents {
height: 2000px;
width: 2000px;
position: relative;
}
.vertical #start, .vertical #end {
background: blue;
border-top: 5px solid pink;
box-sizing: border-box;
width: 100%;
height: 50px;
}
.vertical #start {
position: absolute;
top: 50px;
}
.vertical #end {
position: absolute;
top: 1050px;
}
.horizontal #start, .horizontal #end {
background: blue;
border-left:5px solid pink;
box-sizing: border-box;
height: 100%;
width: 50px;
}
.horizontal #start {
position: absolute;
left: 50px;
}
.horizontal #end {
position: absolute;
left: 1050px;
}
</style>
<div id="log"></div>
<script>
'use strict';
async function createScrollAnimationTest(description, config) {
promise_test(async t => {
const scroller = createScrollerWithStartAndEnd(t, config.orientation);
t.add_cleanup(() => scroller.remove());
const start = scroller.querySelector("#start");
const end = scroller.querySelector("#end");
// Force layout to ensure the scroll timeline gets the correct scroll
// range.
start.offsetHeight;
const timeline = createScrollTimeline(t, {
scrollSource: scroller,
orientation: config.orientation,
timeRange: 1000,
fill: 'both',
scrollOffsets:
[{target: start, ...config.start}, {target: end, ...config.end }]
});
// Wait for new animation frame which allows the timeline to compute new
// current time.
await waitForNextFrame();
const animation = createScrollLinkedAnimation(t, timeline);
const scrollRange = end.offsetTop - start.offsetTop;
const timeRange = animation.timeline.timeRange;
// Verify initial start and current times in Idle state.
assert_equals(animation.currentTime, null,
"The current time is null in Idle state.");
assert_equals(animation.startTime, null,
"The start time is null in Idle state.");
animation.play();
assert_true(animation.pending, "Animation is in pending state.");
// Verify initial start and current times in Pending state.
assert_times_equal(animation.currentTime, 0,
"The current time is zero in Pending state.");
assert_equals(animation.startTime, 0,
"The start time is zero in Pending state.");
await animation.ready;
// Verify initial start and current times in Playing state.
assert_times_equal(animation.currentTime, 0,
"The current time is zero in Playing state.");
assert_times_equal(animation.startTime, 0,
"The start time is zero in Playing state.");
// Now do some scrolling and make sure that the Animation current time is
// correct.
if (config.orientation == 'vertical') {
scroller.scrollTo({top: config.scrollTo});
assert_equals(scroller.scrollTop, config.scrollTo);
} else {
scroller.scrollTo({left: config.scrollTo});
assert_equals(scroller.scrollLeft, config.scrollTo);
}
await waitForNextFrame();
assert_times_equal(animation.timeline.currentTime, config.expectedCurrentTime,
"The timeline current time corresponds to the scroll position of the scroller.");
assert_times_equal(animation.currentTime, config.expectedCurrentTime,
"The animation current time corresponds to the scroll position of the scroller.");
assert_times_equal(
animation.effect.getComputedTiming().localTime,
config.expectedCurrentTime,
'Effect local time corresponds to the scroll position of the scroller.');
}, description);
}
// start is @ 50px
// end is @ 1050px
// both have 50px heights
// scroller has 500px heights
// For each test the expected start/end is in the comment to help with the
// verification.
const tests = {
// offsets: [100, 1100]
"at start": {
scrollTo: 100,
expectedCurrentTime: 0,
},
// offsets: [100, 1100]
"after start": {
scrollTo: 200,
expectedCurrentTime: 100,
},
// offsets: [100, 1100]
"at middle" : {
scrollTo: 600,
expectedCurrentTime: 500,
},
// offsets: [100, 1100]
"at end" : {
scrollTo: 1099,
expectedCurrentTime: 999,
},
// offsets: [100, 1100]
"after end" : {
scrollTo: 1150,
expectedCurrentTime: 1000,
},
// offsets: [75, 1075]
"with threshold 0.5" : {
// give threshold to both start and end to keep scrollRange
// 1000 which simplifies the calculation.
start: {threshold: 0.5},
end: {threshold: 0.5},
scrollTo: 600 - 25,
expectedCurrentTime: 500,
},
// offsets: [50, 1050]
"with threshold 1.0": {
start: {threshold: 1.0},
end: {threshold: 1.0},
scrollTo: 600 - 50,
expectedCurrentTime: 500,
},
// offset: [100, 550]
"with end edge" : {
end: {edge: "end"},
scrollTo: 325,
expectedCurrentTime: 500,
},
// offset: [100, 600]
"with end edge and threshold 1.0": {
end: {
threshold: 1.0,
edge: "end"
},
scrollTo: 350,
expectedCurrentTime: 500,
},
};
for (let orientation of ['vertical', 'horizontal']) {
for (let testName in tests) {
const description = `Animation start and current times are correct given
element-based offsets for orienation ${orientation} and ${testName}.`;
const config = tests[testName];
config.orientation = orientation;
createScrollAnimationTest(description, config);
}
}
</script>