import fs from "node:fs" import path from "node:path" import { expect, test } from "@playwright/test" const appRoot = path.resolve(__dirname, "../../src/app") const publicRoutes = new Set(["/", "/login", "/register"]) const toRoute = (filePath: string) => { const relative = path.relative(appRoot, filePath).replaceAll("\\", "/") const segments = relative .split("/") .slice(0, -1) .filter((segment) => !segment.startsWith("(")) if (segments.some((segment) => segment.startsWith("["))) return null if (segments.length === 0) return "/" return `/${segments.join("/")}` } const collectPageFiles = (dir: string): string[] => { const entries = fs.readdirSync(dir, { withFileTypes: true }) return entries.flatMap((entry) => { const fullPath = path.join(dir, entry.name) if (entry.isDirectory()) return collectPageFiles(fullPath) return entry.name === "page.tsx" ? [fullPath] : [] }) } const allStaticRoutes = Array.from( new Set( collectPageFiles(appRoot) .map((file) => toRoute(file)) .filter((route): route is string => Boolean(route)), ), ).sort((a, b) => a.localeCompare(b)) const protectedRoutes = allStaticRoutes.filter((route) => !publicRoutes.has(route)) test.describe("full route regression", () => { test("route inventory is complete", async () => { expect(allStaticRoutes.length).toBeGreaterThanOrEqual(30) expect(allStaticRoutes).toContain("/admin/dashboard") expect(allStaticRoutes).toContain("/teacher/dashboard") expect(allStaticRoutes).toContain("/student/dashboard") expect(allStaticRoutes).toContain("/parent/dashboard") expect(allStaticRoutes).toContain("/settings") expect(allStaticRoutes).toContain("/profile") }) for (const route of publicRoutes) { test(`public route renders: ${route}`, async ({ page }) => { const response = await page.goto(route) expect(response?.status() ?? 200).toBeLessThan(500) await expect(page).not.toHaveURL(/\/500(?:$|[/?#])/) }) } for (const route of protectedRoutes) { test(`protected route guard: ${route}`, async ({ page }) => { const response = await page.goto(route) expect(response?.status() ?? 200).toBeLessThan(500) const finalUrl = new URL(page.url()) const finalPath = finalUrl.pathname expect(finalPath === route || finalPath === "/login").toBe(true) if (finalPath === "/login") { const callbackUrl = finalUrl.searchParams.get("callbackUrl") ?? "" const normalizedCallback = callbackUrl.startsWith("http") ? new URL(callbackUrl).pathname : callbackUrl expect(normalizedCallback === "" || normalizedCallback === route).toBe(true) } }) } })