feat: add conversation selection mode and swipe tabs
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
package com.hyzq.boss;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(sdk = 34)
|
||||
public class MainActivityConversationSelectionTest {
|
||||
@Test
|
||||
public void conversationsSelectionMode_requiresAtLeastTwoSelectionsForGroupChat() throws Exception {
|
||||
MainActivity activity = Robolectric.buildActivity(MainActivity.class).setup().get();
|
||||
ReflectionHelpers.setField(activity, "conversationsData", buildConversations());
|
||||
ReflectionHelpers.callInstanceMethod(activity, "showContent");
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(activity, "enterConversationSelectionMode");
|
||||
assertTrue(ReflectionHelpers.getField(activity, "conversationSelectionMode"));
|
||||
|
||||
LinearLayout content = activity.findViewById(R.id.screen_content);
|
||||
assertTrue(viewTreeContainsText(content, "发起群聊"));
|
||||
assertTrue(viewTreeContainsText(content, "至少选择 2 个线程"));
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(activity, "toggleConversationSelection",
|
||||
ReflectionHelpers.ClassParameter.from(String.class, "thread-1"));
|
||||
content = activity.findViewById(R.id.screen_content);
|
||||
assertTrue(viewTreeContainsText(content, "已选 1 个线程"));
|
||||
assertTrue(viewTreeContainsText(content, "至少选择 2 个线程"));
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(activity, "toggleConversationSelection",
|
||||
ReflectionHelpers.ClassParameter.from(String.class, "thread-2"));
|
||||
content = activity.findViewById(R.id.screen_content);
|
||||
assertTrue(viewTreeContainsText(content, "已选 2 个线程"));
|
||||
assertFalse(viewTreeContainsText(content, "至少选择 2 个线程"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectionModeRowsRenderSelectorInTrailingArea() throws Exception {
|
||||
MainActivity activity = Robolectric.buildActivity(MainActivity.class).setup().get();
|
||||
ReflectionHelpers.setField(activity, "conversationsData", buildConversations());
|
||||
ReflectionHelpers.callInstanceMethod(activity, "showContent");
|
||||
ReflectionHelpers.callInstanceMethod(activity, "enterConversationSelectionMode");
|
||||
|
||||
LinearLayout content = activity.findViewById(R.id.screen_content);
|
||||
View row = content.getChildAt(3);
|
||||
assertTrue("多选模式应显示单选圆点", viewTreeContainsContentDescription(row, "未选中会话"));
|
||||
}
|
||||
|
||||
private static JSONArray buildConversations() throws Exception {
|
||||
return new JSONArray()
|
||||
.put(new JSONObject()
|
||||
.put("projectId", "thread-1")
|
||||
.put("projectTitle", "Boss 移动控制台")
|
||||
.put("threadTitle", "Boss 移动控制台")
|
||||
.put("folderLabel", "Boss")
|
||||
.put("lastMessagePreview", "线程链路正常")
|
||||
.put("latestReplyLabel", "09:41")
|
||||
.put("conversationType", "single_device"))
|
||||
.put(new JSONObject()
|
||||
.put("projectId", "thread-2")
|
||||
.put("projectTitle", "硬件审计协作")
|
||||
.put("threadTitle", "硬件审计协作")
|
||||
.put("folderLabel", "Mac Studio")
|
||||
.put("lastMessagePreview", "检查摄像头供电链路")
|
||||
.put("latestReplyLabel", "09:42")
|
||||
.put("conversationType", "single_device"));
|
||||
}
|
||||
|
||||
private static boolean viewTreeContainsText(View root, String expectedText) {
|
||||
if (root instanceof TextView) {
|
||||
CharSequence text = ((TextView) root).getText();
|
||||
if (expectedText.contentEquals(text)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!(root instanceof LinearLayout)) {
|
||||
return false;
|
||||
}
|
||||
LinearLayout group = (LinearLayout) root;
|
||||
for (int index = 0; index < group.getChildCount(); index += 1) {
|
||||
if (viewTreeContainsText(group.getChildAt(index), expectedText)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean viewTreeContainsContentDescription(View root, String expectedText) {
|
||||
CharSequence description = root.getContentDescription();
|
||||
if (expectedText.contentEquals(description)) {
|
||||
return true;
|
||||
}
|
||||
if (!(root instanceof LinearLayout)) {
|
||||
return false;
|
||||
}
|
||||
LinearLayout group = (LinearLayout) root;
|
||||
for (int index = 0; index < group.getChildCount(); index += 1) {
|
||||
if (viewTreeContainsContentDescription(group.getChildAt(index), expectedText)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.hyzq.boss;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(sdk = 34)
|
||||
public class MainActivitySwipeNavigationTest {
|
||||
@Test
|
||||
public void horizontalSwipeMovesBetweenRootTabs() {
|
||||
MainActivity activity = Robolectric.buildActivity(MainActivity.class).setup().get();
|
||||
ReflectionHelpers.callInstanceMethod(activity, "showContent");
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(activity, "handleHorizontalPageSwipe",
|
||||
ReflectionHelpers.ClassParameter.from(int.class, 1));
|
||||
assertEquals("devices", ReflectionHelpers.getField(activity, "activeTab"));
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(activity, "handleHorizontalPageSwipe",
|
||||
ReflectionHelpers.ClassParameter.from(int.class, 1));
|
||||
assertEquals("me", ReflectionHelpers.getField(activity, "activeTab"));
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(activity, "handleHorizontalPageSwipe",
|
||||
ReflectionHelpers.ClassParameter.from(int.class, -1));
|
||||
assertEquals("devices", ReflectionHelpers.getField(activity, "activeTab"));
|
||||
}
|
||||
}
|
||||
@@ -62,9 +62,24 @@ public class WechatSurfaceMapperConversationStatusTest {
|
||||
|
||||
WechatSurfaceMapper.ConversationRow row = WechatSurfaceMapper.toConversationRow(item);
|
||||
|
||||
assertNull(row.contextStatusLabel);
|
||||
assertNull(row.contextStatusLevel);
|
||||
assertEquals(-1, row.contextUsagePercent);
|
||||
assertEquals("上下文稳定", row.contextStatusLabel);
|
||||
assertEquals("safe", row.contextStatusLevel);
|
||||
assertEquals(0, row.contextUsagePercent);
|
||||
assertEquals(true, row.contextIndicatorVisible);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toConversationRow_usesSafeContextDefaultsWhenIndicatorMissing() {
|
||||
JSONObject item = new StubJSONObject()
|
||||
.withString("threadTitle", "北区试产线回归")
|
||||
.withInt("activityIconCount", 0);
|
||||
|
||||
WechatSurfaceMapper.ConversationRow row = WechatSurfaceMapper.toConversationRow(item);
|
||||
|
||||
assertEquals("上下文稳定", row.contextStatusLabel);
|
||||
assertEquals("safe", row.contextStatusLevel);
|
||||
assertEquals(0, row.contextUsagePercent);
|
||||
assertEquals(true, row.contextIndicatorVisible);
|
||||
}
|
||||
|
||||
private static final class StubJSONObject extends JSONObject {
|
||||
|
||||
@@ -8,13 +8,23 @@ import org.junit.Test;
|
||||
|
||||
public class WechatSurfaceMapperTopActionTest {
|
||||
@Test
|
||||
public void rootTopAction_usesPlusForConversations() {
|
||||
WechatSurfaceMapper.RootTopAction action = WechatSurfaceMapper.rootTopAction("conversations", false);
|
||||
public void rootTopAction_usesSelectionForConversations() {
|
||||
WechatSurfaceMapper.RootTopAction action = WechatSurfaceMapper.rootTopAction("conversations", false, false);
|
||||
|
||||
assertEquals("+", action.label);
|
||||
assertEquals("选择", action.label);
|
||||
assertFalse(action.primaryStyle);
|
||||
assertTrue(action.compactStyle);
|
||||
assertEquals("create_group_chat", action.actionKey);
|
||||
assertFalse(action.compactStyle);
|
||||
assertEquals("select_conversations", action.actionKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rootTopAction_usesCancelDuringConversationSelection() {
|
||||
WechatSurfaceMapper.RootTopAction action = WechatSurfaceMapper.rootTopAction("conversations", false, true);
|
||||
|
||||
assertEquals("取消", action.label);
|
||||
assertFalse(action.primaryStyle);
|
||||
assertFalse(action.compactStyle);
|
||||
assertEquals("cancel_select_conversations", action.actionKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user