Files
boss/tests/android-detail-contract-unification.test.ts

123 lines
4.9 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("ProjectDetailActivity reads group dispatch and participant state from project detail payload", async () => {
const source = await readSource("../android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java");
assert.match(
source,
/detailResponse\.json\.optJSONArray\("dispatchPlans"\)/,
"expected project chat detail refreshes to read dispatchPlans directly from project detail payload",
);
assert.match(
source,
/detailResponse\.json\.optJSONObject\("participantsPayload"\)/,
"expected project chat detail refreshes to read participantsPayload directly from project detail payload",
);
assert.doesNotMatch(
source,
/apiClient\.getDispatchPlans\(projectId\)/,
"expected project chat detail refreshes to stop issuing a separate dispatch plans request",
);
assert.doesNotMatch(
source,
/apiClient\.getConversationParticipants\(projectId\)/,
"expected project chat detail refreshes to stop issuing a separate participants request",
);
});
test("GroupInfoActivity derives participants state from project detail payload", async () => {
const source = await readSource("../android/app/src/main/java/com/hyzq/boss/GroupInfoActivity.java");
assert.match(
source,
/JSONObject participantsPayload = extractParticipantsPayload\(detailResponse\.json\);/,
"expected group info page to derive participants from the detail payload before rendering",
);
assert.doesNotMatch(
source,
/apiClient\.getConversationParticipants\(projectId\)/,
"expected group info page to stop issuing a separate participants request",
);
assert.match(
source,
/groupRepairJustApplied = true;/,
"expected group info page to persist a successful repair flag across the immediate reload",
);
assert.match(
source,
/if \(groupRepairJustApplied\) \{/,
"expected group info page to render a durable success acknowledgement after repair reload",
);
assert.match(
source,
/群成员已更新/,
"expected group info page to show explicit success copy after a repair completes",
);
});
test("ConversationInfoActivity derives participants state from project detail payload", async () => {
const source = await readSource("../android/app/src/main/java/com/hyzq/boss/ConversationInfoActivity.java");
assert.match(
source,
/JSONObject participantsPayload = extractParticipantsPayload\(detailResponse\.json\);/,
"expected conversation info page to derive participants from the detail payload before rendering",
);
assert.doesNotMatch(
source,
/apiClient\.getConversationParticipants\(projectId\)/,
"expected conversation info page to stop issuing a separate participants request",
);
});
test("GroupCreateActivity reuses project detail payload when launched from a source conversation", async () => {
const source = await readSource("../android/app/src/main/java/com/hyzq/boss/GroupCreateActivity.java");
assert.match(
source,
/BossApiClient\.ApiResponse detailResponse = apiClient\.getProjectDetail\(sourceProjectId\);/,
"expected group creation from a source conversation to load source detail once",
);
assert.match(
source,
/JSONObject participantsPayload = extractParticipantsPayload\(detailResponse\.json,\s*sourceProjectId\);/,
"expected group creation page to derive source participants from project detail payload",
);
assert.doesNotMatch(
source,
/apiClient\.getConversationParticipants\(sourceProjectId\)/,
"expected group creation page to stop issuing a separate participants request for the source conversation",
);
});
test("BossApiClient no longer keeps unused group detail compatibility wrappers", async () => {
const source = await readSource("../android/app/src/main/java/com/hyzq/boss/BossApiClient.java");
assert.doesNotMatch(
source,
/public ApiResponse getDispatchPlans\(String projectId\)/,
"expected BossApiClient to drop the unused dispatch plans wrapper once all screens read from project detail",
);
assert.doesNotMatch(
source,
/public ApiResponse getConversationParticipants\(String projectId\)/,
"expected BossApiClient to drop the unused participants wrapper once all screens read from project detail",
);
});
test("ProjectDetailActivity uses a distinct repair meta copy when only one valid thread remains", async () => {
const source = await readSource("../android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java");
assert.match(
source,
/validParticipantCount > 0[\s\S]*当前仅有 "\s*\+\s*validParticipantCount\s*\+\s*" 个真实线程成员/,
"expected group repair card copy to distinguish one-valid-thread state from zero-valid-thread state",
);
});