import test from "node:test"; import assert from "node:assert/strict"; import path from "node:path"; import { readFile } from "node:fs/promises"; import { fileURLToPath } from "node:url"; const testsDir = path.dirname(fileURLToPath(import.meta.url)); const projectChatPagePath = path.join(testsDir, "../src/app/conversations/[projectId]/page.tsx"); test("project chat page listens to conversation updates for realtime refresh", async () => { const source = await readFile(projectChatPagePath, "utf8"); const realtimeRefreshConfig = source.match(/\(\);/, "expected project chat page to build a per-message warning map from executionWarnings", ); assert.match( source, /detail\.conversationTasks\.find\(\(task\) => task\.requestMessageId === message\.id\)/, "expected project chat page to bind lightweight conversation tasks to each message", ); assert.match( source, /messageTask \? \(/, "expected project chat page to render a compact per-message task status strip", ); assert.match( source, /new Map\(\)/, "expected project chat page to dedupe repeated warnings per message before rendering", ); assert.match( source, /dedupedWarnings\.map\(\(warning\) => \(/, "expected project chat page to render deduped warnings instead of the raw warning list", ); assert.match( source, /detail\.conversationTasks\.length \?/, "expected project chat page to keep a task status summary when lightweight conversation tasks exist", ); assert.match( source, /resolveDispatchPlanComposerState\(detail\.dispatchPlans\)/, "expected project chat page to derive dispatch plan composer state directly from project detail payload", ); assert.doesNotMatch( source, /listDispatchPlansByProject/, "expected project chat page to avoid a separate dispatch plan read outside project detail payload", ); assert.match( source, /detail\.participantsPayload && detail\.participantsPayload\.repairRequired/, "expected project chat page to surface a repair card when group participants are invalid", ); assert.match( source, /修复群成员/, "expected project chat page to show a visible repair members affordance", ); assert.match( source, /detail\.participantsPayload\.repairReason/, "expected project chat page to render the server-provided repair reason copy", ); assert.match( source, /detail\.participantsPayload\.participants\.filter\(\(participant\) => participant\.status !== "active"\)/, "expected project chat page to surface the concrete invalid group members instead of only a generic repair flag", ); assert.match( source, /participant\.statusLabel \?\? participant\.status/, "expected project chat page to show each invalid participant status label", ); });