summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-conditional/js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/css/css-conditional/js
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/css/css-conditional/js')
-rw-r--r--testing/web-platform/tests/css/css-conditional/js/001.html216
-rw-r--r--testing/web-platform/tests/css/css-conditional/js/CSS-supports-CSSStyleDeclaration.html761
-rw-r--r--testing/web-platform/tests/css/css-conditional/js/CSS-supports-L3.html80
-rw-r--r--testing/web-platform/tests/css/css-conditional/js/CSS-supports-L4.html79
-rw-r--r--testing/web-platform/tests/css/css-conditional/js/CSS-supports-L5.html43
-rw-r--r--testing/web-platform/tests/css/css-conditional/js/CSS-supports-selector-detecting-invalid-in-logical-combinations.html58
-rw-r--r--testing/web-platform/tests/css/css-conditional/js/conditional-CSSGroupingRule.html244
-rw-r--r--testing/web-platform/tests/css/css-conditional/js/supports-conditionText.html41
8 files changed, 1522 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-conditional/js/001.html b/testing/web-platform/tests/css/css-conditional/js/001.html
new file mode 100644
index 0000000000..bafb840d31
--- /dev/null
+++ b/testing/web-platform/tests/css/css-conditional/js/001.html
@@ -0,0 +1,216 @@
+<!doctype html>
+<title>CSS Test (Conditional Rules): @supports rules OM support</title>
+<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
+<link rel="author" href="http://opera.com" title="Opera Software ASA">
+<link rel="help" href="http://www.w3.org/TR/css3-conditional/#at-supports">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<style>
+ @supports (padding: 0) {
+ dfn { width:0; }
+ @supports (width: 0) {
+ br { height:0; }
+ }
+ ol { display:none; }
+ }
+ @media all {
+ @supports (padding: 0) {
+ @keyframes foo {
+ 0% { top: 0; left: 0; }
+ 100% { top: 100px; left: 100px; }
+ }
+ }
+ }
+ @supports (border: black) and (padding: 0) and (width: 0) {
+ dfn { width:0; }
+ }
+ @supports (border: black) or (padding: 0) or (width: 0) {
+ dfn { width:0; }
+ }
+</style>
+<script>
+ /**
+ * Asserts tha the two strings are equal, after normalizing whitespace
+ *
+ * If the serialization of whitespace and identation ever becomes
+ * specified to a sufficient degree of presition, this should be
+ * replaced by a strict textual comparison with assert_equals.
+ */
+ function assert_equals_normalized(a, b) {
+ var normal_a = a.replace(/\s+/g, " ");
+ var normal_b = b.replace(/\s+/g, " ");
+ assert_equals(normal_a, normal_b);
+ }
+ test(function(){
+ var base_rule = document.styleSheets[0].cssRules[0];
+ var child_rule = base_rule.cssRules[1];
+ assert_equals_normalized(base_rule.cssText,
+ "@supports (padding: 0) {\n"
+ +" dfn { width: 0px; }\n"
+ +" @supports (width: 0) {\n"
+ +" br { height: 0px; }\n"
+ +" }\n"
+ +" ol { display: none; }\n"
+ +"}");
+ assert_equals_normalized(child_rule.cssText,
+ "@supports (width: 0) {\n"
+ +" br { height: 0px; }\n"
+ +"}");
+ }, "nested @supports serialize properly");
+
+ test(function(){
+ var base_rule = document.styleSheets[0].cssRules[1];
+ var child_rule = base_rule.cssRules[0];
+ var grand_child_rule = child_rule.cssRules[0];
+ assert_equals_normalized(base_rule.cssText,
+ "@media all {\n"
+ +" @supports (padding: 0) {\n"
+ +" @keyframes foo {\n"
+ +" 0% { top: 0px; left: 0px; }\n"
+ +" 100% { top: 100px; left: 100px; }\n"
+ +" }\n"
+ +" }\n"
+ +"}");
+ assert_equals_normalized(child_rule.cssText,
+ "@supports (padding: 0) {\n"
+ +" @keyframes foo {\n"
+ +" 0% { top: 0px; left: 0px; }\n"
+ +" 100% { top: 100px; left: 100px; }\n"
+ +" }\n"
+ +"}");
+ assert_equals_normalized(grand_child_rule.cssText,
+ "@keyframes foo {\n"
+ +" 0% { top: 0px; left: 0px; }\n"
+ +" 100% { top: 100px; left: 100px; }\n"
+ +"}");
+ }, "@keyframes nested in @supports serialize properly");
+
+ test(function(){
+ var rules = document.styleSheets[0].cssRules;
+ assert_equals(rules.length, 4);
+ assert_equals(rules[0].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[1].type, CSSRule.MEDIA_RULE);
+ assert_equals(rules[0].cssRules.length, 3);
+ assert_equals(rules[0].cssRules[0].type, CSSRule.STYLE_RULE);
+ assert_equals(rules[0].cssRules[1].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[0].cssRules[2].type, CSSRule.STYLE_RULE);
+
+ assert_equals(rules[0].cssRules[1].cssRules.length, 1);
+ assert_equals(rules[0].cssRules[1].cssRules[0].type, CSSRule.STYLE_RULE);
+
+ assert_equals(rules[1].cssRules.length, 1);
+ assert_equals(rules[1].cssRules[0].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[1].cssRules[0].cssRules.length, 1);
+ assert_equals(rules[1].cssRules[0].cssRules[0].type, CSSRule.KEYFRAMES_RULE);
+
+ assert_equals(rules[2].cssRules.length, 1);
+ assert_equals(rules[2].cssRules[0].type, CSSRule.STYLE_RULE);
+
+ assert_equals(rules[3].cssRules.length, 1);
+ assert_equals(rules[3].cssRules[0].type, CSSRule.STYLE_RULE);
+ }, "The style sheet structure is properly represented");
+
+ test(function(){
+ document.styleSheets[0].deleteRule(1);
+
+ var rules = document.styleSheets[0].cssRules;
+ assert_equals(rules.length, 3);
+ assert_equals(rules[0].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[0].cssRules.length, 3);
+ assert_equals(rules[0].cssRules[0].type, CSSRule.STYLE_RULE);
+ assert_equals(rules[0].cssRules[1].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[0].cssRules[2].type, CSSRule.STYLE_RULE);
+
+ assert_equals(rules[0].cssRules[1].cssRules.length, 1);
+ assert_equals(rules[0].cssRules[1].cssRules[0].type, CSSRule.STYLE_RULE);
+ }, "Deleting the top level of a nested structue works");
+
+ test(function(){
+ var rules = document.styleSheets[0].cssRules;
+
+ rules[0].cssRules[1].insertRule("img { visibility:hidden; }", 0);
+
+ assert_equals(rules.length, 3);
+ assert_equals(rules[0].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[0].cssRules.length, 3);
+ assert_equals(rules[0].cssRules[0].type, CSSRule.STYLE_RULE);
+ assert_equals(rules[0].cssRules[1].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[0].cssRules[2].type, CSSRule.STYLE_RULE);
+
+ assert_equals(rules[0].cssRules[1].cssRules.length, 2);
+ assert_equals(rules[0].cssRules[1].cssRules[0].type, CSSRule.STYLE_RULE);
+ assert_equals(rules[0].cssRules[1].cssRules[0].cssText, "img { visibility: hidden; }");
+ assert_equals(rules[0].cssRules[1].cssRules[1].type, CSSRule.STYLE_RULE);
+ assert_equals(rules[0].cssRules[1].cssRules[1].cssText, "br { height: 0px; }");
+ }, "Rule insertion works in nested @supports rules");
+
+ test(function(){
+ var rules = document.styleSheets[0].cssRules;
+
+ rules[0].insertRule("@supports (left: 42px) { #foo { color:green; } }", 1);
+
+ assert_equals(rules.length, 3);
+ assert_equals(rules[0].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[0].cssRules.length, 4);
+ assert_equals(rules[0].cssRules[0].type, CSSRule.STYLE_RULE);
+ assert_equals(rules[0].cssRules[1].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[0].cssRules[2].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[0].cssRules[3].type, CSSRule.STYLE_RULE);
+
+ assert_equals(rules[0].cssRules[1].cssRules.length, 1);
+ assert_equals(rules[0].cssRules[1].cssRules[0].type, CSSRule.STYLE_RULE);
+ assert_equals(rules[0].cssRules[1].cssRules[0].cssText, "#foo { color: green; }");
+
+ assert_equals(rules[0].cssRules[2].cssRules.length, 2);
+ assert_equals(rules[0].cssRules[2].cssRules[0].type, CSSRule.STYLE_RULE);
+ assert_equals(rules[0].cssRules[2].cssRules[0].cssText, "img { visibility: hidden; }");
+ assert_equals(rules[0].cssRules[2].cssRules[1].type, CSSRule.STYLE_RULE);
+ assert_equals(rules[0].cssRules[2].cssRules[1].cssText, "br { height: 0px; }");
+ }, "Insertion @supports rules into another @supports rule works");
+
+ test(function(){
+ var rules = document.styleSheets[0].cssRules;
+
+ rules[0].deleteRule(2);
+
+ assert_equals(rules.length, 3);
+ assert_equals(rules[0].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[0].cssRules.length, 3);
+ assert_equals(rules[0].cssRules[0].type, CSSRule.STYLE_RULE);
+ assert_equals(rules[0].cssRules[1].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[0].cssRules[2].type, CSSRule.STYLE_RULE);
+
+ assert_equals(rules[0].cssRules[1].cssRules.length, 1);
+ assert_equals(rules[0].cssRules[1].cssRules[0].type, CSSRule.STYLE_RULE);
+ assert_equals(rules[0].cssRules[1].cssRules[0].cssText, "#foo { color: green; }");
+ }, "Deletion of a nested @supports rule works");
+
+ test(function(){
+ var rules = document.styleSheets[0].cssRules;
+
+ rules[0].insertRule("@font-face { font-familly: foo; src: url('http://www.example.com/foo'; }", 0);
+
+ assert_equals(rules.length, 3);
+ assert_equals(rules[0].type, CSSRule.SUPPORTS_RULE);
+ assert_equals(rules[0].cssRules.length, 4);
+ assert_equals(rules[0].cssRules[0].type, CSSRule.FONT_FACE_RULE);
+ }, "Inserting @font-face inside @supports works");
+
+ test(function(){
+ var rule = document.styleSheets[0].cssRules[1];
+ assert_equals_normalized(rule.cssText,
+ "@supports (border: black) and (padding: 0) and (width: 0) {\n"
+ +" dfn { width: 0px; }\n"
+ +"}");
+ }, "'and' arguments in @supports serialize in the correct order and with extra parentheses");
+ test(function(){
+ var rule = document.styleSheets[0].cssRules[2];
+ assert_equals_normalized(rule.cssText,
+ "@supports (border: black) or (padding: 0) or (width: 0) {\n"
+ +" dfn { width: 0px; }\n"
+ +"}");
+ }, "'or' arguments in @supports serialize in the correct order and with extra parentheses");
+</script>
+
+<div id=log></div>
+
diff --git a/testing/web-platform/tests/css/css-conditional/js/CSS-supports-CSSStyleDeclaration.html b/testing/web-platform/tests/css/css-conditional/js/CSS-supports-CSSStyleDeclaration.html
new file mode 100644
index 0000000000..a27e385faf
--- /dev/null
+++ b/testing/web-platform/tests/css/css-conditional/js/CSS-supports-CSSStyleDeclaration.html
@@ -0,0 +1,761 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS.supports v. CSSStyleDeclaration</title>
+<link rel="help" href="https://drafts.csswg.org/css-conditional/#dom-css-supports">
+<link rel="help" href="https://drafts.csswg.org/cssom/#the-cssstyledeclaration-interface">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="testElement"></div>
+<script>
+// This gigantic list of properties is derived from the union of pretty much everything ever
+// exposed via CSSStyleDeclaration since 2010 in a major browser; this deliberately includes all
+// the vendor-prefixed properties _because_ they're often where bugs lie
+
+const properties = [
+ "-apple-color-filter",
+ "-apple-pay-button-style",
+ "-apple-pay-button-type",
+ "-apple-trailing-word",
+ "-epub-caption-side",
+ "-epub-text-combine",
+ "-epub-text-emphasis",
+ "-epub-text-emphasis-color",
+ "-epub-text-emphasis-style",
+ "-epub-text-orientation",
+ "-epub-text-transform",
+ "-epub-word-break",
+ "-epub-writing-mode",
+ "-moz-animation",
+ "-moz-animation-delay",
+ "-moz-animation-direction",
+ "-moz-animation-duration",
+ "-moz-animation-fill-mode",
+ "-moz-animation-iteration-count",
+ "-moz-animation-name",
+ "-moz-animation-play-state",
+ "-moz-animation-timing-function",
+ "-moz-appearance",
+ "-moz-backface-visibility",
+ "-moz-binding",
+ "-moz-border-bottom-colors",
+ "-moz-border-end",
+ "-moz-border-end-color",
+ "-moz-border-end-style",
+ "-moz-border-end-width",
+ "-moz-border-image",
+ "-moz-border-left-colors",
+ "-moz-border-right-colors",
+ "-moz-border-start",
+ "-moz-border-start-color",
+ "-moz-border-start-style",
+ "-moz-border-start-width",
+ "-moz-border-top-colors",
+ "-moz-box-align",
+ "-moz-box-direction",
+ "-moz-box-flex",
+ "-moz-box-ordinal-group",
+ "-moz-box-orient",
+ "-moz-box-pack",
+ "-moz-box-sizing",
+ "-moz-column-count",
+ "-moz-column-fill",
+ "-moz-column-gap",
+ "-moz-column-rule",
+ "-moz-column-rule-color",
+ "-moz-column-rule-style",
+ "-moz-column-rule-width",
+ "-moz-column-span",
+ "-moz-column-width",
+ "-moz-columns",
+ "-moz-float-edge",
+ "-moz-font-feature-settings",
+ "-moz-font-language-override",
+ "-moz-force-broken-image-icon",
+ "-moz-hyphens",
+ "-moz-image-region",
+ "-moz-margin-end",
+ "-moz-margin-start",
+ "-moz-orient",
+ "-moz-osx-font-smoothing",
+ "-moz-padding-end",
+ "-moz-padding-start",
+ "-moz-perspective",
+ "-moz-perspective-origin",
+ "-moz-stack-sizing",
+ "-moz-tab-size",
+ "-moz-text-align-last",
+ "-moz-text-size-adjust",
+ "-moz-transform",
+ "-moz-transform-origin",
+ "-moz-transform-style",
+ "-moz-transition",
+ "-moz-transition-delay",
+ "-moz-transition-duration",
+ "-moz-transition-property",
+ "-moz-transition-timing-function",
+ "-moz-user-focus",
+ "-moz-user-input",
+ "-moz-user-modify",
+ "-moz-user-select",
+ "-moz-window-dragging",
+ "-ms-content-zoom-chaining",
+ "-ms-content-zoom-limit",
+ "-ms-content-zoom-limit-max",
+ "-ms-content-zoom-limit-min",
+ "-ms-content-zoom-snap",
+ "-ms-content-zoom-snap-points",
+ "-ms-content-zoom-snap-type",
+ "-ms-content-zooming",
+ "-ms-flow-from",
+ "-ms-flow-into",
+ "-ms-font-feature-settings",
+ "-ms-grid-column",
+ "-ms-grid-column-align",
+ "-ms-grid-column-span",
+ "-ms-grid-columns",
+ "-ms-grid-row",
+ "-ms-grid-row-align",
+ "-ms-grid-row-span",
+ "-ms-grid-rows",
+ "-ms-high-contrast-adjust",
+ "-ms-hyphenate-limit-chars",
+ "-ms-hyphenate-limit-lines",
+ "-ms-hyphenate-limit-zone",
+ "-ms-hyphens",
+ "-ms-ime-align",
+ "-ms-overflow-style",
+ "-ms-scroll-chaining",
+ "-ms-scroll-limit",
+ "-ms-scroll-limit-x-max",
+ "-ms-scroll-limit-x-min",
+ "-ms-scroll-limit-y-max",
+ "-ms-scroll-limit-y-min",
+ "-ms-scroll-rails",
+ "-ms-scroll-snap-points-x",
+ "-ms-scroll-snap-points-y",
+ "-ms-scroll-snap-type",
+ "-ms-scroll-snap-x",
+ "-ms-scroll-snap-y",
+ "-ms-scroll-translation",
+ "-ms-text-combine-horizontal",
+ "-ms-text-size-adjust",
+ "-ms-touch-select",
+ "-ms-user-select",
+ "-ms-wrap-flow",
+ "-ms-wrap-margin",
+ "-ms-wrap-through",
+ "-webkit-align-content",
+ "-webkit-align-items",
+ "-webkit-align-self",
+ "-webkit-animation",
+ "-webkit-animation-delay",
+ "-webkit-animation-direction",
+ "-webkit-animation-duration",
+ "-webkit-animation-fill-mode",
+ "-webkit-animation-iteration-count",
+ "-webkit-animation-name",
+ "-webkit-animation-play-state",
+ "-webkit-animation-timing-function",
+ "-webkit-appearance",
+ "-webkit-backface-visibility",
+ "-webkit-background-clip",
+ "-webkit-background-origin",
+ "-webkit-background-size",
+ "-webkit-border-bottom-left-radius",
+ "-webkit-border-bottom-right-radius",
+ "-webkit-border-image",
+ "-webkit-border-radius",
+ "-webkit-border-top-left-radius",
+ "-webkit-border-top-right-radius",
+ "-webkit-box-align",
+ "-webkit-box-direction",
+ "-webkit-box-flex",
+ "-webkit-box-ordinal-group",
+ "-webkit-box-orient",
+ "-webkit-box-pack",
+ "-webkit-box-shadow",
+ "-webkit-box-sizing",
+ "-webkit-filter",
+ "-webkit-flex",
+ "-webkit-flex-basis",
+ "-webkit-flex-direction",
+ "-webkit-flex-flow",
+ "-webkit-flex-grow",
+ "-webkit-flex-shrink",
+ "-webkit-flex-wrap",
+ "-webkit-justify-content",
+ "-webkit-line-clamp",
+ "-webkit-mask",
+ "-webkit-mask-clip",
+ "-webkit-mask-composite",
+ "-webkit-mask-image",
+ "-webkit-mask-origin",
+ "-webkit-mask-position",
+ "-webkit-mask-position-x",
+ "-webkit-mask-position-y",
+ "-webkit-mask-repeat",
+ "-webkit-mask-size",
+ "-webkit-order",
+ "-webkit-perspective",
+ "-webkit-perspective-origin",
+ "-webkit-text-fill-color",
+ "-webkit-text-size-adjust",
+ "-webkit-text-stroke",
+ "-webkit-text-stroke-color",
+ "-webkit-text-stroke-width",
+ "-webkit-transform",
+ "-webkit-transform-origin",
+ "-webkit-transform-style",
+ "-webkit-transition",
+ "-webkit-transition-delay",
+ "-webkit-transition-duration",
+ "-webkit-transition-property",
+ "-webkit-transition-timing-function",
+ "-webkit-user-select",
+ "align-content",
+ "align-items",
+ "align-self",
+ "alignment-baseline",
+ "all",
+ "alt",
+ "animation",
+ "animation-delay",
+ "animation-direction",
+ "animation-duration",
+ "animation-fill-mode",
+ "animation-iteration-count",
+ "animation-name",
+ "animation-play-state",
+ "animation-timing-function",
+ "appearance",
+ "backdrop-filter",
+ "backface-visibility",
+ "background",
+ "background-attachment",
+ "background-blend-mode",
+ "background-clip",
+ "background-color",
+ "background-image",
+ "background-origin",
+ "background-position",
+ "background-position-x",
+ "background-position-y",
+ "background-repeat",
+ "background-repeat-x",
+ "background-repeat-y",
+ "background-size",
+ "baseline-shift",
+ "block-size",
+ "border",
+ "border-block",
+ "border-block-color",
+ "border-block-end",
+ "border-block-end-color",
+ "border-block-end-style",
+ "border-block-end-width",
+ "border-block-start",
+ "border-block-start-color",
+ "border-block-start-style",
+ "border-block-start-width",
+ "border-block-style",
+ "border-block-width",
+ "border-bottom",
+ "border-bottom-color",
+ "border-bottom-left-radius",
+ "border-bottom-right-radius",
+ "border-bottom-style",
+ "border-bottom-width",
+ "border-collapse",
+ "border-color",
+ "border-end-end-radius",
+ "border-end-start-radius",
+ "border-image",
+ "border-image-outset",
+ "border-image-repeat",
+ "border-image-slice",
+ "border-image-source",
+ "border-image-width",
+ "border-inline",
+ "border-inline-color",
+ "border-inline-end",
+ "border-inline-end-color",
+ "border-inline-end-style",
+ "border-inline-end-width",
+ "border-inline-start",
+ "border-inline-start-color",
+ "border-inline-start-style",
+ "border-inline-start-width",
+ "border-inline-style",
+ "border-inline-width",
+ "border-left",
+ "border-left-color",
+ "border-left-style",
+ "border-left-width",
+ "border-radius",
+ "border-right",
+ "border-right-color",
+ "border-right-style",
+ "border-right-width",
+ "border-spacing",
+ "border-start-end-radius",
+ "border-start-start-radius",
+ "border-style",
+ "border-top",
+ "border-top-color",
+ "border-top-left-radius",
+ "border-top-right-radius",
+ "border-top-style",
+ "border-top-width",
+ "border-width",
+ "bottom",
+ "box-decoration-break",
+ "box-shadow",
+ "box-sizing",
+ "break-after",
+ "break-before",
+ "break-inside",
+ "buffered-rendering",
+ "caption-side",
+ "caret-color",
+ "clear",
+ "clip",
+ "clip-path",
+ "clip-rule",
+ "color",
+ "color-adjust",
+ "color-interpolation",
+ "color-interpolation-filters",
+ "color-profile",
+ "color-rendering",
+ "color-scheme",
+ "column-count",
+ "column-fill",
+ "column-gap",
+ "column-progression",
+ "column-rule",
+ "column-rule-color",
+ "column-rule-style",
+ "column-rule-width",
+ "column-span",
+ "column-width",
+ "columns",
+ "contain",
+ "contain-intrinsic-size",
+ "content",
+ "content-visibility",
+ "counter-increment",
+ "counter-reset",
+ "counter-set",
+ "cursor",
+ "cx",
+ "cy",
+ "d",
+ "direction",
+ "display",
+ "dominant-baseline",
+ "empty-cells",
+ "enable-background",
+ "fill",
+ "fill-opacity",
+ "fill-rule",
+ "filter",
+ "flex",
+ "flex-basis",
+ "flex-direction",
+ "flex-flow",
+ "flex-grow",
+ "flex-shrink",
+ "flex-wrap",
+ "float",
+ "flood-color",
+ "flood-opacity",
+ "font",
+ "font-display",
+ "font-family",
+ "font-feature-settings",
+ "font-kerning",
+ "font-language-override",
+ "font-optical-sizing",
+ "font-size",
+ "font-size-adjust",
+ "font-stretch",
+ "font-style",
+ "font-synthesis",
+ "font-variant",
+ "font-variant-alternates",
+ "font-variant-caps",
+ "font-variant-east-asian",
+ "font-variant-ligatures",
+ "font-variant-numeric",
+ "font-variant-position",
+ "font-variation-settings",
+ "font-weight",
+ "gap",
+ "glyph-orientation-horizontal",
+ "glyph-orientation-vertical",
+ "grid",
+ "grid-area",
+ "grid-auto-columns",
+ "grid-auto-flow",
+ "grid-auto-rows",
+ "grid-column",
+ "grid-column-end",
+ "grid-column-gap",
+ "grid-column-start",
+ "grid-gap",
+ "grid-row",
+ "grid-row-end",
+ "grid-row-gap",
+ "grid-row-start",
+ "grid-template",
+ "grid-template-areas",
+ "grid-template-columns",
+ "grid-template-rows",
+ "hanging-punctuation",
+ "height",
+ "hyphens",
+ "image-orientation",
+ "image-rendering",
+ "ime-mode",
+ "inherits",
+ "initial-value",
+ "inline-size",
+ "inset",
+ "inset-block",
+ "inset-block-end",
+ "inset-block-start",
+ "inset-inline",
+ "inset-inline-end",
+ "inset-inline-start",
+ "internal-text-autosizing-status",
+ "isolation",
+ "justify-content",
+ "justify-items",
+ "justify-self",
+ "kerning",
+ "layout-grid",
+ "layout-grid-char",
+ "layout-grid-line",
+ "layout-grid-mode",
+ "layout-grid-type",
+ "left",
+ "letter-spacing",
+ "lighting-color",
+ "line-break",
+ "line-height",
+ "list-style",
+ "list-style-image",
+ "list-style-position",
+ "list-style-type",
+ "margin",
+ "margin-block",
+ "margin-block-end",
+ "margin-block-start",
+ "margin-bottom",
+ "margin-inline",
+ "margin-inline-end",
+ "margin-inline-start",
+ "margin-left",
+ "margin-right",
+ "margin-top",
+ "marker",
+ "marker-end",
+ "marker-mid",
+ "marker-offset",
+ "marker-start",
+ "mask",
+ "mask-clip",
+ "mask-composite",
+ "mask-image",
+ "mask-mode",
+ "mask-origin",
+ "mask-position",
+ "mask-position-x",
+ "mask-position-y",
+ "mask-repeat",
+ "mask-size",
+ "mask-type",
+ "max-block-size",
+ "max-height",
+ "max-inline-size",
+ "max-width",
+ "max-zoom",
+ "min-block-size",
+ "min-height",
+ "min-inline-size",
+ "min-width",
+ "min-zoom",
+ "mix-blend-mode",
+ "motion",
+ "motion-offset",
+ "motion-path",
+ "motion-rotation",
+ "object-fit",
+ "object-position",
+ "offset",
+ "offset-anchor",
+ "offset-block-end",
+ "offset-block-start",
+ "offset-distance",
+ "offset-inline-end",
+ "offset-inline-start",
+ "offset-path",
+ "offset-rotate",
+ "offset-rotation",
+ "opacity",
+ "order",
+ "orientation",
+ "orphans",
+ "outline",
+ "outline-color",
+ "outline-offset",
+ "outline-style",
+ "outline-width",
+ "overflow",
+ "overflow-anchor",
+ "overflow-block",
+ "overflow-inline",
+ "overflow-wrap",
+ "overflow-x",
+ "overflow-y",
+ "overscroll-behavior",
+ "overscroll-behavior-block",
+ "overscroll-behavior-inline",
+ "overscroll-behavior-x",
+ "overscroll-behavior-y",
+ "padding",
+ "padding-block",
+ "padding-block-end",
+ "padding-block-start",
+ "padding-bottom",
+ "padding-inline",
+ "padding-inline-end",
+ "padding-inline-start",
+ "padding-left",
+ "padding-right",
+ "padding-top",
+ "page",
+ "page-break-after",
+ "page-break-before",
+ "page-break-inside",
+ "page-orientation",
+ "paint-order",
+ "pen-action",
+ "perspective",
+ "perspective-origin",
+ "perspective-origin-x",
+ "perspective-origin-y",
+ "place-content",
+ "place-items",
+ "place-self",
+ "pointer-events",
+ "position",
+ "quotes",
+ "r",
+ "resize",
+ "right",
+ "rotate",
+ "row-gap",
+ "ruby-align",
+ "ruby-overhang",
+ "ruby-position",
+ "rx",
+ "ry",
+ "scale",
+ "scroll-behavior",
+ "scroll-margin",
+ "scroll-margin-block",
+ "scroll-margin-block-end",
+ "scroll-margin-block-start",
+ "scroll-margin-bottom",
+ "scroll-margin-inline",
+ "scroll-margin-inline-end",
+ "scroll-margin-inline-start",
+ "scroll-margin-left",
+ "scroll-margin-right",
+ "scroll-margin-top",
+ "scroll-padding",
+ "scroll-padding-block",
+ "scroll-padding-block-end",
+ "scroll-padding-block-start",
+ "scroll-padding-bottom",
+ "scroll-padding-inline",
+ "scroll-padding-inline-end",
+ "scroll-padding-inline-start",
+ "scroll-padding-left",
+ "scroll-padding-right",
+ "scroll-padding-top",
+ "scroll-snap-align",
+ "scroll-snap-coordinate",
+ "scroll-snap-destination",
+ "scroll-snap-margin",
+ "scroll-snap-margin-bottom",
+ "scroll-snap-margin-left",
+ "scroll-snap-margin-right",
+ "scroll-snap-margin-top",
+ "scroll-snap-points-x",
+ "scroll-snap-points-y",
+ "scroll-snap-stop",
+ "scroll-snap-type",
+ "scroll-snap-type-x",
+ "scroll-snap-type-y",
+ "scrollbar-color",
+ "scrollbar-width",
+ "shape-image-threshold",
+ "shape-margin",
+ "shape-outside",
+ "shape-rendering",
+ "size",
+ "speak",
+ "speak-as",
+ "src",
+ "stop-color",
+ "stop-opacity",
+ "stroke",
+ "stroke-color",
+ "stroke-dasharray",
+ "stroke-dashoffset",
+ "stroke-linecap",
+ "stroke-linejoin",
+ "stroke-miterlimit",
+ "stroke-opacity",
+ "stroke-width",
+ "supported-color-schemes",
+ "syntax",
+ "tab-size",
+ "table-layout",
+ "text-align",
+ "text-align-last",
+ "text-anchor",
+ "text-combine-upright",
+ "text-decoration",
+ "text-decoration-color",
+ "text-decoration-line",
+ "text-decoration-skip",
+ "text-decoration-skip-ink",
+ "text-decoration-style",
+ "text-decoration-thickness",
+ "text-emphasis",
+ "text-emphasis-color",
+ "text-emphasis-position",
+ "text-emphasis-style",
+ "text-indent",
+ "text-justify",
+ "text-kashida",
+ "text-kashida-space",
+ "text-line-through",
+ "text-line-through-color",
+ "text-line-through-mode",
+ "text-line-through-style",
+ "text-line-through-width",
+ "text-orientation",
+ "text-overflow",
+ "text-overline",
+ "text-overline-color",
+ "text-overline-mode",
+ "text-overline-style",
+ "text-overline-width",
+ "text-rendering",
+ "text-shadow",
+ "text-size-adjust",
+ "text-transform",
+ "text-underline",
+ "text-underline-color",
+ "text-underline-mode",
+ "text-underline-offset",
+ "text-underline-position",
+ "text-underline-style",
+ "text-underline-width",
+ "top",
+ "touch-action",
+ "transform",
+ "transform-box",
+ "transform-origin",
+ "transform-origin-x",
+ "transform-origin-y",
+ "transform-origin-z",
+ "transform-style",
+ "transition",
+ "transition-delay",
+ "transition-duration",
+ "transition-property",
+ "transition-timing-function",
+ "translate",
+ "unicode-bidi",
+ "unicode-range",
+ "user-select",
+ "user-zoom",
+ "vector-effect",
+ "vertical-align",
+ "viewport-fit",
+ "visibility",
+ "white-space",
+ "widows",
+ "width",
+ "will-change",
+ "word-break",
+ "word-spacing",
+ "word-wrap",
+ "writing-mode",
+ "x",
+ "y",
+ "z-index",
+ "zoom"
+];
+
+function CSSPropertyToIDLAttribute(property, lowercaseFirstFlag=false) {
+ let output = "";
+ let uppercaseNext = false;
+ if (lowercaseFirstFlag) {
+ property = property.substring(1);
+ }
+ for (let c of property) {
+ if (c === "-") {
+ uppercaseNext = true;
+ } else if (uppercaseNext) {
+ uppercaseNext = false;
+ if (c >= "a" && c <= "z") {
+ output += c.toUpperCase();
+ } else {
+ output += c;
+ }
+ } else {
+ output += c;
+ }
+ }
+ return output;
+}
+
+const styledecl = document.getElementById("testElement").style;
+
+for (let prop of properties) {
+ test(() => {
+ const camelCase = CSSPropertyToIDLAttribute(prop);
+ const supports = CSS.supports(prop, "inherit"); // inherit is always a valid value
+ assert_equals(supports, camelCase in styledecl);
+ }, `${prop}: _camel_cased_attribute v. CSS.supports`);
+
+ if (prop[0] == "-") {
+ if (prop.startsWith("-webkit-")) {
+ test(() => {
+ const webkitCased = CSSPropertyToIDLAttribute(prop, true);
+ const supports = CSS.supports(prop, "inherit"); // inherit is always a valid value
+ assert_equals(supports, webkitCased in styledecl);
+ }, `${prop}: _webkit_cased_attribute v. CSS.supports`);
+ } else {
+ test(() => {
+ const webkitCased = CSSPropertyToIDLAttribute(prop, true);
+ assert_false(webkitCased in styledecl);
+ }, `${prop}: _webkit_cased_attribute must only exist for -webkit-`);
+ }
+ }
+
+ if (prop.indexOf("-") >= 0) {
+ test(() => {
+ const supports = CSS.supports(prop, "inherit"); // inherit is always a valid value
+ assert_equals(supports, prop in styledecl);
+ }, `${prop}: _dashed_attribute v. CSS.supports`);
+ }
+}
+
+</script>
diff --git a/testing/web-platform/tests/css/css-conditional/js/CSS-supports-L3.html b/testing/web-platform/tests/css/css-conditional/js/CSS-supports-L3.html
new file mode 100644
index 0000000000..f94933422a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-conditional/js/CSS-supports-L3.html
@@ -0,0 +1,80 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS.supports() Level 3</title>
+<link rel="help" href="https://www.w3.org/TR/css-conditional-3/#the-css-namespace">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ test(function() {
+ assert_equals(CSS.supports("(color: red)"), true);
+ }, "Single-argument form allows for declarations with enclosing parentheses");
+
+ test(function() {
+ assert_equals(CSS.supports("color: red"), true);
+ }, "Single-argument form allows for declarations without enclosing parentheses");
+
+ test(function() {
+ assert_equals(CSS.supports("(color: red) and (color: blue)"), true);
+ }, "Complex conditions allowed");
+
+ test(function() {
+ assert_equals(CSS.supports("not (foobar)"), true);
+ }, "general_enclosed still parses");
+
+ test(function() {
+ assert_equals(CSS.supports("color: something-pointless var(--foo)"), true);
+ }, "Variable references always parse");
+
+ test(function() {
+ assert_equals(CSS.supports("color: something-pointless(var(--foo))"), true);
+ }, "Variable references in an unknown function always parse");
+
+ test(function() {
+ // no one-arg test for this as the with/without enclosing parentheses tests do this
+ assert_equals(CSS.supports("color", "red"), true);
+ }, "two argument form succeeds for known property");
+
+ test(function() {
+ assert_equals(CSS.supports("unknownproperty: blah"), false);
+ }, "one argument form fails for unknown property");
+
+ test(function() {
+ assert_equals(CSS.supports("unknownproperty", "blah"), false);
+ }, "two argument form fails for unknown property");
+
+ test(function() {
+ // https://github.com/w3c/csswg-drafts/issues/5929
+ assert_equals(CSS.supports("unicode-range: U+0-7F"), false);
+ }, "one argument form fails for unknown property (but known descriptor)");
+
+ test(function() {
+ // https://github.com/w3c/csswg-drafts/issues/5929
+ assert_equals(CSS.supports("unicode-range", "U+0-7F"), false);
+ }, "two argument form fails for unknown property (but known descriptor)");
+
+ test(function() {
+ // https://github.com/w3c/csswg-drafts/issues/5929
+ assert_equals(CSS.supports("unicode-range: inherit"), false);
+ }, "one argument form fails for unknown property (but known descriptor, universal value)");
+
+ test(function() {
+ // https://github.com/w3c/csswg-drafts/issues/5929
+ assert_equals(CSS.supports("unicode-range", "inherit"), false);
+ }, "two argument form fails for unknown property (but known descriptor, universal value)");
+
+ test(function() {
+ assert_equals(CSS.supports("width: blah"), false);
+ }, "one argument form fails for invalid value");
+
+ test(function() {
+ assert_equals(CSS.supports("width", "blah"), false);
+ }, "two argument form fails for invalid value");
+
+ test(function() {
+ assert_equals(CSS.supports("--foo: blah"), true);
+ }, "one argument form succeeds for custom property");
+
+ test(function() {
+ assert_equals(CSS.supports("--foo", "blah"), true);
+ }, "two argument form succeeds for custom property");
+</script>
diff --git a/testing/web-platform/tests/css/css-conditional/js/CSS-supports-L4.html b/testing/web-platform/tests/css/css-conditional/js/CSS-supports-L4.html
new file mode 100644
index 0000000000..2250e2be74
--- /dev/null
+++ b/testing/web-platform/tests/css/css-conditional/js/CSS-supports-L4.html
@@ -0,0 +1,79 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS.supports() Level 4</title>
+<link rel="help" href="https://www.w3.org/TR/css-conditional-4/#the-css-namespace">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ test(function() {
+ assert_equals(CSS.supports("selector(div)"), true);
+ }, "selector() function accepts a selector");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(div, div)"), false);
+ }, "selector() function doesn't accept a selector list");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(::-webkit-unknown-pseudo-element)"), false);
+ }, "selector() function rejects unknown webkit pseudo-elements.");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(::before)"), true);
+ }, "selector() function accepts known pseudo-elements");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(div + .c)"), true);
+ }, "selector() with simple combinators");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(div | .c)"), false);
+ }, "selector() with unknown combinators");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:is(:foo))"), false);
+ }, "selector() with forgiving :is, 1 arg");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:is(:foo, div))"), false);
+ }, "selector() with forgiving :is, multiple args");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:where(:foo))"), false);
+ }, "selector() with forgiving :where, 1 arg");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:where(:foo, div))"), false);
+ }, "selector() with forgiving :where, multiple args");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:has(:foo))"), false);
+ }, "selector() with forgiving :has, 1 arg");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:has(:foo, div))"), false);
+ }, "selector() with forgiving :has, multiple args");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:nth-child(2n + 3 of :foo))"), false);
+ }, "selector() with unforgiving :nth-child, 1 arg");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:nth-last-child(2n + 3 of :foo))"), false);
+ }, "selector() with unforgiving :nth-last-child, 1 arg");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:nth-child(2n + 3 of :foo, div))"), false);
+ }, "selector() with unforgiving :nth-child, multiple args");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:nth-last-child(2n + 3 of :foo, div))"), false);
+ }, "selector() with unforgiving :nth-last-child, multiple args");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:nth-child(2n 4))"), false);
+ }, "selector() with a non-identifier after :nth-child's An+B index");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:nth-last-child(2n 4))"), false);
+ }, "selector() with a non-identifier after :nth-last-child's An+B index");
+</script>
diff --git a/testing/web-platform/tests/css/css-conditional/js/CSS-supports-L5.html b/testing/web-platform/tests/css/css-conditional/js/CSS-supports-L5.html
new file mode 100644
index 0000000000..b87d6e8fdf
--- /dev/null
+++ b/testing/web-platform/tests/css/css-conditional/js/CSS-supports-L5.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS.supports() Level 5</title>
+<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#at-supports-ext">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ test(function() {
+ assert_equals(CSS.supports("font-format(opentype)"), true);
+ }, "font-format() function accepts a known format");
+
+ test(function() {
+ assert_equals(CSS.supports("font-format(xyzzy)"), false);
+ }, "font-format() function doesn't accept an unknown format");
+
+ test(function() {
+ assert_equals(CSS.supports("font-format(opentype, truetype)"), false);
+ }, "font-format() function doesn't accept a format list");
+
+ test(function() {
+ assert_equals(CSS.supports("font-format('opentype')"), false);
+ }, "font-format() function doesn't accept a string.");
+
+ test(function() {
+ assert_equals(CSS.supports("font-tech(features-opentype)"), true);
+ }, "font-tech() function accepts a known technology");
+
+ test(function() {
+ assert_equals(CSS.supports("font-tech(feature-opentype)"), false);
+ }, "font-tech() function doesn't accept singular feature-* form for technology");
+
+ test(function() {
+ assert_equals(CSS.supports("font-tech(foobar)"), false);
+ }, "font-tech() function doesn't accept an unknown technology");
+
+ test(function() {
+ assert_equals(CSS.supports("font-tech(features-opentype, color-COLRv0)"), false);
+ }, "font-tech() function doesn't accept a technology list");
+
+ test(function() {
+ assert_equals(CSS.supports("font-tech('features-opentype')"), false);
+ }, "font-tech() function doesn't accept a string.");
+</script>
diff --git a/testing/web-platform/tests/css/css-conditional/js/CSS-supports-selector-detecting-invalid-in-logical-combinations.html b/testing/web-platform/tests/css/css-conditional/js/CSS-supports-selector-detecting-invalid-in-logical-combinations.html
new file mode 100644
index 0000000000..3adcd7ae2e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-conditional/js/CSS-supports-selector-detecting-invalid-in-logical-combinations.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS.supports() detecting invalid in logical combinations</title>
+<link rel="help" href="https://www.w3.org/TR/css-conditional-4/#the-css-namespace">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ test(function() {
+ assert_equals(CSS.supports("selector(:has(:foo))"), false);
+ assert_equals(CSS.supports("selector(:has(.a, :foo))"), false);
+ assert_equals(CSS.supports("selector(:has(:foo, .a))"), false);
+ assert_equals(CSS.supports("selector(:not(:foo))"), false);
+ assert_equals(CSS.supports("selector(:not(.a, :foo))"), false);
+ assert_equals(CSS.supports("selector(:not(:foo, .a))"), false);
+ }, "Invalid selector can be detected with CSS.supports()");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:is(:foo))"), false);
+ assert_equals(CSS.supports("selector(:is(.a, :foo))"), false);
+ assert_equals(CSS.supports("selector(:is(:foo, .a))"), false);
+ assert_equals(CSS.supports("selector(:is(:has(:foo, a), .b))"), false);
+ assert_equals(CSS.supports("selector(:where(:foo))"), false);
+ assert_equals(CSS.supports("selector(:where(.a, :foo))"), false);
+ assert_equals(CSS.supports("selector(:where(:foo, .a))"), false);
+ assert_equals(CSS.supports("selector(:where(:is(:foo, a), .b))"), false);
+ assert_equals(CSS.supports("selector(:has(:where(:foo, a), .b))"), false);
+ }, "Invalid selector can be detected with CSS.supports() even if it is dropped by forgiving parsing");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:is())"), false);
+ assert_equals(CSS.supports("selector(:where())"), false);
+ assert_equals(CSS.supports("selector(:has())"), false);
+ }, ":is(), :where() or :has() always fails without argument");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:has(:has(.a)))"), false);
+ assert_equals(CSS.supports("selector(:has(:has(.a), b))"), false);
+ assert_equals(CSS.supports("selector(.a, :has(:has(.b)))"), false);
+ assert_equals(CSS.supports("selector(:has(:is(:has(.a))))"), false);
+ assert_equals(CSS.supports("selector(:has(:is(:has(.a), .b)))"), false);
+ assert_equals(CSS.supports("selector(:has(:is(.a, :has(.b))))"), false);
+ }, ":has() always fails inside :has()");
+
+ test(function() {
+ assert_equals(CSS.supports("selector(:is(::after)"), false);
+ assert_equals(CSS.supports("selector(:is(::before)"), false);
+ assert_equals(CSS.supports("selector(:is(::first-letter)"), false);
+ assert_equals(CSS.supports("selector(:is(::first-line)"), false);
+ assert_equals(CSS.supports("selector(:where(::after)"), false);
+ assert_equals(CSS.supports("selector(:where(::before)"), false);
+ assert_equals(CSS.supports("selector(:where(::first-letter)"), false);
+ assert_equals(CSS.supports("selector(:where(::first-line)"), false);
+ assert_equals(CSS.supports("selector(:has(::after)"), false);
+ assert_equals(CSS.supports("selector(:has(::before)"), false);
+ assert_equals(CSS.supports("selector(:has(::first-letter)"), false);
+ assert_equals(CSS.supports("selector(:has(::first-line)"), false);
+ }, "Some pseudo elements always fail inside :is(), :where(), :has()");
+</script>
diff --git a/testing/web-platform/tests/css/css-conditional/js/conditional-CSSGroupingRule.html b/testing/web-platform/tests/css/css-conditional/js/conditional-CSSGroupingRule.html
new file mode 100644
index 0000000000..bde92d7091
--- /dev/null
+++ b/testing/web-platform/tests/css/css-conditional/js/conditional-CSSGroupingRule.html
@@ -0,0 +1,244 @@
+<!DOCTYPE HTML>
+<html lang=en>
+ <title>CSSGroupingRule Conditional Rules Test</title>
+ <link rel="author" title="L. David Baron" href="https://dbaron.org/">
+ <link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
+ <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+ <link rel="help" href="http://www.w3.org/TR/css3-conditional/#the-cssgroupingrule-interface">
+ <meta name="assert" content="requirements in definition of insertRule">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+<style id="style">
+ @media unsupported { /* tests need to work even if condition is false */ }
+ @supports (unsupported: value) { }
+</style>
+<div id=log></div>
+<div id="test"></div>
+<script>
+
+ var rules = document.getElementById("style").sheet.cssRules;
+ var rule_names = ["@media", "@supports"];
+ var rule_types = [CSSRule.MEDIA_RULE, CSSRule.SUPPORTS_RULE]
+ var rule_nums = [4, 12]
+
+ for (let i = 0; i < 2; i++) {
+ var grouping_rule = rules[i];
+ var rule_name = rule_names[i];
+
+ test(function() {
+ assert_true(grouping_rule instanceof CSSGroupingRule,
+ rule_name + " instanceof CSSGroupingRule");
+ },
+ rule_name + " is CSSGroupingRule");
+
+ test(function() {
+ assert_equals(grouping_rule.type, rule_types[i],
+ "Rule type of " + rule_name + " rule");
+ assert_equals(grouping_rule.type, rule_nums[i],
+ "Rule number of " + rule_name + " rule");
+ },
+ rule_name + " rule type");
+
+ test(function() {
+ assert_equals(grouping_rule.cssRules.length, 0,
+ "Starting cssRules.length of " + rule_name + " rule");
+ },
+ "Empty " + rule_name + " rule length");
+
+ test(function() {
+ assert_throws_dom("HIERARCHY_REQUEST_ERR",
+ function() {
+ grouping_rule.insertRule("@import url(foo.css);", 0);
+ },
+ "inserting a disallowed rule should throw HIERARCHY_REQUEST_ERR");
+ },
+ "insertRule of @import into " + rule_name);
+
+ test(function() {
+ assert_throws_dom("INDEX_SIZE_ERR",
+ function() {
+ grouping_rule.insertRule("p { color: green }", 1);
+ },
+ "inserting at a bad index throws INDEX_SIZE_ERR");
+ },
+ "insertRule into empty " + rule_name + " at bad index");
+
+ test(function() {
+ grouping_rule.insertRule("p { color: green }", 0);
+ assert_equals(grouping_rule.cssRules.length, 1,
+ "Modified cssRules.length of " + rule_name + " rule");
+ grouping_rule.insertRule("p { color: blue }", 1);
+ assert_equals(grouping_rule.cssRules.length, 2,
+ "Modified cssRules.length of " + rule_name + " rule");
+ grouping_rule.insertRule("p { color: aqua }", 1);
+ assert_equals(grouping_rule.cssRules.length, 3,
+ "Modified cssRules.length of " + rule_name + " rule");
+ assert_throws_dom("INDEX_SIZE_ERR",
+ function() {
+ grouping_rule.insertRule("p { color: green }", 4);
+ },
+ "inserting at a bad index throws INDEX_SIZE_ERR");
+ assert_equals(grouping_rule.cssRules.length, 3,
+ "Modified cssRules.length of " + rule_name + " rule");
+ },
+ "insertRule into " + rule_name + " updates length");
+
+ test(function() {
+ while (grouping_rule.cssRules.length > 0) {
+ grouping_rule.deleteRule(0);
+ }
+ grouping_rule.insertRule("@media print {}", 0);
+ assert_equals(grouping_rule.cssRules.length, 1,
+ "Modified cssRules.length of " + rule_name + " rule");
+ assert_equals(grouping_rule.cssRules[0].type, CSSRule.MEDIA_RULE,
+ "inserting syntactically correct media rule succeeds");
+ },
+ "insertRule of valid @media into " + rule_name);
+
+ test(function() {
+ while (grouping_rule.cssRules.length > 0) {
+ grouping_rule.deleteRule(0);
+ }
+ grouping_rule.insertRule("p { color: yellow }", 0);
+ assert_equals(grouping_rule.cssRules.length, 1,
+ "Modified cssRules.length of " + rule_name + " rule");
+ assert_equals(grouping_rule.cssRules[0].type, CSSRule.STYLE_RULE,
+ "inserting syntactically correct style rule succeeds");
+ },
+ "insertRule of valid style rule into " + rule_name);
+
+ test(function() {
+ while (grouping_rule.cssRules.length > 0) {
+ grouping_rule.deleteRule(0);
+ }
+ assert_throws_dom("SYNTAX_ERR",
+ function() {
+ grouping_rule.insertRule("@media bad syntax;", 0);
+ },
+ "inserting syntactically invalid rule throws syntax error");
+ assert_equals(grouping_rule.cssRules.length, 0,
+ "Modified cssRules.length of " + rule_name + " rule");
+ },
+ "insertRule of invalid @media into " + rule_name);
+
+ test(function() {
+ while (grouping_rule.cssRules.length > 0) {
+ grouping_rule.deleteRule(0);
+ }
+ assert_throws_dom("SYNTAX_ERR",
+ function() {
+ grouping_rule.insertRule("", 0);
+ },
+ "inserting empty rule throws syntax error");
+ assert_equals(grouping_rule.cssRules.length, 0,
+ "Modified cssRules.length of " + rule_name + " rule");
+ },
+ "insertRule of empty string into " + rule_name);
+
+ test(function() {
+ while (grouping_rule.cssRules.length > 0) {
+ grouping_rule.deleteRule(0);
+ }
+ assert_throws_dom("SYNTAX_ERR",
+ function() {
+ grouping_rule.insertRule("@media print {} foo", 0);
+ },
+ "inserting rule with garbage afterwards throws syntax error");
+ assert_equals(grouping_rule.cssRules.length, 0,
+ "Modified cssRules.length of " + rule_name + " rule");
+ },
+ "insertRule of valid @media rule followed by garbage into " + rule_name);
+
+ test(function() {
+ while (grouping_rule.cssRules.length > 0) {
+ grouping_rule.deleteRule(0);
+ }
+ assert_throws_dom("SYNTAX_ERR",
+ function() {
+ grouping_rule.insertRule("p { color: yellow } foo", 0);
+ },
+ "inserting rule with garbage afterwards throws syntax error");
+ assert_equals(grouping_rule.cssRules.length, 0,
+ "Modified cssRules.length of " + rule_name + " rule");
+ },
+ "insertRule of valid style rule followed by garbage into " + rule_name);
+
+ test(function() {
+ while (grouping_rule.cssRules.length > 0) {
+ grouping_rule.deleteRule(0);
+ }
+ assert_throws_dom("SYNTAX_ERR",
+ function() {
+ grouping_rule.insertRule("@media print {} @media print {}", 0);
+ },
+ "inserting multiple rules throws syntax error");
+ assert_equals(grouping_rule.cssRules.length, 0,
+ "Modified cssRules.length of " + rule_name + " rule");
+ },
+ "insertRule of mutiple valid @media into " + rule_name);
+
+ test(function() {
+ while (grouping_rule.cssRules.length > 0) {
+ grouping_rule.deleteRule(0);
+ }
+ assert_throws_dom("SYNTAX_ERR",
+ function() {
+ grouping_rule.insertRule("p { color: yellow } @media print {}", 0);
+ },
+ "inserting multiple rules throws syntax error");
+ assert_equals(grouping_rule.cssRules.length, 0,
+ "Modified cssRules.length of " + rule_name + " rule");
+ },
+ "insertRule of valid style rulle followed by valid @media into " + rule_name);
+
+ test(function() {
+ while (grouping_rule.cssRules.length > 0) {
+ grouping_rule.deleteRule(0);
+ }
+ assert_throws_dom("SYNTAX_ERR",
+ function() {
+ grouping_rule.insertRule("@media print {} p { color: yellow }", 0);
+ },
+ "inserting multiple rules throws syntax error");
+ assert_equals(grouping_rule.cssRules.length, 0,
+ "Modified cssRules.length of " + rule_name + " rule");
+ },
+ "insertRule of valid style rule followed by valid @media into " + rule_name);
+
+ test(function() {
+ while (grouping_rule.cssRules.length > 0) {
+ grouping_rule.deleteRule(0);
+ }
+ assert_throws_dom("SYNTAX_ERR",
+ function() {
+ grouping_rule.insertRule("p { color: yellow } p { color: yellow }", 0);
+ },
+ "inserting multiple rules throws syntax error");
+ assert_equals(grouping_rule.cssRules.length, 0,
+ "Modified cssRules.length of " + rule_name + " rule");
+ },
+ "insertRule of two valid style rules into " + rule_name);
+
+ test(function() {
+ while (grouping_rule.cssRules.length > 0) {
+ grouping_rule.deleteRule(0);
+ }
+ var res = grouping_rule.insertRule("p { color: green }", 0);
+ assert_equals(res, 0, "return value should be index");
+ assert_equals(grouping_rule.cssRules.length, 1,
+ "Modified cssRules.length of " + rule_name + " rule");
+ res = grouping_rule.insertRule("p { color: green }", 0);
+ assert_equals(res, 0, "return value should be index");
+ assert_equals(grouping_rule.cssRules.length, 2,
+ "Modified cssRules.length of " + rule_name + " rule");
+ res = grouping_rule.insertRule("p { color: green }", 2);
+ assert_equals(res, 2, "return value should be index");
+ assert_equals(grouping_rule.cssRules.length, 3,
+ "Modified cssRules.length of " + rule_name + " rule");
+ },
+ "Return value of insertRule into " + rule_name);
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-conditional/js/supports-conditionText.html b/testing/web-platform/tests/css/css-conditional/js/supports-conditionText.html
new file mode 100644
index 0000000000..ea74077dfd
--- /dev/null
+++ b/testing/web-platform/tests/css/css-conditional/js/supports-conditionText.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<meta charset=UTF-8>
+<title>CSSGroupingRule Conditional Rules Test</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/">
+<link rel="help" href="https://www.w3.org/TR/css-conditional-3/#the-cssconditionrule-interface">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style id="style"></style>
+
+<script>
+
+function check_condition_text(text) {
+ test(function() {
+ let style_element = document.getElementById("style");
+ style_element.textContent = `@supports ${text} {}`;
+ let rules = style_element.sheet.cssRules;
+ assert_equals(rules.length, 1);
+ assert_equals(rules[0].conditionText, text);
+ }, `conditionText getter for @supports ${text}`);
+}
+
+check_condition_text("(color: red)");
+check_condition_text("(color : red) or ( color:blue )");
+check_condition_text("not (color: red)");
+check_condition_text("()");
+check_condition_text("func()");
+check_condition_text("([])");
+check_condition_text("({})");
+check_condition_text("(())");
+check_condition_text("(func())");
+check_condition_text("(x)");
+check_condition_text("func(x)");
+check_condition_text("([x])");
+check_condition_text("({x})");
+check_condition_text("((x))");
+check_condition_text("(func(x))");
+
+</script>
+</body>
+</html>