feat: add group repair and dispatch rejection flows

This commit is contained in:
kris
2026-03-31 03:56:28 +08:00
parent 9c02ebb574
commit 4336dc22a7
21 changed files with 832 additions and 83 deletions

View File

@@ -54,6 +54,21 @@ public class BossApiClientDispatchPlansTest {
assertEquals("{\"approvedTargetProjectIds\":[\"target-1\",\"target-2\"]}", connection.requestBody());
}
@Test
public void rejectDispatchPlanUsesProjectScopedRejectEndpoint() throws Exception {
RecordingConnection connection = new RecordingConnection(new URL("https://boss.hyzq.net/api/v1/projects/p1/dispatch-plans/plan-1/reject"));
RecordingBossApiClient apiClient = new RecordingBossApiClient(connection);
BossApiClient.ApiResponse response = apiClient.rejectDispatchPlan("p1", "plan-1");
assertEquals(200, response.statusCode);
assertEquals("/api/v1/projects/p1/dispatch-plans/plan-1/reject", apiClient.lastPath);
assertEquals("POST", connection.requestMethodValue);
assertEquals(12000, connection.connectTimeoutValue);
assertEquals(65000, connection.readTimeoutValue);
assertEquals("{}", connection.requestBody());
}
@Test
public void sendProjectMessageUsesExtendedReadTimeoutForMasterAgent() throws Exception {
RecordingConnection connection = new RecordingConnection(new URL("https://boss.hyzq.net/api/v1/projects/master-agent/messages"));

View File

@@ -92,6 +92,29 @@ public class GroupInfoActivityTest {
);
}
@Test
public void renderGroupShowsRepairEntryForDirtyMembers() throws Exception {
Intent intent = new Intent()
.putExtra(GroupInfoActivity.EXTRA_PROJECT_ID, "group-1")
.putExtra(GroupInfoActivity.EXTRA_PROJECT_NAME, "巡检协作群");
TestGroupInfoActivity activity = Robolectric
.buildActivity(TestGroupInfoActivity.class, intent)
.setup()
.get();
ReflectionHelpers.callInstanceMethod(
activity,
"renderGroup",
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildDetailPayload()),
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildRepairParticipantsPayload())
);
LinearLayout content = activity.findViewById(R.id.screen_content);
assertTrue(viewTreeContainsText(content, "修复群成员"));
assertTrue(viewTreeContainsText(content, "当前群聊里有失效或不可下发的线程引用,请重新整理群成员。"));
assertTrue(viewTreeContainsText(content, "失效"));
}
private static JSONObject buildDetailPayload() throws Exception {
JSONObject threadMeta = new JSONObject()
.put("threadId", "group-thread-3")
@@ -123,6 +146,25 @@ public class GroupInfoActivityTest {
return new JSONObject().put("participants", participants);
}
private static JSONObject buildRepairParticipantsPayload() throws Exception {
JSONArray participants = new JSONArray()
.put(new JSONObject()
.put("projectId", "master-agent")
.put("threadDisplayName", "主 Agent 汇总")
.put("folderName", "主控线程")
.put("deviceId", "Mac Studio")
.put("threadId", "master-agent-thread")
.put("status", "invalid_target")
.put("statusLabel", "不是可下发线程")
.put("canOpenProject", true));
return new JSONObject()
.put("participants", participants)
.put("repairRequired", true)
.put("repairReason", "当前群聊里有失效或不可下发的线程引用,请重新整理群成员。")
.put("validParticipantCount", 0)
.put("invalidParticipantCount", 1);
}
private static boolean viewTreeContainsText(View root, String expectedText) {
if (root instanceof TextView) {
CharSequence text = ((TextView) root).getText();