rpki/ui/rpki-explorer/tests/e2e/shell.spec.ts

102 lines
3.8 KiB
TypeScript

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/);
});