import { expect, test } from "@playwright/test"; import { installMockApi } from "./mockApi"; test.beforeEach(async ({ page }) => { await installMockApi(page); }); test("shell renders navigation, brand and connection status", async ({ page }) => { await page.goto("/"); await expect(page.getByText("RPKI Explorer")).toBeVisible(); const nav = page.getByRole("navigation", { name: "Primary" }); for (const label of [ "Overview", "Repositories", "Publication Points", "Objects", "Validation", "Exports", "Runs", "API", ]) { await expect(nav.getByRole("link", { name: label })).toBeVisible(); } await expect(page.getByText("connected")).toBeVisible(); }); test("every nav entry navigates to a real page (no dead controls)", async ({ page }) => { await page.goto("/"); const nav = page.getByRole("navigation", { name: "Primary" }); const cases: { label: string; path: RegExp; heading: string | RegExp }[] = [ { label: "Repositories", path: /\/repositories$/, heading: "Repositories" }, { label: "Publication Points", path: /\/publication-points$/, heading: "Publication Points" }, { label: "Objects", path: /\/objects$/, heading: "Objects" }, { label: "Validation", path: /\/validation$/, heading: "Validation" }, { label: "Exports", path: /\/exports$/, heading: "Exports" }, { label: "Runs", path: /\/runs$/, heading: "Runs" }, { label: "API", path: /\/api$/, heading: "API" }, ]; for (const { label, path, heading } of cases) { await nav.getByRole("link", { name: label, exact: true }).click(); await expect(page).toHaveURL(path); await expect(page.getByRole("heading", { name: heading }).first()).toBeVisible(); } }); test("run selector pins the run via ?run= and pages use it", async ({ page }) => { const requests: string[] = []; page.on("request", (req) => { if (req.url().includes("/api/v1/runs/")) requests.push(req.url()); }); await page.goto("/"); const selector = page.getByLabel("Run"); await expect(selector).toBeVisible(); await selector.selectOption("run_0001"); await expect(page).toHaveURL(/run=run_0001/); await expect.poll(() => requests.some((url) => url.includes("/runs/run_0001/"))).toBe(true); }); test("topbar search routes to the search page with the query", async ({ page }) => { await page.goto("/"); const input = page.getByRole("searchbox", { name: "Global search" }); await input.fill("repo-a.example"); await input.press("Enter"); await expect(page).toHaveURL(/\/search\?q=repo-a/); await expect(page.getByRole("heading", { name: "Search", exact: true })).toBeVisible(); }); test("unknown routes render the 404 page", async ({ page }) => { await page.goto("/definitely-not-a-page"); await expect(page.getByText("404")).toBeVisible(); await page.getByRole("link", { name: "Back to Overview" }).click(); await expect(page).toHaveURL(/\/$/); }); test("deep links restore page state after reload", async ({ page }) => { await page.goto("/objects?type=manifest"); await expect(page).toHaveURL(/type=manifest/); await expect(page.getByLabel("Type")).toHaveValue("manifest"); await page.reload(); await expect(page.getByLabel("Type")).toHaveValue("manifest"); }); test("runs page lists runs, pins a run and expands artifacts", async ({ page }) => { await page.goto("/runs"); await expect(page.getByRole("cell", { name: "run_0002" })).toBeVisible(); await expect(page.getByRole("cell", { name: "run_0001" })).toBeVisible(); // Expand artifacts for run_0001 const row = page.getByRole("row", { name: /run_0001/ }); await row.getByRole("button", { name: "Artifacts" }).click(); await expect(page.getByText("/data/runs/run_0001/report.json")).toBeVisible(); // Pin run_0001 — navigates to overview with ?run=run_0001 await row.getByRole("button", { name: "Use run" }).click(); await expect(page).toHaveURL(/run=run_0001/); });