Refresh conversation info surfaces in realtime

This commit is contained in:
kris
2026-04-07 15:49:18 +08:00
parent 45329159f5
commit a42e5b75dc
9 changed files with 485 additions and 6 deletions

View File

@@ -19,6 +19,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowDialog;
import org.robolectric.util.ReflectionHelpers;
@@ -117,6 +118,70 @@ public class ConversationFolderActivityTest {
assertEquals(1, countTextOccurrences(content, "目标线程"));
}
@Test
public void matchingProjectMessagesUpdatedEventTriggersReload() throws Exception {
Intent intent = new Intent()
.putExtra(ConversationFolderActivity.EXTRA_FOLDER_KEY, "talking")
.putExtra(ConversationFolderActivity.EXTRA_FOLDER_NAME, "Talking");
TestConversationFolderActivity activity = Robolectric
.buildActivity(TestConversationFolderActivity.class, intent)
.setup()
.resume()
.get();
ReflectionHelpers.callInstanceMethod(
activity,
"renderFolder",
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildFolderPayload())
);
activity.reloadEnabled = true;
activity.reloadCount = 0;
ReflectionHelpers.callInstanceMethod(
activity,
"handleRealtimeEvent",
ReflectionHelpers.ClassParameter.from(
BossRealtimeEvent.class,
new BossRealtimeEvent("project.messages.updated", new JSONObject().put("projectId", "project-2"))
)
);
Shadows.shadowOf(activity.getMainLooper()).idle();
assertEquals(1, activity.reloadCount);
}
@Test
public void unrelatedConversationEventDoesNotTriggerReload() throws Exception {
Intent intent = new Intent()
.putExtra(ConversationFolderActivity.EXTRA_FOLDER_KEY, "talking")
.putExtra(ConversationFolderActivity.EXTRA_FOLDER_NAME, "Talking");
TestConversationFolderActivity activity = Robolectric
.buildActivity(TestConversationFolderActivity.class, intent)
.setup()
.resume()
.get();
ReflectionHelpers.callInstanceMethod(
activity,
"renderFolder",
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildFolderPayload())
);
activity.reloadEnabled = true;
activity.reloadCount = 0;
ReflectionHelpers.callInstanceMethod(
activity,
"handleRealtimeEvent",
ReflectionHelpers.ClassParameter.from(
BossRealtimeEvent.class,
new BossRealtimeEvent("conversation.updated", new JSONObject().put("projectId", "project-9"))
)
);
Shadows.shadowOf(activity.getMainLooper()).idle();
assertEquals(0, activity.reloadCount);
}
private static JSONObject buildFolderPayload() throws Exception {
JSONArray threads = new JSONArray()
.put(new JSONObject()
@@ -182,9 +247,17 @@ public class ConversationFolderActivityTest {
}
public static class TestConversationFolderActivity extends ConversationFolderActivity {
private boolean reloadEnabled;
private int reloadCount;
@Override
protected void reload() {
// Tests render the folder state directly.
if (!reloadEnabled) {
return;
}
reloadCount += 1;
replaceContent(BossUi.buildEmptyCard(this, "test reload"));
setRefreshing(false);
}
}
}

View File

@@ -187,6 +187,7 @@ public class ConversationInfoActivityTest {
);
ReflectionHelpers.setField(activity, "apiClient", apiClient);
ReflectionHelpers.setField(activity, "reloadEnabled", true);
ReflectionHelpers.setField(activity, "delegateReloadToSuper", true);
ReflectionHelpers.setField(activity, "executor", new DirectExecutorService());
activity.reload();
@@ -217,6 +218,7 @@ public class ConversationInfoActivityTest {
apiClient.failFirstSave = true;
ReflectionHelpers.setField(activity, "apiClient", apiClient);
ReflectionHelpers.setField(activity, "reloadEnabled", true);
ReflectionHelpers.setField(activity, "delegateReloadToSuper", true);
ReflectionHelpers.setField(activity, "executor", new DirectExecutorService());
activity.reload();
@@ -233,6 +235,58 @@ public class ConversationInfoActivityTest {
assertEquals(1, apiClient.autoLoginCalls);
}
@Test
public void matchingProjectMessagesUpdatedEventTriggersReload() throws Exception {
Intent intent = new Intent()
.putExtra(ConversationInfoActivity.EXTRA_PROJECT_ID, "project-1")
.putExtra(ConversationInfoActivity.EXTRA_PROJECT_NAME, "北区试产线回归");
TestConversationInfoActivity activity = Robolectric
.buildActivity(TestConversationInfoActivity.class, intent)
.setup()
.resume()
.get();
activity.reloadEnabled = true;
activity.reloadCount = 0;
ReflectionHelpers.callInstanceMethod(
activity,
"handleRealtimeEvent",
ReflectionHelpers.ClassParameter.from(
BossRealtimeEvent.class,
new BossRealtimeEvent("project.messages.updated", new JSONObject().put("projectId", "project-1"))
)
);
ShadowLooper.shadowMainLooper().idle();
assertEquals(1, activity.reloadCount);
}
@Test
public void unrelatedConversationEventDoesNotTriggerReload() throws Exception {
Intent intent = new Intent()
.putExtra(ConversationInfoActivity.EXTRA_PROJECT_ID, "project-1")
.putExtra(ConversationInfoActivity.EXTRA_PROJECT_NAME, "北区试产线回归");
TestConversationInfoActivity activity = Robolectric
.buildActivity(TestConversationInfoActivity.class, intent)
.setup()
.resume()
.get();
activity.reloadEnabled = true;
activity.reloadCount = 0;
ReflectionHelpers.callInstanceMethod(
activity,
"handleRealtimeEvent",
ReflectionHelpers.ClassParameter.from(
BossRealtimeEvent.class,
new BossRealtimeEvent("conversation.updated", new JSONObject().put("projectId", "project-2"))
)
);
ShadowLooper.shadowMainLooper().idle();
assertEquals(0, activity.reloadCount);
}
private static JSONObject buildDetailPayload() throws Exception {
JSONObject threadMeta = new JSONObject()
.put("threadId", "thread-7")
@@ -341,13 +395,21 @@ public class ConversationInfoActivityTest {
public static class TestConversationInfoActivity extends ConversationInfoActivity {
private boolean reloadEnabled;
private boolean delegateReloadToSuper;
private int reloadCount;
@Override
protected void reload() {
if (!reloadEnabled) {
return;
}
super.reload();
reloadCount += 1;
if (delegateReloadToSuper) {
super.reload();
return;
}
replaceContent(BossUi.buildEmptyCard(this, "test reload"));
setRefreshing(false);
}
}

View File

@@ -286,6 +286,58 @@ public class GroupInfoActivityTest {
assertEquals("{\"lightDispatchReminderEnabled\":true}", connection.requestBody());
}
@Test
public void matchingConversationUpdatedEventTriggersReload() 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()
.resume()
.get();
activity.reloadEnabled = true;
activity.reloadCount = 0;
ReflectionHelpers.callInstanceMethod(
activity,
"handleRealtimeEvent",
ReflectionHelpers.ClassParameter.from(
BossRealtimeEvent.class,
new BossRealtimeEvent("conversation.updated", new JSONObject().put("projectId", "group-1"))
)
);
Shadows.shadowOf(Looper.getMainLooper()).idle();
assertEquals(1, activity.reloadCount);
}
@Test
public void unrelatedProjectMessagesEventDoesNotTriggerReload() 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()
.resume()
.get();
activity.reloadEnabled = true;
activity.reloadCount = 0;
ReflectionHelpers.callInstanceMethod(
activity,
"handleRealtimeEvent",
ReflectionHelpers.ClassParameter.from(
BossRealtimeEvent.class,
new BossRealtimeEvent("project.messages.updated", new JSONObject().put("projectId", "project-2"))
)
);
Shadows.shadowOf(Looper.getMainLooper()).idle();
assertEquals(0, activity.reloadCount);
}
private static JSONObject buildDetailPayload() throws Exception {
return buildDetailPayload(false);
}
@@ -425,9 +477,17 @@ public class GroupInfoActivityTest {
}
public static class TestGroupInfoActivity extends GroupInfoActivity {
private boolean reloadEnabled;
private int reloadCount;
@Override
protected void reload() {
// Tests render the lightweight info state directly.
if (!reloadEnabled) {
return;
}
reloadCount += 1;
replaceContent(BossUi.buildEmptyCard(this, "test reload"));
setRefreshing(false);
}
}