import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { expect, test } from "@playwright/test";
const ROUTER_RS = fileURLToPath(
new URL("../../crates/buzz-relay/src/router.rs", import.meta.url),
);
/// The exact policy the relay serves on admin SPA documents. Read from the
/// relay source rather than copied, so this test can never pass against a
/// policy operators do not actually get. The preview server used here serves
/// no CSP of its own, so it is injected below.
function adminCsp() {
const source = readFileSync(ROUTER_RS, "utf8");
const match = source.match(/const ADMIN_CSP: &str = "([^"]+)";/);
if (!match) throw new Error(`ADMIN_CSP not found in ${ROUTER_RS}`);
return match[1];
}
const TOKEN =
"5f0e1d2c3b4a59687786958493a2b1c0decadebeefcafe0123456789abcdef01";
test("the relay admin csp does not break the built dashboard", async ({
page,
}) => {
const csp = adminCsp();
expect(csp).toContain("frame-ancestors 'none'");
expect(csp).not.toContain("unsafe-inline");
await page.addInitScript((token) => {
sessionStorage.setItem("buzz-admin-token", token);
}, TOKEN);
await page.route("**/api/admin/v1/**", (route) =>
route.fulfill({ contentType: "application/json", body: "[]" }),
);
// Only the document request: the API call to /reports carries a query string.
await page.route(
(url) => url.pathname === "/reports" && url.search === "",
async (route) => {
const response = await route.fetch();
await route.fulfill({
response,
headers: { ...response.headers(), "content-security-policy": csp },
});
},
);
const violations: string[] = [];
page.on("console", (message) => {
if (message.text().includes("Content Security Policy"))
violations.push(message.text());
});
await page.goto("/reports");
// Rendering at all proves the bundle's script and stylesheet loaded, and the
// empty state proves the fetch to /api/admin/v1 survived `connect-src 'self'`.
await expect(
page.getByRole("heading", { name: "Open reports" }),
).toBeVisible();
await expect(page.getByText("No records.")).toBeVisible();
expect(violations).toEqual([]);
});
test("the linked favicon loads under the admin csp", async ({ page }) => {
const csp = adminCsp();
await page.route(
(url) => url.pathname === "/" && url.search === "",
async (route) => {
const response = await route.fetch();
await route.fulfill({
response,
headers: { ...response.headers(), "content-security-policy": csp },
});
},
);
const violations: string[] = [];
page.on("console", (message) => {
if (message.text().includes("Content Security Policy"))
violations.push(message.text());
});
await page.goto("/");
const href = await page.locator("link[rel=icon]").getAttribute("href");
expect(href).toBe("/favicon.svg");
// Headless Chromium never issues the `` request itself, so
// load the same file the same way the policy sees it: an image fetch under
// `img-src 'self'`. A blocked fetch rejects `decode()`; a successful one
// proves the icon renders, and that the SVG's own inline