mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Update web-platform-tests to revision f0cb9071aea5ce5b641fcba5f362a0796bdc70bc
This commit is contained in:
parent
0d549e8146
commit
7289e837fd
558 changed files with 8627 additions and 6619 deletions
|
@ -0,0 +1,128 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-scroll-snap-1" />
|
||||
<title>Arrow key scroll snapping</title>
|
||||
<meta name="flags" content="should">
|
||||
<meta name="assert"
|
||||
content="Test passes if keyboard scrolling correctly snaps on a snap
|
||||
container">
|
||||
|
||||
<link rel="stylesheet" href="../support/common.css">
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/resources/testdriver-actions.js"></script>
|
||||
<script src="../support/common.js"></script>
|
||||
|
||||
|
||||
<div id="scroller">
|
||||
<div id="space"></div>
|
||||
<div class="snap left top" id="top-left"></div>
|
||||
<div class="snap right top" id="top-right"></div>
|
||||
<div class="snap left bottom" id="bottom-left"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const scroller = document.getElementById("scroller");
|
||||
const topLeft = document.getElementById("top-left");
|
||||
const topRight = document.getElementById("top-right");
|
||||
|
||||
scrollLeft = () => scroller.scrollLeft;
|
||||
scrollTop = () => scroller.scrollTop;
|
||||
|
||||
promise_test(async t => {
|
||||
scroller.scrollTo(0, 0);
|
||||
assert_equals(scroller.scrollTop, 0, "verify test pre-condition");
|
||||
await keyPress(scroller, "ArrowDown");
|
||||
await waitForAnimationEnd(scrollTop);
|
||||
assert_equals(scroller.scrollTop, 400);
|
||||
}, "Snaps to bottom-left after pressing ArrowDown");
|
||||
|
||||
promise_test(async t => {
|
||||
scroller.scrollTo(0, 400);
|
||||
assert_equals(scroller.scrollTop, 400, "verify test pre-condition");
|
||||
await keyPress(scroller, "ArrowUp");
|
||||
await waitForAnimationEnd(scrollTop);
|
||||
assert_equals(scroller.scrollTop, 0);
|
||||
}, "Snaps to top-left after pressing ArrowUp");
|
||||
|
||||
promise_test(async t => {
|
||||
scroller.scrollTo(0, 0);
|
||||
assert_equals(scroller.scrollTop, 0, "verify test pre-condition");
|
||||
await keyPress(scroller, "ArrowRight");
|
||||
await waitForAnimationEnd(scrollLeft);
|
||||
assert_equals(scroller.scrollLeft, 400);
|
||||
}, "Snaps to top-right after pressing ArrowRight");
|
||||
|
||||
promise_test(async t => {
|
||||
scroller.scrollTo(400, 0);
|
||||
assert_equals(scroller.scrollLeft, 400, "verify test pre-condition");
|
||||
await keyPress(scroller, "ArrowLeft");
|
||||
await waitForAnimationEnd(scrollLeft);
|
||||
assert_equals(scroller.scrollLeft, 0);
|
||||
}, "Snaps to top-left after pressing ArrowLeft");
|
||||
|
||||
promise_test(async t => {
|
||||
t.add_cleanup(function() {
|
||||
topLeft.style.width = "";
|
||||
topRight.style.left = "400px";
|
||||
});
|
||||
|
||||
// Make the snap area cover the snapport.
|
||||
topLeft.style.width = "800px";
|
||||
// Make the distance between the previous and the next snap position larger
|
||||
// than snapport.
|
||||
topRight.style.left = "500px";
|
||||
scroller.scrollTo(0, 0);
|
||||
assert_equals(scroller.scrollLeft, 0, "verify test pre-condition");
|
||||
await keyPress(scroller, "ArrowRight");
|
||||
await waitForAnimationEnd(scrollLeft);
|
||||
assert_between_exclusive(scroller.scrollLeft, 0, 500);
|
||||
}, "If the original intended offset is valid as making a snap area cover the"
|
||||
+ "snapport, and there's no other snap offset in between, use the original"
|
||||
+ "intended offset");
|
||||
|
||||
promise_test(async t => {
|
||||
t.add_cleanup(function() {
|
||||
topLeft.style.width = "";
|
||||
topRight.style.left = "400px";
|
||||
});
|
||||
|
||||
// Make the snap area cover the snapport.
|
||||
topLeft.style.width = "800px";
|
||||
// Make the next snap offset closer than the original intended offset.
|
||||
topRight.style.left = "20px";
|
||||
scroller.scrollTo(0, 0);
|
||||
assert_equals(scroller.scrollLeft, 0, "verify test pre-condition");
|
||||
await keyPress(scroller, "ArrowRight");
|
||||
await waitForAnimationEnd(scrollLeft);
|
||||
assert_equals(scroller.scrollLeft, 20);
|
||||
}, "If the original intended offset is valid as making a snap area cover the "
|
||||
+ "snapport, but there's a defined snap offset in between, use the defined snap"
|
||||
+ " offset.");
|
||||
|
||||
promise_test(async t => {
|
||||
scroller.scrollTo(400, 0);
|
||||
await keyPress(scroller, "ArrowRight");
|
||||
await waitForAnimationEnd(scrollLeft);
|
||||
assert_equals(scroller.scrollLeft, 400);
|
||||
}, "If there is no valid snap offset on the arrow key's direction other than "
|
||||
+ "the current offset, and the scroll-snap-type is mandatory, stay at the "
|
||||
+ "current offset.");
|
||||
|
||||
promise_test(async t => {
|
||||
t.add_cleanup(function() {
|
||||
scroller.style.scrollSnapType = "both mandatory";
|
||||
});
|
||||
|
||||
scroller.style.scrollSnapType = "both proximity";
|
||||
scroller.scrollTo(400, 0);
|
||||
assert_equals(scroller.scrollLeft, 400, "verify test pre-condition");
|
||||
await keyPress(scroller, "ArrowRight");
|
||||
await waitForAnimationEnd(scrollLeft);
|
||||
assert_greater_than(scroller.scrollLeft, 400);
|
||||
}, "If there is no valid snap offset on the arrow key's direction other than "
|
||||
+ "the current offset, and the scroll-snap-type is proximity, go to the "
|
||||
+ "original intended offset");
|
||||
</script>
|
|
@ -76,54 +76,54 @@ body {
|
|||
// its snap areas to the next scrollable ancestor, per spec [1].
|
||||
// [1] https://drafts.csswg.org/css-scroll-snap/#captures-snap-positions
|
||||
test(() => {
|
||||
const innerscroller = document.getElementById("inner-scroller");
|
||||
const middlescroller = document.getElementById("middle-scroller");
|
||||
const documentscroller = document.scrollingElement;
|
||||
const inner_scroller = document.getElementById("inner-scroller");
|
||||
const middle_scroller = document.getElementById("middle-scroller");
|
||||
const document_scroller = document.scrollingElement;
|
||||
|
||||
// Middle scroller doesn't snap.
|
||||
// Document scroller should snap to its only captured area.
|
||||
documentscroller.scrollBy(0, 100);
|
||||
middlescroller.scrollBy(0, 10);
|
||||
assert_equals(innerscroller.scrollTop, 0);
|
||||
assert_equals(middlescroller.scrollTop, 10);
|
||||
assert_equals(documentscroller.scrollTop, 500);
|
||||
document_scroller.scrollBy(0, 100);
|
||||
middle_scroller.scrollBy(0, 10);
|
||||
assert_equals(inner_scroller.scrollTop, 0);
|
||||
assert_equals(middle_scroller.scrollTop, 10);
|
||||
assert_equals(document_scroller.scrollTop, 500);
|
||||
|
||||
// Inner scroller snaps.
|
||||
innerscroller.scrollBy(0, 10);
|
||||
assert_equals(innerscroller.scrollTop, 300);
|
||||
assert_equals(middlescroller.scrollTop, 10);
|
||||
assert_equals(documentscroller.scrollTop, 500);
|
||||
inner_scroller.scrollBy(0, 10);
|
||||
assert_equals(inner_scroller.scrollTop, 300);
|
||||
assert_equals(middle_scroller.scrollTop, 10);
|
||||
assert_equals(document_scroller.scrollTop, 500);
|
||||
|
||||
// Inner scroller is no longer a scroll container.
|
||||
innerscroller.style.setProperty("overflow", "visible");
|
||||
assert_equals(innerscroller.scrollTop, 0);
|
||||
assert_equals(middlescroller.scrollTop, 10);
|
||||
assert_equals(documentscroller.scrollTop, 500);
|
||||
inner_scroller.style.setProperty("overflow", "visible");
|
||||
assert_equals(inner_scroller.scrollTop, 0);
|
||||
assert_equals(middle_scroller.scrollTop, 10);
|
||||
assert_equals(document_scroller.scrollTop, 500);
|
||||
|
||||
// The new snap container is the middle scroller, which has snap-type 'none'.
|
||||
// Per spec, the scroll container should capture snap positions even if it has
|
||||
// snap-type 'none'.
|
||||
// The middle scroller should not snap.
|
||||
// The document scroller should still only snap to its captured snap area.
|
||||
documentscroller.scrollBy(0, 100);
|
||||
middlescroller.scrollBy(0, 10);
|
||||
assert_equals(innerscroller.scrollTop, 0);
|
||||
assert_equals(middlescroller.scrollTop, 20);
|
||||
assert_equals(documentscroller.scrollTop, 500);
|
||||
document_scroller.scrollBy(0, 100);
|
||||
middle_scroller.scrollBy(0, 10);
|
||||
assert_equals(inner_scroller.scrollTop, 0);
|
||||
assert_equals(middle_scroller.scrollTop, 20);
|
||||
assert_equals(document_scroller.scrollTop, 500);
|
||||
|
||||
// The scroll container should now be at the document level.
|
||||
middlescroller.style.setProperty("overflow", "visible");
|
||||
documentscroller.scrollBy(0, -10);
|
||||
assert_equals(innerscroller.scrollTop, 0);
|
||||
assert_equals(middlescroller.scrollTop, 0);
|
||||
middle_scroller.style.setProperty("overflow", "visible");
|
||||
document_scroller.scrollBy(0, -10);
|
||||
assert_equals(inner_scroller.scrollTop, 0);
|
||||
assert_equals(middle_scroller.scrollTop, 0);
|
||||
|
||||
// Check that the existing snap area did not get removed when reassigning
|
||||
// the inner snap area.
|
||||
assert_equals(documentscroller.scrollTop, 500);
|
||||
assert_equals(document_scroller.scrollTop, 500);
|
||||
|
||||
// Check that the inner snap area got reassigned to the document.
|
||||
documentscroller.scrollBy(0, 150);
|
||||
assert_equals(documentscroller.scrollTop, 600);
|
||||
document_scroller.scrollBy(0, 150);
|
||||
assert_equals(document_scroller.scrollTop, 600);
|
||||
}, 'Making a snap container not scrollable should promote the next scrollable\
|
||||
ancestor to become a snap container.');
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
<!DOCTYPE html>
|
||||
<title>
|
||||
Adding a scrollable element should make it start capturing snap points.
|
||||
</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-scroll-snap/#captures-snap-positions"/>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
div {
|
||||
position: absolute;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-snap-type: y mandatory;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#middle-scroller {
|
||||
top: 100px;
|
||||
height: 500px;
|
||||
width: 500px;
|
||||
overflow: visible;
|
||||
background-color: rgb(12, 61, 2);
|
||||
scroll-snap-type: none;
|
||||
}
|
||||
|
||||
#inner-scroller {
|
||||
top: 200px;
|
||||
height: 400px;
|
||||
width: 400px;
|
||||
overflow: visible;
|
||||
background-color: rgb(65, 139, 50);
|
||||
scroll-snap-type: y mandatory;
|
||||
}
|
||||
|
||||
.space {
|
||||
width: 2000px;
|
||||
height: 2000px;
|
||||
}
|
||||
|
||||
#inner-snap-area {
|
||||
top: 300px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background-color: blue;
|
||||
scroll-snap-align: start;
|
||||
}
|
||||
|
||||
#document-snap-area {
|
||||
top: 500px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background-color: lightblue;
|
||||
scroll-snap-align: start;
|
||||
}
|
||||
|
||||
#inserted-snap-container {
|
||||
top: 400px;
|
||||
height: 600px;
|
||||
width: 400px;
|
||||
overflow: scroll;
|
||||
scroll-snap-type: y mandatory;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="space"></div>
|
||||
<div id="middle-scroller">
|
||||
<div class="space"></div>
|
||||
<div id="inner-scroller">
|
||||
<div class="space"></div>
|
||||
<div id="inner-snap-area"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="document-snap-area"></div>
|
||||
<script>
|
||||
|
||||
const inner_scroller = document.getElementById("inner-scroller");
|
||||
const middle_scroller = document.getElementById("middle-scroller");
|
||||
const document_scroller = document.scrollingElement;
|
||||
|
||||
// This tests that making an element scrollable will reassign the correct snap
|
||||
// areas to itself, per spec [1].
|
||||
// [1] https://drafts.csswg.org/css-scroll-snap/#captures-snap-positions
|
||||
test(() => {
|
||||
// Confirm that the document-level scroller is the snap container for all of
|
||||
// the snap areas.
|
||||
document_scroller.scrollBy(0, 10);
|
||||
assert_equals(document_scroller.scrollTop, 500);
|
||||
// Snaps to the inner snap area.
|
||||
document_scroller.scrollBy(0, 75);
|
||||
assert_equals(document_scroller.scrollTop, 600);
|
||||
|
||||
// The middle scroller should now have the inner snap area assigned to it.
|
||||
// Per spec, even if the snap-type is 'none', it should still capture snap
|
||||
// points.
|
||||
middle_scroller.style.setProperty("overflow", "scroll");
|
||||
|
||||
// The middle scroller has snap-type 'none' so it should not snap.
|
||||
middle_scroller.scrollBy(0, 10);
|
||||
assert_equals(middle_scroller.scrollTop, 10);
|
||||
|
||||
// The document scroller should only snap to the document-level snap area.
|
||||
document_scroller.scrollTo(0, 600);
|
||||
assert_equals(document_scroller.scrollTop, 500);
|
||||
|
||||
// The inner scroller should now have the innermost snap area assigned to it.
|
||||
inner_scroller.style.setProperty("overflow", "scroll");
|
||||
inner_scroller.scrollBy(0, 10);
|
||||
assert_equals(inner_scroller.scrollTop, 300);
|
||||
|
||||
document_scroller.scrollTo(0, 600);
|
||||
assert_equals(document_scroller.scrollTop, 500);
|
||||
|
||||
}, "Making an element scrollable should make it capture the correct descendant\
|
||||
snap areas' snap points.");
|
||||
|
||||
// Test that attaching a new snap container also properly assigns snap areas.
|
||||
test(() => {
|
||||
// Sanity check that the scrollers still snap to the snap areas.
|
||||
document_scroller.scrollBy(0, 10);
|
||||
inner_scroller.scrollBy(0,10);
|
||||
assert_equals(inner_scroller.scrollTop, 300);
|
||||
assert_equals(document_scroller.scrollTop, 500);
|
||||
|
||||
// Create new snap container and append thedocument-level snap area as its
|
||||
// child.
|
||||
const inserted_scroller = document.createElement("div");
|
||||
inserted_scroller.id = "inserted-snap-container";
|
||||
const space = document.createElement("div");
|
||||
space.classList.add("space");
|
||||
inserted_scroller.appendChild(space);
|
||||
inserted_scroller.appendChild(document.getElementById("document-snap-area"));
|
||||
document_scroller.appendChild(inserted_scroller);
|
||||
|
||||
// Document scroller no longer snaps.
|
||||
document_scroller.scrollTo(0, 400);
|
||||
assert_equals(document_scroller.scrollTop, 400);
|
||||
|
||||
// Inserted scroller snaps.
|
||||
inserted_scroller.scrollBy(0, 10);
|
||||
assert_equals(inserted_scroller.scrollTop, 500);
|
||||
}, "Attaching a new element that is scrollable should assign the correct snap\
|
||||
areas to it.");
|
||||
</script>
|
|
@ -0,0 +1,44 @@
|
|||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#scroller {
|
||||
position: absolute;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
overflow: scroll;
|
||||
padding: 0;
|
||||
|
||||
scroll-snap-type: both mandatory;
|
||||
}
|
||||
|
||||
.snap {
|
||||
position: absolute;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background-color: blue;
|
||||
|
||||
scroll-snap-align: start;
|
||||
}
|
||||
|
||||
#space {
|
||||
position: absolute;
|
||||
width: 1000px;
|
||||
height: 1000px;
|
||||
}
|
||||
|
||||
.left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.top {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.right {
|
||||
left: 400px;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
top: 400px;
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
const KEY_CODE_MAP = {
|
||||
'ArrowLeft': '\uE012',
|
||||
'ArrowUp': '\uE013',
|
||||
'ArrowRight': '\uE014',
|
||||
'ArrowDown': '\uE015',
|
||||
'PageUp': '\uE00E',
|
||||
'PageDown': '\uE00F',
|
||||
'End': '\uE010',
|
||||
'Home': '\uE011',
|
||||
'Space': ' ',
|
||||
};
|
||||
|
||||
// Send key event to the target element using test driver. Supports human
|
||||
// friendly key names for common keyboard scroll operations e.g., arrow keys,
|
||||
// page keys, etc.
|
||||
async function keyPress(target, key) {
|
||||
let code = key;
|
||||
if (KEY_CODE_MAP.hasOwnProperty(key))
|
||||
code = KEY_CODE_MAP[key];
|
||||
|
||||
// First move pointer on target and click to ensure it receives the key.
|
||||
let actions = new test_driver.Actions()
|
||||
.pointerMove(0, 0, {origin: target})
|
||||
.pointerDown()
|
||||
.pointerUp()
|
||||
.keyDown(code)
|
||||
.keyUp(code);
|
||||
|
||||
return actions.send();
|
||||
}
|
||||
|
||||
// Use rAF to wait for the value of the getter function passed to not change for
|
||||
// at least 15 frames or timeout after 1 second.
|
||||
//
|
||||
// Example usage:
|
||||
// await waitForAnimationEnd(() => scroller.scrollTop);
|
||||
function waitForAnimationEnd(getValue) {
|
||||
const TIMEOUT = 1000; // milliseconds
|
||||
const MAX_UNCHANGED_FRAMES = 15;
|
||||
|
||||
const start_time = performance.now();
|
||||
let last_changed_frame = 0;
|
||||
let last_value = getValue();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
function tick(frames, time) {
|
||||
// We requestAnimationFrame either for TIMEOUT milliseconds or until
|
||||
// MAX_UNCHANGED_FRAMES with no change have been observed.
|
||||
if (time - start_time > TIMEOUT ||
|
||||
frames - last_changed_frame >= MAX_UNCHANGED_FRAMES) {
|
||||
resolve();
|
||||
} else {
|
||||
current_value = getValue();
|
||||
if (last_value != current_value) {
|
||||
last_changed_frame = frames;
|
||||
last_value = current_value;
|
||||
}
|
||||
requestAnimationFrame(tick.bind(this, frames + 1));
|
||||
}
|
||||
}
|
||||
tick(0, start_time);
|
||||
});
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue