Files
CapaKraken/apps/web/e2e/dev-system/nav-smoke.spec.ts
T
Hartmut aef4c61dcc test(e2e): add nav-smoke spec covering all 35 sidebar routes (#50)
- e2e/dev-system/nav-smoke.spec.ts: new Playwright spec in the dev-system
  suite; iterates every href from navSections + adminNavEntries, asserts
  HTTP status ≠ 404 and no "page not found" text for an authenticated admin
- e2e/navigation.spec.ts: add "all nav routes resolve" smoke block covering
  16 routes not previously tested in the isolated test suite

All 35 routes pass against live dev server. Catches dead nav links before
users encounter them.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-03 12:11:37 +02:00

104 lines
3.5 KiB
TypeScript

/**
* Navigation route smoke test — runs against the live dev server (port 3100).
*
* Verifies that every sidebar destination in AppShell (navSections + adminNavEntries)
* returns a real page (not 404) for an authenticated ADMIN user.
*
* Config: playwright.dev.config.ts
* Auth: e2e/dev-system/.auth/admin.json (created by global-setup.ts)
*
* Run:
* pnpm --filter @capakraken/web exec playwright test \
* --config playwright.dev.config.ts \
* e2e/dev-system/nav-smoke.spec.ts
*/
import * as path from "path";
import { expect, test } from "@playwright/test";
// ── Standalone href list ────────────────────────────────────────────────────
// Mirrors AppShell.tsx navSections + adminNavEntries.
// DO NOT import AppShell here — that pulls in the full Next.js component tree.
// Keep in sync with apps/web/src/components/layout/AppShell.tsx.
const REGULAR_NAV_HREFS = [
// Planning
"/dashboard",
"/timeline",
"/allocations",
"/staffing",
"/notifications",
// Estimating
"/estimates",
"/admin/rate-cards",
"/admin/effort-rules",
"/admin/experience-multipliers",
// Resources
"/resources",
"/projects",
"/roles",
// Analytics
"/analytics/skills",
"/reports/chargeability",
"/reports/builder",
"/analytics/computation-graph",
"/analytics/insights",
// Time Off
"/vacations/my",
"/vacations",
// Account
"/account/security",
] as const;
const ADMIN_NAV_HREFS = [
"/admin/blueprints",
"/admin/clients",
"/admin/countries",
"/admin/org-units",
"/admin/utilization-categories",
"/admin/management-levels",
"/admin/imports",
"/admin/calculation-rules",
"/admin/vacations",
"/admin/users",
"/admin/system-roles",
"/admin/settings",
"/admin/notifications",
"/admin/webhooks",
"/admin/activity-log",
] as const;
const ALL_HREFS = [...REGULAR_NAV_HREFS, ...ADMIN_NAV_HREFS] as const;
// ── Auth state ──────────────────────────────────────────────────────────────
// Reuse the saved admin session from global-setup — avoids hitting the rate limiter.
test.use({
storageState: path.join(__dirname, ".auth/admin.json"),
});
// ── Tests ───────────────────────────────────────────────────────────────────
test.describe("nav smoke — all sidebar routes resolve for admin (no 404)", () => {
for (const href of ALL_HREFS) {
test(href, async ({ page }) => {
// waitUntil: "commit" — only wait for HTTP response headers, not full render.
// Fast enough for a 404 check; avoids timeouts on data-heavy pages.
// Generous timeout: analytics/insights may need JIT compile on first visit (~15 s).
const response = await page.goto(href, {
waitUntil: "commit",
timeout: 60_000,
});
// HTTP response must not be 404
expect(
response?.status(),
`${href} returned HTTP ${response?.status()} — expected any status except 404`,
).not.toBe(404);
// Belt-and-suspenders: also check the rendered page doesn't contain Next.js 404 text
await expect(
page.locator("text=This page could not be found"),
`${href} rendered a Next.js 404 page`,
).not.toBeVisible({ timeout: 15_000 });
});
}
});