import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { join } from "node:path"; import test from "node:test"; const source = async (relativePath: string) => { return await readFile( join(process.cwd(), ...relativePath.split("/")), "utf8", ); }; test("audits dashboard page uses a dedicated board component", async () => { const dashboardPageSource = await source("app/dashboard/audits/page.tsx"); assert.doesNotMatch( dashboardPageSource, /DashboardPlaceholderPage/i, "Dashboard audits route should not render the placeholder page.", ); assert.match( dashboardPageSource, //, "Audits board should be mounted from route page.", ); assert.match( dashboardPageSource, /"@\/components\/audits\/audits-board"/, "Audits board should be imported from components.", ); }); test("audits board renders compact list with convex list query and core columns", async () => { const boardSource = await source("components/audits/audits-board.tsx"); assert.match( boardSource, /\"use client\"/, "AuditsBoard must be a Client Component for useQuery.", ); assert.match( boardSource, /useQuery\s*\(\s*api\.audits\.list,\s*\{\s*limit:\s*100\s*\}\s*\)/, "AuditsBoard should call api.audits.list with { limit: 100 }.", ); assert.match( boardSource, /sort\(\(\s*a,\s*b\s*\)\s*=>\s*b\.createdAt\s*-\s*a\.createdAt\)/, "Audits should be sorted newest first.", ); assert.match(boardSource, /Loading|lädt|Lade/i); assert.match(boardSource, /Keine Audits|keine Audits/i); assert.match(boardSource, /Slug/); assert.match(boardSource, /Domain/); assert.match(boardSource, /Status/); assert.match(boardSource, /Seiten/); assert.match( boardSource, /href=\{`\/dashboard\/audits\/\$\{audit\._id\}`\}/, "Each audit row should link to /dashboard/audits/{id}.", ); }); test("audit detail component uses getDetail query and renders skills overview section", async () => { const detailSource = await source("components/audits/audit-detail.tsx"); assert.match( detailSource, /\"use client\"/, "AuditDetail must be client-side for Convex query calls.", ); assert.match( detailSource, /api\.audits[\s\S]{0,80}getDetail/, "AuditDetail should use api.audits.getDetail query.", ); assert.match( detailSource, /useQuery\(\s*api\.audits\.getDetail,\s*\{/, "AuditDetail should call useQuery with api.audits.getDetail directly.", ); assert.doesNotMatch( detailSource, /const\s+auditDetailQueryRef/, "AuditDetail should not use a cast-based query fallback variable.", ); assert.match( detailSource, /const\s+audit\s*=\s*result\?\.audit;/, "AuditDetail should destructure audit from result.audit.", ); assert.match( detailSource, /const\s+lead\s*=\s*result\?\.lead;/, "AuditDetail should destructure lead from result.lead.", ); assert.match( detailSource, /leadSummary\(\s*lead\s*\)/, "AuditDetail should pass lead into leadSummary from result.lead.", ); assert.match( detailSource, /usedSkills/, "AuditDetail should inspect usedSkills for overview rendering.", ); assert.match( detailSource, /Keine Skills gespeichert/, "AuditDetail should show fallback text when no skills are saved.", ); assert.match( detailSource, /Verwendete Skills/, "AuditDetail should render Verwendete Skills heading.", ); assert.match( detailSource, /Lead|lead/, "AuditDetail should surface lead context when available.", ); assert.doesNotMatch( detailSource, /]*>\s*\{leadSummary\(\s*lead\|[\s\S]*?\)\s*\}\s*<\/p>/, "Lead summary should not wrap leadSummary output in a nested

.", ); assert.doesNotMatch( detailSource, /]*>\s*\{leadSummary\(\s*audit\.lead\)\s*\}\s*<\/p>/, "Lead summary should not wrap leadSummary output in a nested

.", ); }); test("audits detail route passes id to AuditDetail via Promise params", async () => { const pageSource = await source("app/dashboard/audits/[id]/page.tsx"); assert.match( pageSource, /params:\s*Promise<\{\s*id:\s*string\s*\}>/, "Audit detail route should accept params as Promise in Next.js 16 style.", ); assert.match( pageSource, /const \{\s*id\s*\}\s*=\s*await params/, "Audit detail route should unwrap Promise params.", ); assert.match( pageSource, / { const publicAuditSource = await source("app/audit/[slug]/page.tsx"); assert.doesNotMatch( publicAuditSource, /Verwendete Skills|usedSkills/i, "Public audit page must not show used skills.", ); });