68 lines
2.6 KiB
TypeScript
68 lines
2.6 KiB
TypeScript
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("moves theme variables from :root onto the view root", () => {
|
|
expect(one(":root,:host{--spacing:.25rem}")).toBe(
|
|
".beaver-root { --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; }"
|
|
);
|
|
});
|
|
});
|