import assert from "node:assert/strict"; import test from "node:test"; import { cssDeclarations } from "./css-contract-test-support.ts"; const source = ` @media (max-width: 640px) { [data-sidebar="content"] { -webkit-overflow-scrolling: touch; } } [data-sidebar="content"] { min-height: 0; overflow-y: auto; } .session-list { overflow-x: clip; } .panel [data-sidebar="content"] { color: red; } .a, .b { gap: 4px; } /* ---- Documented section ---- */ .documented { padding: 8px; } .wrapper .multiline { margin: 0; } `; test("reads a base rule that a responsive override precedes", () => { const declarations = cssDeclarations('[data-sidebar="content"]', source); assert.match(declarations, /min-height:\s*0/); assert.match(declarations, /overflow-y:\s*auto/); }); test("includes every rule for the selector so a negative assertion cannot be evaded", () => { const declarations = cssDeclarations('[data-sidebar="content"]', source); assert.match(declarations, /-webkit-overflow-scrolling:\s*touch/); assert.match(declarations, /color:\s*red/); }); test("matches a selector inside a comma separated list", () => { assert.match(cssDeclarations(".b", source), /gap:\s*4px/); }); test("accepts a whole group as the query", () => { assert.match(cssDeclarations(".a, .b", source), /gap:\s*4px/); assert.match(cssDeclarations(".missing-one, .documented", source), /padding:\s*8px/); }); test("does not match a different selector that shares a prefix", () => { assert.doesNotMatch(cssDeclarations(".session-list", source), /min-height/); }); test("reads a rule introduced by a comment", () => { assert.match(cssDeclarations(".documented", source), /padding:\s*8px/); }); test("reads a rule whose selector wraps across lines", () => { assert.match(cssDeclarations(".multiline", source), /margin:\s*0/); }); test("fails loudly when the selector is absent", () => { assert.throws(() => cssDeclarations(".missing", source), /missing CSS selector: \.missing/); });