77 lines
3.2 KiB
TypeScript
77 lines
3.2 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
||
import { installMockApi } from "./mockApi";
|
||
|
||
test("overview renders run strip, KPIs, charts, top repos and reasons", async ({ page }) => {
|
||
await installMockApi(page);
|
||
await page.goto("/");
|
||
|
||
// Run strip
|
||
await expect(page.locator(".overview-run-strip").getByText("run_0002")).toBeVisible();
|
||
await expect(page.getByText("delta sync")).toBeVisible();
|
||
|
||
// KPI cards with fixture values
|
||
await expect(page.getByText("VRPs")).toBeVisible();
|
||
await expect(page.getByText("987")).toBeVisible();
|
||
await expect(page.locator(".kpi-grid").getByText("Rejected")).toBeVisible();
|
||
// Repositories KPI from stats/overview
|
||
const reposKpi = page.locator(".kpi-grid > *", { hasText: "Repositories" });
|
||
await expect(reposKpi).toBeVisible();
|
||
await expect(reposKpi).toContainText("3");
|
||
|
||
// Charts render (recharts svg)
|
||
await expect(page.locator(".recharts-responsive-container").first()).toBeVisible();
|
||
|
||
// Top repositories table, sorted by objects desc (900 > 300 > 84),
|
||
// not the fixture index order (300, 900, 84).
|
||
const repoRows = page.locator(".overview-bottom table tbody tr");
|
||
await expect(repoRows.first()).toContainText("repo-a.example");
|
||
await expect(repoRows.nth(1)).toContainText("repo-b.example");
|
||
await expect(repoRows.nth(2)).toContainText("repo-c.example");
|
||
|
||
// Top reject reasons, clustered by prefix: the two validation_time
|
||
// variants merge into one row with a combined count.
|
||
const cluster = page.getByRole("link", { name: /manifest is not valid at validation_time/ });
|
||
await expect(cluster).toBeVisible();
|
||
await expect(cluster).toContainText("×2");
|
||
await expect(cluster).toContainText("5");
|
||
await expect(page.getByRole("link", { name: "certificate expired" })).toBeVisible();
|
||
});
|
||
|
||
test("overview does not request the global object list (first-screen discipline)", async ({
|
||
page,
|
||
}) => {
|
||
await installMockApi(page);
|
||
const objectListRequests: string[] = [];
|
||
page.on("request", (req) => {
|
||
const url = new URL(req.url());
|
||
if (/\/api\/v1\/runs\/[^/]+\/objects$/.test(url.pathname)) {
|
||
objectListRequests.push(req.url());
|
||
}
|
||
});
|
||
await page.goto("/");
|
||
await expect(page.getByText("987")).toBeVisible();
|
||
expect(objectListRequests).toEqual([]);
|
||
});
|
||
|
||
test("overview drill-down: repo row navigates to repository detail", async ({ page }) => {
|
||
await installMockApi(page);
|
||
await page.goto("/");
|
||
await page.getByRole("cell", { name: "repo-b.example" }).click();
|
||
await expect(page).toHaveURL(/\/repositories\/repo-b2c3d4e5f6a7/);
|
||
await expect(page.getByRole("heading", { name: "repo-b.example" })).toBeVisible();
|
||
});
|
||
|
||
test("overview drill-down: reason navigates to filtered validation page", async ({ page }) => {
|
||
await installMockApi(page);
|
||
await page.goto("/");
|
||
await page.getByRole("link", { name: /manifest stale/ }).click();
|
||
await expect(page).toHaveURL(/\/validation\?reason=manifest/);
|
||
await expect(page.getByRole("heading", { name: "Validation" })).toBeVisible();
|
||
});
|
||
|
||
test("overview shows an explicit error state when the run cannot be loaded", async ({ page }) => {
|
||
await installMockApi(page, { failLatestRun: true });
|
||
await page.goto("/");
|
||
await expect(page.getByRole("alert")).toContainText("Failed to load run latest");
|
||
});
|