import { describe, expect, it } from "vitest";
import { sanitizeBadgeWallCss } from "./sanitizeCss";
describe("sanitizeBadgeWallCss", () => {
// Behaviour gate: the CSS people actually write for their badge wall survives.
it("preserves ordinary rules, declarations and values", () => {
const out = sanitizeBadgeWallCss(
".badge { color: red; opacity: 0.5; border-radius: 8px; }",
);
expect(out).toContain("color");
expect(out).toContain("red");
expect(out).toContain("border-radius");
});
it("preserves backdrop-filter, content, url() and at-rules", () => {
expect(
sanitizeBadgeWallCss(".x { backdrop-filter: blur(4px); }"),
).toContain("backdrop-filter");
expect(sanitizeBadgeWallCss('.x::before { content: "★"; }')).toContain(
"content",
);
expect(
sanitizeBadgeWallCss(
".x { background: url(https://cdn.due.moe/a.png); }",
),
).toContain("url(https://cdn.due.moe/a.png)");
expect(
sanitizeBadgeWallCss("@media (min-width: 1px) { .x { color: blue; } }"),
).toContain("@media");
expect(
sanitizeBadgeWallCss(
"@keyframes spin { from { transform: rotate(0); } to { transform: rotate(360deg); } }",
),
).toContain("@keyframes");
});
it("returns empty string for nullish input", () => {
expect(sanitizeBadgeWallCss("")).toBe("");
// @ts-expect-error exercising defensive nullish handling
expect(sanitizeBadgeWallCss(undefined)).toBe("");
});
// The fix: dangerous constructs are removed while surrounding CSS is kept.
it("strips @import, behavior, -moz-binding, expression and js: urls", () => {
const imported = sanitizeBadgeWallCss(
"@import url(https://evil.example.com/x.css); .x { color: red; }",
);
expect(imported).not.toContain("@import");
expect(imported).toContain("color");
expect(
sanitizeBadgeWallCss(".x { behavior: url(evil.htc); color: red; }"),
).not.toContain("behavior");
expect(
sanitizeBadgeWallCss(".x { -moz-binding: url(evil.xml#x); }"),
).not.toContain("-moz-binding");
expect(
sanitizeBadgeWallCss(".x { width: expression(alert(1)); }"),
).not.toContain("expression");
expect(
sanitizeBadgeWallCss(".x { background: url(javascript:alert(1)); }"),
).not.toContain("javascript:");
});
it("drops .b { color: blue; }",
);
expect(out).not.toContain("