Tests: Import WPT container-unit tests

We've skipped the ref-tests for now, and will import them once they pass
instead.
This commit is contained in:
Sam Atkins 2026-05-28 14:51:59 +01:00
parent 24e767a06e
commit bf2c799aee
33 changed files with 1396 additions and 0 deletions

View file

@ -0,0 +1,29 @@
Harness status: OK
Found 24 tests
24 Fail
Fail CSS Animation using cqw unit
Fail CSS Animation using cqw unit responds to changing container size
Fail CSS Animation using cqh unit
Fail CSS Animation using cqh unit responds to changing container size
Fail CSS Animation using cqi unit
Fail CSS Animation using cqi unit responds to changing container size
Fail CSS Animation using cqb unit
Fail CSS Animation using cqb unit responds to changing container size
Fail CSS Animation using cqmin unit
Fail CSS Animation using cqmin unit responds to changing container size
Fail CSS Animation using cqmax unit
Fail CSS Animation using cqmax unit responds to changing container size
Fail Web Animation using cqw unit
Fail Web Animation using cqw unit responds to changing container size
Fail Web Animation using cqh unit
Fail Web Animation using cqh unit responds to changing container size
Fail Web Animation using cqi unit
Fail Web Animation using cqi unit responds to changing container size
Fail Web Animation using cqb unit
Fail Web Animation using cqb unit responds to changing container size
Fail Web Animation using cqmin unit
Fail Web Animation using cqmin unit responds to changing container size
Fail Web Animation using cqmax unit
Fail Web Animation using cqmax unit responds to changing container size

View file

@ -0,0 +1,6 @@
Harness status: OK
Found 1 tests
1 Fail
Fail Resolving cqh against a auto height size container should be 0

View file

@ -0,0 +1,7 @@
Harness status: OK
Found 2 tests
2 Fail
Fail Container relative units
Fail Container relative units in math functions

View file

@ -0,0 +1,11 @@
Harness status: OK
Found 6 tests
6 Pass
Pass Container relative unit cqw is not computationally independent
Pass Container relative unit cqh is not computationally independent
Pass Container relative unit cqi is not computationally independent
Pass Container relative unit cqb is not computationally independent
Pass Container relative unit cqmin is not computationally independent
Pass Container relative unit cqmax is not computationally independent

View file

@ -0,0 +1,7 @@
Harness status: OK
Found 2 tests
2 Fail
Fail Container units are relative to the content box of the container
Fail Container units are relative to the content box of the container (box-sizing: border-box)

View file

@ -0,0 +1,6 @@
Harness status: OK
Found 1 tests
1 Fail
Fail Query with container-relative units are responsive to changes

View file

@ -0,0 +1,6 @@
Harness status: OK
Found 1 tests
1 Fail
Fail Use small viewport size as fallback

View file

@ -0,0 +1,23 @@
Harness status: OK
Found 18 tests
18 Fail
Fail cqw unit resolves against appropriate container
Fail cqh unit resolves against appropriate container
Fail cqi unit resolves against appropriate container
Fail cqb unit resolves against appropriate container
Fail cqmin unit resolves against appropriate container
Fail cqmax unit resolves against appropriate container
Fail cqw unit resolves against appropriate container (vertical writing-mode on subject)
Fail cqh unit resolves against appropriate container (vertical writing-mode on subject)
Fail cqi unit resolves against appropriate container (vertical writing-mode on subject)
Fail cqb unit resolves against appropriate container (vertical writing-mode on subject)
Fail cqmin unit resolves against appropriate container (vertical writing-mode on subject)
Fail cqmax unit resolves against appropriate container (vertical writing-mode on subject)
Fail cqw unit resolves against appropriate container (vertical writing-mode on container)
Fail cqh unit resolves against appropriate container (vertical writing-mode on container)
Fail cqi unit resolves against appropriate container (vertical writing-mode on container)
Fail cqb unit resolves against appropriate container (vertical writing-mode on container)
Fail cqmin unit resolves against appropriate container (vertical writing-mode on container)
Fail cqmax unit resolves against appropriate container (vertical writing-mode on container)

View file

@ -0,0 +1,14 @@
Harness status: OK
Found 9 tests
9 Fail
Fail /* basic */
Fail display: table
Fail display: table-cell
Fail display: inline
Fail display: contents
Fail display: none
Fail container-type: normal
Fail container-type: inline-size
Fail container-type: inline-size; writing-mode: vertical-lr

View file

@ -0,0 +1,10 @@
Harness status: OK
Found 5 tests
5 Fail
Fail cqi respond when selected container changes type (inline-size -> normal)
Fail cqb respond when selected container changes type (size -> normal)
Fail cqb respond when intermediate container changes type (inline-size -> size)
Fail cqi respond when selected container changes inline-size
Fail cqb respond when selected container changes block-size

View file

@ -0,0 +1,14 @@
Harness status: OK
Found 8 tests
2 Pass
6 Fail
Fail @media(width:100cqw) applies
Fail @media(width:100cqi) applies
Fail @media(width:100cqmax) applies
Fail @media(height:100cqh) applies
Fail @media(height:100cqb) applies
Fail @media(height:100cqmin) applies
Pass @media(width:90cqw) does not apply
Pass @media(height:90cqh) does not apply

View file

@ -0,0 +1,7 @@
Harness status: OK
Found 2 tests
2 Fail
Fail Container units select the proper container
Fail Units respond to the writing-mode of the element

View file

@ -0,0 +1,7 @@
Harness status: OK
Found 2 tests
2 Fail
Fail Direct slotted child queries flat tree
Fail Nondirect slotted child queries flat tree ancestors

View file

@ -0,0 +1,6 @@
Harness status: OK
Found 1 tests
1 Fail
Fail Use small viewport size as fallback

View file

@ -0,0 +1,13 @@
Harness status: OK
Found 7 tests
1 Pass
6 Fail
Pass unitType with container-relative units
Fail cqw,cqh can be resolved
Fail cqi,cqb can be resolved
Fail cqmin,cqmax can be resolved
Fail calc() with container-relative units can be resolved
Fail Can modify value with container-relative units
Fail CSS Container Queries Test: container-relative units in SVGLength

View file

@ -0,0 +1,29 @@
Harness status: OK
Found 24 tests
24 Fail
Fail CSS.cqw function
Fail Reify value with cqw unit
Fail Set value with cqw unit (string)
Fail Set value with cqw unit (CSS.cqw)
Fail CSS.cqh function
Fail Reify value with cqh unit
Fail Set value with cqh unit (string)
Fail Set value with cqh unit (CSS.cqh)
Fail CSS.cqi function
Fail Reify value with cqi unit
Fail Set value with cqi unit (string)
Fail Set value with cqi unit (CSS.cqi)
Fail CSS.cqb function
Fail Reify value with cqb unit
Fail Set value with cqb unit (string)
Fail Set value with cqb unit (CSS.cqb)
Fail CSS.cqmin function
Fail Reify value with cqmin unit
Fail Set value with cqmin unit (string)
Fail Set value with cqmin unit (CSS.cqmin)
Fail CSS.cqmax function
Fail Reify value with cqmax unit
Fail Set value with cqmax unit (string)
Fail Set value with cqmax unit (CSS.cqmax)

View file

@ -0,0 +1,112 @@
<!doctype html>
<title>Container Relative Units: Animation</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
#container {
container-type: size;
width: 200px;
height: 200px;
}
@keyframes anim_cqw { from { top: 20cqw; } to { top: 40cqw; } }
@keyframes anim_cqh { from { top: 20cqh; } to { top: 40cqh; } }
@keyframes anim_cqi { from { top: 20cqi; } to { top: 40cqi; } }
@keyframes anim_cqb { from { top: 20cqb; } to { top: 40cqb; } }
@keyframes anim_cqmin { from { top: 20cqmin; } to { top: 40cqmin; } }
@keyframes anim_cqmax { from { top: 20cqmax; } to { top: 40cqmax; } }
#container > div.css-animation {
animation-delay: -5s;
animation-play-state: paused;
animation-duration: 10s;
animation-timing-function: linear;
}
.css-animation.cqw { animation-name: anim_cqw; }
.css-animation.cqh { animation-name: anim_cqh; }
.css-animation.cqi { animation-name: anim_cqi; }
.css-animation.cqb { animation-name: anim_cqb; }
.css-animation.cqmin { animation-name: anim_cqmin; }
.css-animation.cqmax { animation-name: anim_cqmax; }
</style>
<div id=container>
<div class="css-animation cqw"></div>
<div class="css-animation cqh"></div>
<div class="css-animation cqi"></div>
<div class="css-animation cqb"></div>
<div class="css-animation cqmin"></div>
<div class="css-animation cqmax"></div>
<div class="web-animation cqw"></div>
<div class="web-animation cqh"></div>
<div class="web-animation cqi"></div>
<div class="web-animation cqb"></div>
<div class="web-animation cqmin"></div>
<div class="web-animation cqmax"></div>
</div>
<script>
setup(() => assert_implements_size_container_queries());
const units = ['cqw', 'cqh', 'cqi', 'cqb', 'cqmin', 'cqmax'];
for (let unit of units) {
test(() => {
let element = document.querySelector(`.css-animation.${unit}`)
assert_equals(getComputedStyle(element).top, '60px');
}, `CSS Animation using ${unit} unit`);
test(() => {
let element = document.querySelector(`.css-animation.${unit}`)
assert_equals(getComputedStyle(element).top, '60px');
try {
container.style.width = '300px';
container.style.height = '300px';
assert_equals(getComputedStyle(element).top, '90px');
} finally {
container.style = '';
}
assert_equals(getComputedStyle(element).top, '60px');
}, `CSS Animation using ${unit} unit responds to changing container size`);
}
const keyframes = {
"cqw" : { top: ["20cqw", "40cqw"] },
"cqh" : { top: ["20cqh", "40cqh"] },
"cqi" : { top: ["20cqi", "40cqi"] },
"cqb" : { top: ["20cqb", "40cqb"] },
"cqmin" : { top: ["20cqmin", "40cqmin"] },
"cqmax" : { top: ["20cqmax", "40cqmax"] }
};
for (const unit in keyframes) {
const target = document.querySelector(`.web-animation.${unit}`);
const assert_top = expected => assert_equals(getComputedStyle(target).top, expected);
const animation = target.animate(keyframes[unit], 10 * 1000);
animation.currentTime = 5 * 1000;
animation.pause();
test(() => {
assert_top('60px');
}, `Web Animation using ${unit} unit`);
test(() => {
assert_top('60px');
try {
container.style.width = '300px';
container.style.height = '300px';
assert_top('90px');
} finally {
container.style = '';
}
assert_top('60px');
}, `Web Animation using ${unit} unit responds to changing container size`);
}
</script>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<title>CSS Container Queries Test: auto sized size container unit</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<style>
#container {
container-type: size;
}
#target {
width: 100cqh;
height: calc(100px + 1000cqh);
}
</style>
<div id="container">
<div id="target"></div>
</div>
<script>
test(() => {
assert_equals(getComputedStyle(target).width, "0px");
assert_equals(getComputedStyle(target).height, "100px");
}, "Resolving cqh against a auto height size container should be 0");
</script>

View file

@ -0,0 +1,54 @@
<!doctype html>
<title>Container Relative Units: cqi, cqb, etc</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
.inline { container-type: inline-size; }
.size { container-type: size; }
.inline.outer { width: 500px; }
.size.outer { height: 400px; }
.inline.inner { width: 300px; }
</style>
<div id=ref></div>
<div class="inline outer">
<div class="size outer">
<div class="inline inner">
<div id=child>Test</div>
</div>
</div>
</div>
<script>
setup(() => assert_implements_size_container_queries());
function assert_unit_equals(element, actual, expected) {
try {
element.style.padding = actual;
ref.style.padding = expected;
assert_equals(getComputedStyle(element).paddingLeft,
getComputedStyle(ref).paddingLeft);
} finally {
element.style = '';
ref.style = '';
}
}
test(function() {
assert_unit_equals(child, '0cqi', '0px');
assert_unit_equals(child, '1cqi', '3px');
assert_unit_equals(child, '10cqi', '30px');
assert_unit_equals(child, '10cqw', '30px');
assert_unit_equals(child, '10cqb', '40px');
assert_unit_equals(child, '10cqh', '40px');
assert_unit_equals(child, '10cqmin', '30px');
assert_unit_equals(child, '10cqmax', '40px');
}, 'Container relative units');
test(function() {
assert_unit_equals(child, '10cqi', '30px');
assert_unit_equals(child, '10cqb', '40px');
assert_unit_equals(child, 'calc(10cqi + 10cqb)', '70px');
assert_unit_equals(child, 'max(10cqi, 10cqb)', '40px');
}, 'Container relative units in math functions');
</script>

View file

@ -0,0 +1,20 @@
<!doctype html>
<title>Container Relative Units: Computationally independent</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1/#computationally-independent">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<script>
setup(() => assert_implements_size_container_queries());
const units = ['cqw', 'cqh', 'cqi', 'cqb', 'cqmin', 'cqmax'];
for (let unit of units) {
test(function() {
assert_throws_dom('SyntaxError', () => {
CSS.registerProperty({ name: '--x', inherits: false, syntax: '<length>', initialValue: `1${unit}` });
});
}, `Container relative unit ${unit} is not computationally independent`);
}
</script>

View file

@ -0,0 +1,58 @@
<!doctype html>
<title>Container Relative Units: evaluate against the content box</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
.size {
container-type: size;
width:100px;
height:50px;
border: 10px solid green;
padding: 10px;
}
.border-box {
box-sizing: border-box;
}
</style>
<div id=ref></div>
<div class="size">
<div id=child></div>
</div>
<div class="size border-box">
<div id=child2></div>
</div>
<script>
setup(() => assert_implements_size_container_queries());
function assert_unit_equals(element, actual, expected) {
try {
element.style.padding = actual;
ref.style.padding = expected;
assert_equals(getComputedStyle(element).paddingLeft,
getComputedStyle(ref).paddingLeft);
} finally {
element.style = '';
ref.style = '';
}
}
test(function() {
assert_unit_equals(child, '10cqi', '10px');
assert_unit_equals(child, '10cqw', '10px');
assert_unit_equals(child, '10cqb', '5px');
assert_unit_equals(child, '10cqh', '5px');
assert_unit_equals(child, '10cqmin', '5px');
assert_unit_equals(child, '10cqmax', '10px');
}, 'Container units are relative to the content box of the container');
test(function() {
assert_unit_equals(child2, '10cqi', '6px');
assert_unit_equals(child2, '10cqw', '6px');
assert_unit_equals(child2, '10cqb', '1px');
assert_unit_equals(child2, '10cqh', '1px');
assert_unit_equals(child2, '10cqmin', '1px');
assert_unit_equals(child2, '10cqmax', '6px');
}, 'Container units are relative to the content box of the container (box-sizing: border-box)');
</script>

View file

@ -0,0 +1,37 @@
<!doctype html>
<title>Container Relative Units: in @container prelude (dynamic)</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
#outer {
container-type: size;
width: 40px;
height: 40px;
}
#container {
container-type: size;
width: 16px;
height: 16px;
}
@container ((width = 16px) and (width = 50cqw)) { #child { --cqw:true; } }
</style>
<div id=outer>
<div id=container>
<div id=child>Test</div>
</div>
</div>
<script>
setup(() => assert_implements_size_container_queries());
test(() => {
assert_equals(getComputedStyle(child).getPropertyValue('--cqw'), '');
outer.style.width = '32px';
assert_equals(getComputedStyle(child).getPropertyValue('--cqw'), 'true');
}, 'Query with container-relative units are responsive to changes');
</script>

View file

@ -0,0 +1,68 @@
<!DOCTYPE html>
<title>Container Relative Units: container relative units fall back to small viewport</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
iframe {
width: 200px;
height: 320px;
}
</style>
<iframe id=iframe srcdoc="
<style>
#parent {
container-type: inline-size;
width: 64px;
height: 50px;
}
#container {
container-type: size;
width: 32px;
height: 32px;
}
#target1, #target2 { color: green; }
/* Unit should evaluate against width of #parent */
@container ((height = 32px) and (height = 50cqw)) {
#target1 { color: blue; }
}
/* Unit should evaluate against height of iframe */
@container ((height = 32px) and (height = 10cqh)) {
#target2 { color: blue; }
}
</style>
<div id=parent>
<div id=container>
<div id=target1></div>
<div id=target2></div>
</div>
</div>
"></iframe>
<script>
setup(() => assert_implements_size_container_queries());
function waitForLoad(w) {
return new Promise(resolve => w.addEventListener('load', resolve));
}
promise_test(async () => {
await waitForLoad(window);
let inner_target1 = iframe.contentDocument.querySelector('#target1');
let inner_target2 = iframe.contentDocument.querySelector('#target2');
assert_equals(getComputedStyle(inner_target1).color, 'rgb(0, 0, 255)');
assert_equals(getComputedStyle(inner_target2).color, 'rgb(0, 0, 255)');
iframe.style = 'height:400px';
// #target1 is not affected since it evaluated against another container.
// #target2 *is* affected, because it evaluated against the iframe size
// which just changed.
assert_equals(getComputedStyle(inner_target1).color, 'rgb(0, 0, 255)');
assert_equals(getComputedStyle(inner_target2).color, 'rgb(0, 128, 0)');
}, 'Use small viewport size as fallback');
</script>

View file

@ -0,0 +1,111 @@
<!doctype html>
<title>Container Relative Units: in @container prelude</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
.size { container-type: size; }
.inline { container-type: inline-size; }
.ancestor {
container-type: size;
width: 64px;
height: 160px;
}
.parent {
container-type: inline-size;
width: 32px;
height: 77px;
}
.container {
container-type: size;
width: 16px;
height: 16px;
}
/* Unit should resolve against .parent width. */
@container ((width = 16px) and (width = 50cqw)) { #child1 { --cqw:true; } }
/* Unit should resolve against .ancestor height. */
@container ((width = 16px) and (width = 10cqh)) { #child1 { --cqh:true; } }
/* Unit should resolve against .parent width. */
@container ((width = 16px) and (width = 50cqi)) { #child1 { --cqi:true; } }
/* Unit should resolve against .ancestor height. */
@container ((width = 16px) and (width = 10cqb)) { #child1 { --cqb:true; } }
/* Unit should resolve against biggest of w/h. */
@container ((width = 16px) and (width = 10cqmax)) { #child1 { --cqmax:true; } }
/* Unit should resolve against smallest of w/h. */
@container ((width = 16px) and (width = 50cqmin)) { #child1 { --cqmin:true; } }
/* Flipped writing mode: */
/* Non-logical units are the same as above */
@container ((width = 16px) and (width = 50cqw)) { #child2 { --cqw:true; } }
@container ((width = 16px) and (width = 10cqh)) { #child2 { --cqh:true; } }
@container ((width = 16px) and (width = 10cqmax)) { #child2 { --cqmax:true; } }
@container ((width = 16px) and (width = 50cqmin)) { #child2 { --cqmin:true; } }
/* Unit should resolve against .ancestor height. */
@container ((width = 16px) and (width = 50cqb)) { #child2 { --cqi:true; } }
/* Unit should resolve against .parent width. */
@container ((width = 16px) and (width = 10cqi)) { #child2 { --cqb:true; } }
</style>
<div class=ancestor>
<div class=parent>
<div class=container>
<div id=child1>Test1</div>
</div>
</div>
</div>
<div class=ancestor>
<div class=parent>
<div class=container style="writing-mode:vertical-rl;">
<div id=child2>Test1</div>
</div>
</div>
</div>
<script>
setup(() => assert_implements_size_container_queries());
let units = [
'cqw',
'cqh',
'cqi',
'cqb',
'cqmin',
'cqmax',
];
for (let unit of units) {
test(() => {
assert_equals(getComputedStyle(child1).getPropertyValue(`--${unit}`), 'true');
}, `${unit} unit resolves against appropriate container`);
}
// Ensure that the writing mode of the subject element is not relevant for
// container-relative units in the @container prelude.
for (let unit of units) {
test((t) => {
t.add_cleanup(() => {
child1.style = '';
});
child1.style.writingMode = 'vertical-rl';
assert_equals(getComputedStyle(child1).getPropertyValue(`--${unit}`), 'true');
}, `${unit} unit resolves against appropriate container (vertical writing-mode on subject)`);
}
for (let unit of units) {
test(() => {
assert_equals(getComputedStyle(child2).getPropertyValue(`--${unit}`), 'true');
}, `${unit} unit resolves against appropriate container (vertical writing-mode on container)`);
}
</script>

View file

@ -0,0 +1,44 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Container Relative Units: ineligible container</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
<style>
#grandparent, #parent { container-type: size; }
#grandparent { width: 300px; height: 250px; }
#parent { width: 200px; height: 150px; }
#target { width: 10cqw; height: 10cqh; }
</style>
<div id="log"></div>
<div id="grandparent">
<div id="parent">
<div id="target"></div>
</div>
</div>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<script>
setup(() => assert_implements_size_container_queries());
const cases = {
"/* basic */": [20, 15],
"display: table": [30, 25],
"display: table-cell": [30, 25],
"display: inline": [30, 25],
"display: contents": [30, 25],
"display: none": [30, 25],
"container-type: normal": [30, 25],
"container-type: inline-size": [20, 25],
"container-type: inline-size; writing-mode: vertical-lr": [30, 15],
};
const parent = document.getElementById("parent");
const target = document.getElementById("target");
const cs = getComputedStyle(target);
for (let [style, [width, height]] of Object.entries(cases)) {
test(() => {
parent.style.cssText = style;
assert_equals(cs.width, width + "px", "width");
assert_equals(cs.height, height + "px", "height");
}, style);
}
</script>

View file

@ -0,0 +1,119 @@
<!doctype html>
<title>Container Relative Units: Invalidation</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
#inline { container-type: inline-size; }
#size, #outer { container-type: size; }
.h600 { height: 600px; }
.w500 { width: 500px; }
.h400 { height: 400px; }
.w300 { width: 300px; }
.child {
padding-left: 10cqi;
padding-right: 10cqb;
}
</style>
<div id=ref></div>
<div id=outer class="h600">
<div id=size class="w500 h400">
<div id=inline class="w300">
<div id=child class="child">Test</div>
<div><div id=deeper class="child">Test</div></div>
</div>
</div>
</div>
<script>
setup(() => assert_implements_size_container_queries());
function assert_cqi_equals(element, expected) {
assert_equals(getComputedStyle(element).paddingLeft, expected);
}
function assert_cqb_equals(element, expected) {
assert_equals(getComputedStyle(element).paddingRight, expected);
}
test(function(t) {
assert_cqi_equals(child, '30px');
assert_cqi_equals(deeper, '30px');
try {
inline.style.containerType = 'normal';
assert_cqi_equals(child, '50px');
assert_cqi_equals(deeper, '50px');
} finally {
inline.style = '';
}
assert_cqi_equals(child, '30px');
assert_cqi_equals(deeper, '30px');
}, `cqi respond when selected container changes type (inline-size -> normal)`);
test(function() {
assert_cqb_equals(child, '40px');
assert_cqb_equals(deeper, '40px');
try {
size.style.containerType = 'normal';
assert_cqb_equals(child, '60px');
assert_cqb_equals(deeper, '60px');
} finally {
size.style = '';
}
assert_cqb_equals(child, '40px');
assert_cqb_equals(deeper, '40px');
}, `cqb respond when selected container changes type (size -> normal)`);
test(function() {
assert_cqb_equals(child, '40px');
assert_cqb_equals(deeper, '40px');
try {
inline.style.containerType = 'size';
inline.style.height = '200px';
assert_cqb_equals(child, '20px');
assert_cqb_equals(deeper, '20px');
} finally {
inline.style = '';
}
assert_cqb_equals(child, '40px');
assert_cqb_equals(deeper, '40px');
}, `cqb respond when intermediate container changes type (inline-size -> size)`);
test(function() {
assert_cqi_equals(child, '30px');
assert_cqi_equals(deeper, '30px');
try {
inline.style.width = '50px';
assert_cqi_equals(child, '5px');
assert_cqi_equals(deeper, '5px');
} finally {
inline.style = '';
}
assert_cqi_equals(child, '30px');
assert_cqi_equals(deeper, '30px');
}, 'cqi respond when selected container changes inline-size');
test(function() {
assert_cqb_equals(child, '40px');
assert_cqb_equals(deeper, '40px');
try {
size.style.height = '50px';
assert_cqb_equals(child, '5px');
assert_cqb_equals(deeper, '5px');
} finally {
size.style = '';
}
assert_cqb_equals(child, '40px');
assert_cqb_equals(deeper, '40px');
}, 'cqb respond when selected container changes block-size');
</script>

View file

@ -0,0 +1,61 @@
<!DOCTYPE html>
<title>Container-relative units in @media</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
iframe {
width: 200px;
height: 100px;
}
</style>
<iframe id=iframe></iframe>
<script>
setup(() => assert_implements_size_container_queries());
const doc = iframe.contentDocument;
const win = iframe.contentWindow;
function test_media_query(feature, result, description) {
test((t) => {
t.add_cleanup(() => { doc.body.innerHTML = ''; })
doc.body.innerHTML = `
<style>
body {
color: red;
}
@media (${feature}) {
body {
color: green;
}
}
</style>
`;
assert_equals(win.getComputedStyle(doc.body).color, result);
}, description);
}
function test_media_query_applies(feature) {
test_media_query(feature, 'rgb(0, 128, 0)', `@media(${feature}) applies`);
}
function test_media_query_does_not_apply(feature) {
test_media_query(feature, 'rgb(255, 0, 0)', `@media(${feature}) does not apply`);
}
// Container-relative units resolve against the "small viewport size" for
// media queries.
test_media_query_applies('width:100cqw');
test_media_query_applies('width:100cqi');
test_media_query_applies('width:100cqmax');
test_media_query_applies('height:100cqh');
test_media_query_applies('height:100cqb');
test_media_query_applies('height:100cqmin');
test_media_query_does_not_apply('width:90cqw');
test_media_query_does_not_apply('height:90cqh');
</script>

View file

@ -0,0 +1,105 @@
<!doctype html>
<title>Container Relative Units: Advanced Container Selection</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
* { writing-mode: initial; }
.inline { container-type: inline-size; }
.size { container-type: size; }
.vertical { writing-mode: vertical-rl; }
.w500 { width: 500px; }
.h400 { height: 400px; }
.w300 { width: 300px; }
.h200 { height: 200px; }
.w100 { width: 100px; }
</style>
<div id=ref></div>
<div id=c1>
<div id=c2>
<div id=c3>
<div id=c4>
<div id=child>Test</div>
</div>
</div>
</div>
</div>
<script>
setup(() => assert_implements_size_container_queries());
function assert_unit_equals(element, actual, expected) {
try {
element.style.margin = actual;
ref.style.margin = expected;
assert_equals(getComputedStyle(element).marginLeft,
getComputedStyle(ref).marginLeft);
} finally {
element.style = '';
ref.style = '';
}
}
test(() => {
try {
c1.className = 'inline w500'; // Selected by nothing.
c2.className = 'size h400 w300'; // Selected by cqh, cqb.
c3.className = 'inline w100'; // Selected by cqw, cqi.
assert_unit_equals(child, '10cqw', '10px');
assert_unit_equals(child, '10cqi', '10px');
assert_unit_equals(child, '10cqh', '40px');
assert_unit_equals(child, '10cqb', '40px');
assert_unit_equals(child, '10cqmin', '10px');
assert_unit_equals(child, '10cqmax', '40px');
assert_unit_equals(child, '-10cqmin', '-10px');
assert_unit_equals(child, '-10cqmax', '-40px');
c3.className = ''; // cqw, cqi now selects c2 instead.
assert_unit_equals(child, '10cqw', '30px');
assert_unit_equals(child, '10cqi', '30px');
assert_unit_equals(child, '10cqh', '40px');
assert_unit_equals(child, '10cqb', '40px');
assert_unit_equals(child, '10cqmin', '30px');
assert_unit_equals(child, '10cqmax', '40px');
assert_unit_equals(child, '-10cqmin', '-30px');
assert_unit_equals(child, '-10cqmax', '-40px');
} finally {
for (let c of [c1, c2, c3, c4, child])
c.className = '';
}
}, 'Container units select the proper container');
test(() => {
try {
c1.className = 'size w500 h400';
c2.className = 'inline w300 h200';
// [cqi, cqb] corresponds to [cqw, cqh].
assert_unit_equals(child, '10cqw', '30px');
assert_unit_equals(child, '10cqi', '30px');
assert_unit_equals(child, '10cqh', '40px');
assert_unit_equals(child, '10cqb', '40px');
child.className = 'vertical';
// [cqi, cqb] now corresponds to [cqh, cqw].
assert_unit_equals(child, '10cqw', '30px');
assert_unit_equals(child, '10cqi', '40px');
assert_unit_equals(child, '10cqh', '40px');
assert_unit_equals(child, '10cqb', '30px');
c2.classList.add('vertical');
// The inline containment on #c2 now applies to the vertical axis.
// [cqi, cqb] still corresponds to [cqh, cqw], but we now expect
// cqh to resolve against #c2, and cqw to resolve against #c1.
assert_unit_equals(child, '10cqw', '50px');
assert_unit_equals(child, '10cqi', '20px');
assert_unit_equals(child, '10cqh', '20px');
assert_unit_equals(child, '10cqb', '50px');
} finally {
for (let c of [c1, c2, c3, c4, child])
c.className = '';
}
}, 'Units respond to the writing-mode of the element');
</script>

View file

@ -0,0 +1,63 @@
<!doctype html>
<title>Container Relative Units: Shadow DOM</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-queries">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
#outer {
container-type: size;
width: 200px;
height: 200px;
}
#direct {
container-type: inline-size;
width: 50cqw;
height: 50cqh;
}
#nondirect {
width: 10cqw;
height: 10cqh;
background: green;
}
</style>
<div id=outer>
<div>
<template shadowrootmode="open">
<style>
#inner {
container-type: size;
width: 30px;
height: 30px;
}
</style>
<div id=inner>
<slot></slot>
</div>
</template>
<div>
<div id=direct>
<div id=nondirect>
</div>
</div>
</div>
</div>
</div>
<script>
setup(() => {
assert_implements_size_container_queries();
});
test(() => {
let cs = getComputedStyle(direct);
assert_equals(cs.width, '15px');
assert_equals(cs.height, '15px');
}, 'Direct slotted child queries flat tree');
test(() => {
let cs = getComputedStyle(nondirect);
assert_equals(cs.width, '1.5px');
assert_equals(cs.height, '3px');
}, 'Nondirect slotted child queries flat tree ancestors');
</script>

View file

@ -0,0 +1,70 @@
<!doctype html>
<title>Container Relative Units: fall back to small viewport</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
iframe {
width: 200px;
height: 40px;
}
</style>
<iframe id=iframe srcdoc="
<style>
#container {
container-type: inline-size;
width: 70px;
height: 30px;
}
#target {
left: 10cqw;
top: 10cqh;
right: 10cqi;
bottom: 10cqb;
margin-left: 10cqmax;
margin-right: 10cqmin;
}
</style>
<div id=container>
<div id=target></div>
</div>
"></iframe>
<script>
setup(() => assert_implements_size_container_queries());
function waitForLoad(w) {
return new Promise(resolve => w.addEventListener('load', resolve));
}
promise_test(async () => {
await waitForLoad(window);
let inner_target = iframe.contentDocument.querySelector('#target');
// Since there's an inline-size container, cqw/cqi should evaluate against
// that.
assert_equals(getComputedStyle(inner_target).left, '7px'); // 10cqw
assert_equals(getComputedStyle(inner_target).right, '7px'); // 10cqi
// However, there is no size container, so cqh/cqb should evaluate against
// the small viewport size.
assert_equals(getComputedStyle(inner_target).top, '4px'); // 10cqh
assert_equals(getComputedStyle(inner_target).bottom, '4px'); // 10cqb
assert_equals(getComputedStyle(inner_target).marginLeft, '7px'); // 10cqmax
assert_equals(getComputedStyle(inner_target).marginRight, '4px'); // 10cqmin
iframe.style = 'width:400px;height:80px';
// Not affected by resize:
assert_equals(getComputedStyle(inner_target).left, '7px'); // 10cqw
assert_equals(getComputedStyle(inner_target).right, '7px'); // 10cqi
// Affected:
assert_equals(getComputedStyle(inner_target).top, '8px'); // 10cqh
assert_equals(getComputedStyle(inner_target).bottom, '8px'); // 10cqb
assert_equals(getComputedStyle(inner_target).marginLeft, '8px'); // 10cqmax
assert_equals(getComputedStyle(inner_target).marginRight, '7px'); // 10cqmin
}, 'Use small viewport size as fallback');
</script>

View file

@ -0,0 +1,95 @@
<!DOCTYPE html>
<title>CSS Container Queries Test: container-relative units in SVGLength</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<link rel="help" href="https://w3c.github.io/svgwg/svg2-draft/types.html#InterfaceSVGLength">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<script src="../../../resources/SVGAnimationTestCase-testharness.js"></script>
<style>
#container {
container-type: size;
width: 200px;
height: 150px;
}
</style>
<div id=container>
<svg id=rootSVGElement>
<rect id="rect1" width="10cqw" height="10cqh"/>
<rect id="rect2" width="10cqi" height="10cqb"/>
<rect id="rect3" width="10cqmin" height="10cqmax"/>
<rect id="rect4" width="calc(10cqmin + 10cqmax)" height="calc(10cqw + 3px)"/>
<rect id="rect_dynamic"/>
<rect id="rect_animated" width="42px" height="42px" fill="green">
<animate id=animation attributeName=width from="5cqw" to="10cqw" begin="0s" dur="4s"/>
</rect>
</svg>
</div>
<script>
setup(() => {
assert_implements_size_container_queries();
container.offsetTop;
});
function cleanup() {
rect_dynamic.removeAttribute('width');
rect_dynamic.removeAttribute('height');
}
test(() => {
assert_equals(rect1.width.baseVal.unitType, SVGLength.SVG_LENGTHTYPE_UNKNOWN);
}, 'unitType with container-relative units');
test(() => {
assert_equals(rect1.width.baseVal.value, 20);
assert_equals(rect1.height.baseVal.value, 15);
}, 'cqw,cqh can be resolved');
test(() => {
assert_equals(rect2.width.baseVal.value, 20);
assert_equals(rect2.height.baseVal.value, 15);
}, 'cqi,cqb can be resolved');
test(() => {
assert_equals(rect3.width.baseVal.value, 15);
assert_equals(rect3.height.baseVal.value, 20);
}, 'cqmin,cqmax can be resolved');
test(() => {
assert_equals(rect4.width.baseVal.value, 35);
assert_equals(rect4.height.baseVal.value, 23);
}, 'calc() with container-relative units can be resolved');
test((t) => {
t.add_cleanup(cleanup);
rect_dynamic.setAttribute('width', '20cqw');
rect_dynamic.setAttribute('height', '20cqh');
assert_equals(rect_dynamic.width.baseVal.value, 40);
assert_equals(rect_dynamic.height.baseVal.value, 30);
rect_dynamic.width.baseVal.value = 80;
rect_dynamic.height.baseVal.value = 45;
assert_equals(rect_dynamic.getAttribute('width'), '80');
assert_equals(rect_dynamic.getAttribute('height'), '45');
}, 'Can modify value with container-relative units');
smil_async_test((t) => {
t.add_cleanup(cleanup);
let assert_width = (expected) => {
let epsilon = 1.0;
return () => {
assert_approx_equals(rect_animated.width.animVal.value, expected, epsilon);
};
};
const expectedValues = [
// [animationId, time, sampleCallback]
["animation", 0.0, assert_width(10)],
["animation", 2.0, assert_width(15)],
["animation", 3.999, assert_width(20)],
["animation", 4, assert_width(42)],
];
runAnimationTest(t, expectedValues);
});
</script>

View file

@ -0,0 +1,59 @@
<!doctype html>
<title>Container Relative Units: CSS Typed OM</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#stylepropertymap">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<div id=element></div>
<script>
setup(() => assert_implements_size_container_queries());
const units = ['cqw', 'cqh', 'cqi', 'cqb', 'cqmin', 'cqmax'];
const functions = {
cqw: CSS.cqw,
cqh: CSS.cqh,
cqi: CSS.cqi,
cqb: CSS.cqb,
cqmin: CSS.cqmin,
cqmax: CSS.cqmax,
};
for (let unit of units) {
let func = functions[unit];
test(() => {
assert_equals(`${func(10)}`, `10${unit}`);
}, `CSS.${unit} function`);
test(() => {
try {
element.style.top = `10${unit}`;
let value = element.attributeStyleMap.get('top');
assert_equals(value.value, 10);
assert_equals(value.unit, unit);
} finally {
element.style = '';
}
}, `Reify value with ${unit} unit`);
test(() => {
try {
element.attributeStyleMap.set('top', `10${unit}`);
assert_equals(element.style.top, `10${unit}`);
} finally {
element.style = '';
}
}, `Set value with ${unit} unit (string)`);
test(() => {
try {
element.attributeStyleMap.set('top', func(10));
assert_equals(element.style.top, `10${unit}`);
} finally {
element.style = '';
}
}, `Set value with ${unit} unit (CSS.${unit})`);
}
</script>

View file

@ -0,0 +1,102 @@
// NOTE(edvardt):
// This file is a slimmed down wrapper for the old SVGAnimationTestCase.js,
// it has some convenience functions and should not be used for new tests.
// New tests should not build on this API as it's just meant to keep things
// working.
// Helper functions
const xlinkNS = "http://www.w3.org/1999/xlink"
function expectFillColor(element, red, green, blue, message) {
let color = window.getComputedStyle(element, null).fill;
var re = new RegExp("rgba?\\(([^, ]*), ([^, ]*), ([^, ]*)(?:, )?([^, ]*)\\)");
rgb = re.exec(color);
assert_approx_equals(Number(rgb[1]), red, 2.0, message);
assert_approx_equals(Number(rgb[2]), green, 2.0, message);
assert_approx_equals(Number(rgb[3]), blue, 2.0, message);
}
function expectColor(element, red, green, blue, property) {
if (typeof property != "string")
color = getComputedStyle(element).getPropertyValue("color");
else
color = getComputedStyle(element).getPropertyValue(property);
var re = new RegExp("rgba?\\(([^, ]*), ([^, ]*), ([^, ]*)(?:, )?([^, ]*)\\)");
rgb = re.exec(color);
assert_approx_equals(Number(rgb[1]), red, 2.0);
assert_approx_equals(Number(rgb[2]), green, 2.0);
assert_approx_equals(Number(rgb[3]), blue, 2.0);
}
function createSVGElement(type) {
return document.createElementNS("http://www.w3.org/2000/svg", type);
}
// Inspired by Layoutests/animations/animation-test-helpers.js
function moveAnimationTimelineAndSample(index) {
var animationId = expectedResults[index][0];
var time = expectedResults[index][1];
var sampleCallback = expectedResults[index][2];
var animation = rootSVGElement.ownerDocument.getElementById(animationId);
// If we want to sample the animation end, add a small delta, to reliable point past the end of the animation.
newTime = time;
// The sample time is relative to the start time of the animation, take that into account.
rootSVGElement.setCurrentTime(newTime);
// NOTE(edvardt):
// This is a dumb hack, some of the old tests sampled before the animation start, this
// isn't technically part of the animation tests and is "impossible" to translate since
// tests start automatically. Thus I solved it by skipping it.
if (time != 0.0)
sampleCallback();
}
var currentTest = 0;
var expectedResults;
function sampleAnimation(t) {
if (currentTest == expectedResults.length) {
t.done();
return;
}
moveAnimationTimelineAndSample(currentTest);
++currentTest;
step_timeout(t.step_func(function () { sampleAnimation(t); }), 0);
}
function runAnimationTest(t, expected) {
if (!expected)
throw("Expected results are missing!");
if (currentTest > 0)
throw("Not allowed to call runAnimationTest() twice");
expectedResults = expected;
testCount = expectedResults.length;
currentTest = 0;
step_timeout(t.step_func(function () { sampleAnimation(this); }), 50);
}
function smil_async_test(func) {
async_test(t => {
window.onload = t.step_func(function () {
// Pause animations, we'll drive them manually.
// This also ensures that the timeline is paused before
// it starts. This should make the instance time of the below
// 'click' (for instance) 0, and hence minimize rounding
// errors for the addition in moveAnimationTimelineAndSample.
rootSVGElement.pauseAnimations();
// If eg. an animation is running with begin="0s", and
// we want to sample the first time, before the animation
// starts, then we can't delay the testing by using an
// onclick event, as the animation would be past start time.
func(t);
});
});
}