import { describe, expect, it } from "vitest"; import { scopeCss } from "../scripts/scope-css.mjs"; const one = (css: string) => scopeCss(css).replace(/\s+/gu, " ").trim(); describe("scoping the built stylesheet", () => { it("prefixes a utility with the view root, keeping the root itself in reach", () => { expect(one(".flex{display:flex!important}")).toBe( ":is(.beaver-root, .beaver-root *).flex { display: flex !important; }" ); }); it("outranks the same utility from another plugin's Tailwind", () => { // Class specificity: theirs is (0,1,0); ours must be (0,2,0). const out = one(".hidden{display:none!important}"); expect(out.startsWith(":is(.beaver-root, .beaver-root *).hidden")).toBe( true ); }); it("keeps pseudo-elements at the end where they are valid", () => { expect(one(".x::placeholder{color:red}")).toBe( ":is(.beaver-root, .beaver-root *).x::placeholder { color: red; }" ); expect(one(".y::first-letter{t:1}")).toContain(".y:first-letter"); }); it("scopes rules nested in container queries and layers", () => { const out = one( "@layer utilities{@container (min-width:30rem){.a{display:inline-block!important}}}" ); // lightningcss rewrites the query into range syntax; Obsidian's Chromium // has understood that inside @container since container queries landed. expect(out).toContain("@container (width >= 30rem)"); expect(out).toContain(":is(.beaver-root, .beaver-root *).a"); }); it("drops a leading universal selector instead of producing `:is()*`", () => { const out = one("*,:before,::backdrop{--tw-a:initial}"); expect(out).toContain(":is(.beaver-root, .beaver-root *),"); expect(out).toContain(":is(.beaver-root, .beaver-root *):before"); expect(out).not.toContain("*)*"); }); it("leaves tailwind's theme variables on :root, under obsidian's body values", () => { expect(one(":root,:host{--spacing:.25rem}")).toBe( ":root, :host { --spacing: .25rem; }" ); }); it("leaves rules that already name the root alone", () => { const reset = ".beaver-root.beaver-root button{cursor:pointer}"; expect(one(reset)).toBe( ".beaver-root.beaver-root button { cursor: pointer; }" ); expect(one(".theme-dark .beaver-root{--note:red}")).toBe( ".theme-dark .beaver-root { --note: red; }" ); }); it("scopes variant selectors without breaking their inner :where()", () => { const out = one(".dark\\:bg-x:where(.theme-dark,.theme-dark *){b:1}"); expect(out).toBe( ":is(.beaver-root, .beaver-root *).dark\\:bg-x:where(.theme-dark, .theme-dark *) { b: 1; }" ); }); });