import test from "node:test"; import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; async function readSource(path: string) { return readFile(new URL(path, import.meta.url), "utf8"); } test("BossApiClient exposes a lightweight project messages endpoint", async () => { const source = await readSource("../android/app/src/main/java/com/hyzq/boss/BossApiClient.java"); assert.match( source, /public ApiResponse getProjectMessages\(String projectId\) throws IOException, JSONException \{/, "expected Android client to expose a lightweight messages endpoint", ); assert.match( source, /return requestWithRestore\("GET", "\/api\/v1\/projects\/" \+ encode\(projectId\) \+ "\/messages", null\);/, "expected lightweight message refreshes to reuse the dedicated messages route", ); }); test("ProjectDetailActivity reserves full realtime reloads for non-message events", async () => { const source = await readSource("../android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java"); assert.match( source, /private boolean realtimeReloadRequiresFullSnapshot;/, "expected chat page debounce state to remember whether a full snapshot is required", ); assert.match( source, /runOnUiThread\(\(\) -> scheduleRealtimeReload\(!"project\.messages\.updated"\.equals\(event\.eventName\)\)\);/, "expected message-only realtime updates to avoid forcing a full snapshot", ); assert.match( source, /void triggerRealtimeReload\(boolean requireFullSnapshot\) \{\s*if \(requireFullSnapshot\) \{\s*reload\(\);\s*return;\s*\}\s*reloadMessagesOnly\(\);\s*\}/s, "expected debounced realtime reloads to choose between full and lightweight refresh paths", ); });