109 lines
4.5 KiB
TypeScript
109 lines
4.5 KiB
TypeScript
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("events route enriches message events with a lightweight project chat payload", async () => {
|
|
const source = await readSource("../src/app/api/v1/events/route.ts");
|
|
|
|
assert.match(
|
|
source,
|
|
/projectMessagesPayload:\s*buildProjectMessagesRealtimePayload\(state,\s*String\(payload\.projectId \?\? ""\)\)/,
|
|
"expected realtime event route to include a lightweight project chat payload for message events",
|
|
);
|
|
});
|
|
|
|
test("ProjectDetailActivity applies lightweight realtime chat payloads before scheduling reloads", async () => {
|
|
const source = await readSource("../android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java");
|
|
|
|
assert.match(
|
|
source,
|
|
/if \(tryApplyRealtimeMessagesPatch\(event\)\) \{\s*return;\s*\}/,
|
|
"expected chat page to try a local realtime message patch before falling back to debounced reloads",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/JSONObject projectMessagesPayload = event\.payload\.optJSONObject\("projectMessagesPayload"\);/,
|
|
"expected chat page to read the lightweight message payload from realtime events",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/renderLoadedProjectSnapshot\(new ProjectSnapshot\(projectMessagesPayload,\s*null,\s*null\)\);/,
|
|
"expected chat page to render the local realtime payload without forcing a network request",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/JSONArray executionWarnings = projectMessagesPayload\.optJSONArray\("executionWarnings"\);/,
|
|
"expected chat page to read executionWarnings from the lightweight realtime payload",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/LinearLayout statusRow = BossUi\.buildMessageStatusRow\(this, message, conversationTask, messageWarnings, outgoing\);/,
|
|
"expected each rendered message to create a compact status row",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/private List<JSONObject> buildMessageWarnings\(JSONObject payload, String messageId\)/,
|
|
"expected a helper returning grouped warnings per message",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/if \(!TextUtils\.equals\(currentFingerprint,\s*nextFingerprint\)\) \{/,
|
|
"expected realtime warning patches to branch on fingerprint differences before replacing views",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/replaceMessageViewById\(messageId,\s*buildMessageView\(message\)\);/,
|
|
"expected realtime warning patches to replace only the affected message after fingerprint differences",
|
|
);
|
|
const warningPatchMethod = source.match(
|
|
/private boolean tryPatchRealtimeExecutionWarnings\(JSONObject projectMessagesPayload\) \{[\s\S]*?\n \}/,
|
|
);
|
|
assert.ok(warningPatchMethod, "expected to locate the warning patch helper body");
|
|
const snapshotSwapCount =
|
|
warningPatchMethod[0].match(/currentRenderedProjectPayload = nextPayloadCopy;/g)?.length ?? 0;
|
|
assert.equal(
|
|
snapshotSwapCount,
|
|
1,
|
|
"expected warning patch helper to swap the rendered payload only once after all message diffs are processed",
|
|
);
|
|
});
|
|
|
|
test("BossUi keeps a detail-only message status row visible", async () => {
|
|
const source = await readSource("../android/app/src/main/java/com/hyzq/boss/BossUi.java");
|
|
|
|
assert.match(
|
|
source,
|
|
/boolean hasDetail = !TextUtils\.isEmpty\(detailText\);/,
|
|
"expected message status rows to detect detail-only status text",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/if \(!hasTask && !hasWarnings && !hasDetail\) \{\s*row\.setVisibility\(View\.GONE\);\s*return row;\s*\}/,
|
|
"expected message status rows to stay visible whenever detail text exists",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/if \(hasDetail\) \{\s*TextView detailView = new TextView\(context\);/,
|
|
"expected detail-only rows to still render their muted status text",
|
|
);
|
|
});
|
|
|
|
test("ProjectDetailActivity bypasses realtime message-only patching when group dispatch or repair state is active", async () => {
|
|
const source = await readSource("../android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java");
|
|
|
|
assert.match(
|
|
source,
|
|
/if \(shouldBypassRealtimeMessagesPatchForGroupState\(\)\) \{\s*return false;\s*\}/,
|
|
"expected realtime message patching to fall back to a full reload when group dispatch or repair state could be stale",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/private boolean shouldBypassRealtimeMessagesPatchForGroupState\(\) \{/,
|
|
"expected a dedicated helper guarding the fast patch path for group-only state",
|
|
);
|
|
});
|