Skip to content

Commit

Permalink
[@container] Move scroll-state() query tests to wpt
Browse files Browse the repository at this point in the history
The spec PR landed, so tests should now be supported by the spec.

The 'inset-' prefix for the stuck keywords per were not per spec and
remove both from tests and implementation.

The tests for the 'none'-keyword for snapped and stuck does not match
the current spec draft, but will be fixed by [1]

[1] w3c/csswg-drafts#10874

Bug: 40279568, 40268059
Change-Id: I7cf8d3a2f251eaea0c3a78329c46a7bfddd85dda
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5850484
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
Commit-Queue: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1354415}
  • Loading branch information
Rune Lillesveen authored and chromium-wpt-export-bot committed Sep 12, 2024
1 parent 121c225 commit d2c522e
Show file tree
Hide file tree
Showing 13 changed files with 653 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!DOCTYPE html>
<title>CSS Conditional Test: @container snapped query parsing</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-rule">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/css-conditional/container-queries/support/cq-testcommon.js"></script>
<div style="container-name:name;container-type:scroll-state">
<main id="main"></main>
</div>
<script>
setup(() => assert_implements_container_queries());

function cleanup_main() {
while (main.firstChild)
main.firstChild.remove();
}

function set_style(text) {
let style = document.createElement('style');
style.innerText = text;
main.append(style);
return style;
}

function test_rule_valid(query) {
test(t => {
t.add_cleanup(cleanup_main);
let style = set_style(`@container ${query} {}`);
assert_equals(style.sheet.rules.length, 1);
}, query);
}

function test_condition_invalid(condition) {
test(t => {
t.add_cleanup(cleanup_main);
let style = set_style(`@container name ${condition} {}`);
assert_equals(style.sheet.rules.length, 0);
}, condition);
}

// Tests that 1) the condition parses, and 2) is either "unknown" or not, as
// specified.
function test_condition_valid(condition, unknown) {
test(t => {
t.add_cleanup(cleanup_main);
let style = set_style(`
@container name ${condition} {}
@container name (${condition}) or (not (${condition})) { main { --match:true; } }
`);
assert_equals(style.sheet.rules.length, 2);
const expected = unknown ? '' : 'true';
assert_equals(getComputedStyle(main).getPropertyValue('--match'), expected);
}, condition);
}

function test_condition_known(condition) {
test_condition_valid(condition, false /* unknown */);
}

function test_condition_unknown(condition) {
test_condition_valid(condition, true /* unknown */);
}

test_condition_known('scroll-state(snapped)');
test_condition_known('scroll-state(snapped: x)');
test_condition_known('scroll-state(snapped: y)');
test_condition_known('scroll-state(snapped: none)');
test_condition_known('scroll-state(snapped: block)');
test_condition_known('scroll-state(snapped: inline)');
test_condition_known('(scroll-state(snapped: block))');
test_condition_known('scroll-state((snapped: inline))');
test_condition_known('scroll-state(not ((snapped: inline) and (snapped: block)))');
test_condition_known('scroll-state((snapped: x) or (snapped: y))');

test_condition_unknown('scroll-state(snapped: auto)');
test_condition_unknown('scroll-state(snapped: true)');
test_condition_unknown('scroll-state(style(snapped: inline))');
test_condition_unknown('style(scroll-state(snapped: inline))');
test_condition_unknown('scroll-state(snapped:)');
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<title>CSS Container Queries: scroll-state(snapped) conditionText serialization</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-queries">
<link rel="help" href="https://drafts.csswg.org/cssom/#serialize-a-css-rule">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/css-conditional/container-queries/support/cq-testcommon.js"></script>
<style id="testSheet">
@container scroll-state( snapped:inline) { }
@container scroll-STate(snapped: ) { }
@container scroll-STate(snapped) { }
@container scroll-state( ( snapped: INLINE) OR ( SNAPPED: BlOCK ) ) { }
@container scroll-state (snapped: inline) { }
</style>
<script>
setup(() => {
assert_implements_container_queries();
assert_equals(testSheet.sheet.cssRules.length, 5);
});

const tests = [
["scroll-state(snapped: inline)", "Normalize spaces"],
["scroll-STate(snapped: )", "No value - invalid, serializes as <general-enclosed>"],
["scroll-state(snapped)", "Boolean context"],
["scroll-state((snapped: inline) or (snapped: block))", "Logical with 'or'"],
["scroll-state (snapped: inline)", "Not a scroll-state function with space before '('"]
].map((e, i) => [testSheet.sheet.cssRules[i], ...e]);

tests.forEach((t) => {
test(() => assert_equals(t[0].conditionText, t[1]), t[2]);
});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<!DOCTYPE html>
<title>CSS Conditional Test: @container stuck query parsing</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-rule">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/css-conditional/container-queries/support/cq-testcommon.js"></script>
<div style="container-name:name;container-type:scroll-state">
<main id="main"></main>
</div>
<script>
setup(() => assert_implements_container_queries());

function cleanup_main() {
while (main.firstChild)
main.firstChild.remove();
}

function set_style(text) {
let style = document.createElement('style');
style.innerText = text;
main.append(style);
return style;
}

function test_rule_valid(query) {
test(t => {
t.add_cleanup(cleanup_main);
let style = set_style(`@container ${query} {}`);
assert_equals(style.sheet.rules.length, 1);
}, query);
}

function test_condition_invalid(condition) {
test(t => {
t.add_cleanup(cleanup_main);
let style = set_style(`@container name ${condition} {}`);
assert_equals(style.sheet.rules.length, 0);
}, condition);
}

// Tests that 1) the condition parses, and 2) is either "unknown" or not, as
// specified.
function test_condition_valid(condition, unknown) {
test(t => {
t.add_cleanup(cleanup_main);
let style = set_style(`
@container name ${condition} {}
@container name (${condition}) or (not (${condition})) { main { --match:true; } }
`);
assert_equals(style.sheet.rules.length, 2);
const expected = unknown ? '' : 'true';
assert_equals(getComputedStyle(main).getPropertyValue('--match'), expected);
}, condition);
}

function test_condition_known(condition) {
test_condition_valid(condition, false /* unknown */);
}

function test_condition_unknown(condition) {
test_condition_valid(condition, true /* unknown */);
}

test_condition_known('scroll-state(stuck)');
test_condition_known('scroll-state(stuck: none)');
test_condition_known('scroll-state(stuck: top)');
test_condition_known('scroll-state(stuck: left)');
test_condition_known('scroll-state(stuck: bottom)');
test_condition_known('scroll-state(stuck: right)');
test_condition_known('scroll-state(stuck: block-start)');
test_condition_known('scroll-state(stuck: block-end)');
test_condition_known('scroll-state(stuck: inline-start)');
test_condition_known('scroll-state(stuck: inline-end)');
test_condition_known('(scroll-state(stuck: top))');
test_condition_known('scroll-state((stuck: top))');
test_condition_known('scroll-state(not ((stuck: top) and (stuck: bottom)))');
test_condition_known('scroll-state((stuck: right) or (stuck: left))');

test_condition_unknown('scroll-state(stuck: auto)');
test_condition_unknown('scroll-state(stuck: true)');
test_condition_unknown('scroll-state(style(stuck: top))');
test_condition_unknown('style(scroll-state(stuck: top))');
test_condition_unknown('scroll-state(stuck:)');
test_condition_unknown('scroll-state(--foo)');
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<title>CSS Container Queries: scroll-state(stuck) conditionText serialization</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-queries">
<link rel="help" href="https://drafts.csswg.org/cssom/#serialize-a-css-rule">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/css-conditional/container-queries/support/cq-testcommon.js"></script>
<style id="testSheet">
@container scroll-state( stuck:top) { }
@container scroll-STate(stuck: ) { }
@container scroll-STate(stuck) { }
@container scroll-state( ( stuck: BOTTOM) OR ( STUCK: inline-START ) ) { }
@container scroll-state (stuck: top) { }
</style>
<script>
setup(() => {
assert_implements_container_queries();
assert_equals(testSheet.sheet.cssRules.length, 5);
});

const tests = [
["scroll-state(stuck: top)", "Normalize spaces"],
["scroll-STate(stuck: )", "No value - invalid, serializes as <general-enclosed>"],
["scroll-state(stuck)", "Boolean context"],
["scroll-state((stuck: bottom) or (stuck: inline-start))", "Logical with 'or'"],
["scroll-state (stuck: top)", "Not a scroll-state function with space before '('"]
].map((e, i) => [testSheet.sheet.cssRules[i], ...e]);

tests.forEach((t) => {
test(() => assert_equals(t[0].conditionText, t[1]), t[2]);
});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Conditional Test: Computed values of container-type with scroll-state</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-type">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/computed-testcommon.js"></script>
<script src="/css/css-conditional/container-queries/support/cq-testcommon.js"></script>
<div id="target"></div>
<script>
setup(() => assert_implements_container_queries());

test_computed_value('container-type', 'scroll-state');
test_computed_value('container-type', 'scroll-state size', 'size scroll-state');
test_computed_value('container-type', 'inline-size scroll-state');
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<title>CSS Container Queries: container type scroll-state</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-type">
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/6402#issuecomment-1812973013">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/css-conditional/container-queries/support/cq-testcommon.js"></script>
<style>
body { margin: 0; }
#container {
margin-top: 100px;
container-type: scroll-state;
width: fit-content;
}
#child {
margin-top: 100px;
width: 100px;
height: 100px;
}
</style>
<div id="container">
<div id="child">Non-zero-content</div>
</div>
<script>
test(() => {
assert_equals(container.offsetWidth, 100, "Intrinsically sized width");
assert_equals(container.offsetHeight, 100, "Intrinsically sized height");
}, "container-type:scroll-state does not apply size containment");

test(() => {
assert_equals(child.getBoundingClientRect().y, 100,
"#container and #child margins collapsed");
}, "container-type:scroll-state does not establish a formatting context");
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Conditional Test: Parsing of container-type with scroll-state</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-type">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<script src="/css/css-conditional/container-queries/support/cq-testcommon.js"></script>
<div id="target"></div>
<script>
setup(() => assert_implements_container_queries());

test_valid_value('container-type', 'scroll-state');
test_valid_value('container-type', 'size scroll-state');
test_valid_value('container-type', 'scroll-state inline-size', 'inline-size scroll-state');

test_invalid_value('container-type', 'scroll-state scroll-state');
test_invalid_value('container-type', 'normal scroll-state');
test_invalid_value('container-type', 'inline-size block-size scroll-state');
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!DOCTYPE html>
<title>@container: scroll-state(snapped) matching for initial rendering</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-rule">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/css-conditional/container-queries/support/cq-testcommon.js"></script>
<script src="/css/css-transitions/support/helper.js"></script>
<style>
:root {
scroll-snap-type: block mandatory;
}
body {
margin: 0;
}
#filler-before {
height: 200px;
}
#filler-after {
height: 10000px;
}
#snapped {
container-name: initially-snapped;
container-type: scroll-state;
scroll-snap-align: start;
width: 100px;
height: 100px;
background: teal;
}

@container initially-snapped scroll-state(snapped: block) {
span { --snapped: yes }
}
</style>
<div id="filler-before"></div>
<div id="snapped">
<span id="target">My container is snapped</span>
</div>
<div id="filler-after"></div>
<script>
setup(() => assert_implements_container_queries());

promise_test(async t => {
await waitForAnimationFrames(2);
assert_equals(getComputedStyle(target).getPropertyValue("--snapped"), "yes");
assert_equals(document.documentElement.scrollTop, 200);
}, "Check that scroll-state(snapped: block) matches");
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<title>@container: scroll-state(stuck) matching for initial rendering</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-rule">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/css-conditional/container-queries/support/cq-testcommon.js"></script>
<script src="/css/css-transitions/support/helper.js"></script>
<style>
#filler {
height: 10000px;
}
#stuck {
container-name: initially-stuck;
container-type: scroll-state;
position: sticky;
bottom: 0;
}

@container initially-stuck scroll-state(stuck: bottom) {
span { --stuck: yes }
}
</style>
<div id="filler"></div>
<div id="stuck">
<span id="target">My container is stuck</span>
</div>
<script>
setup(() => assert_implements_container_queries());

promise_test(async t => {
await waitForAnimationFrames(2);
assert_equals(getComputedStyle(target).getPropertyValue("--stuck"), "yes");
}, "Check that scroll-state(stuck: bottom) matches");
</script>
Loading

0 comments on commit d2c522e

Please sign in to comment.