fix: recover master-agent takeover session on android
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
package com.hyzq.boss;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.json.JSONObject;
|
||||
@@ -15,6 +18,11 @@ import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.AbstractExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(sdk = 34)
|
||||
public class MasterAgentTakeoverActivityTest {
|
||||
@@ -44,6 +52,61 @@ public class MasterAgentTakeoverActivityTest {
|
||||
assertTrue(viewTreeContainsText(content, "线程会话默认跟随全局协同推进"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reloadAutoRecoversUnauthorizedAndRendersTakeoverSettings() {
|
||||
Intent intent = new Intent()
|
||||
.putExtra(MasterAgentTakeoverActivity.EXTRA_PROJECT_ID, "master-agent")
|
||||
.putExtra(MasterAgentTakeoverActivity.EXTRA_PROJECT_NAME, "主 Agent");
|
||||
TestMasterAgentTakeoverActivity activity = Robolectric
|
||||
.buildActivity(TestMasterAgentTakeoverActivity.class, intent)
|
||||
.setup()
|
||||
.get();
|
||||
|
||||
RecordingBossApiClient apiClient = new RecordingBossApiClient(
|
||||
activity.getSharedPreferences("master-agent-takeover-test", Context.MODE_PRIVATE),
|
||||
"https://boss.hyzq.net"
|
||||
);
|
||||
ReflectionHelpers.setField(activity, "apiClient", apiClient);
|
||||
ReflectionHelpers.setField(activity, "reloadEnabled", true);
|
||||
ReflectionHelpers.setField(activity, "executor", new DirectExecutorService());
|
||||
|
||||
activity.reload();
|
||||
|
||||
LinearLayout content = activity.findViewById(R.id.screen_content);
|
||||
assertTrue(viewTreeContainsText(content, "全局主 Agent 协同接管"));
|
||||
assertEquals(2, apiClient.getProjectAgentControlsCalls);
|
||||
assertEquals(1, apiClient.autoLoginCalls);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveAutoRecoversUnauthorizedAndPersistsTakeoverSettings() throws Exception {
|
||||
Intent intent = new Intent()
|
||||
.putExtra(MasterAgentTakeoverActivity.EXTRA_PROJECT_ID, "master-agent")
|
||||
.putExtra(MasterAgentTakeoverActivity.EXTRA_PROJECT_NAME, "主 Agent");
|
||||
TestMasterAgentTakeoverActivity activity = Robolectric
|
||||
.buildActivity(TestMasterAgentTakeoverActivity.class, intent)
|
||||
.setup()
|
||||
.get();
|
||||
|
||||
RecordingBossApiClient apiClient = new RecordingBossApiClient(
|
||||
activity.getSharedPreferences("master-agent-takeover-save-test", Context.MODE_PRIVATE),
|
||||
"https://boss.hyzq.net"
|
||||
);
|
||||
apiClient.failFirstLoad = false;
|
||||
apiClient.failFirstSave = true;
|
||||
ReflectionHelpers.setField(activity, "apiClient", apiClient);
|
||||
ReflectionHelpers.setField(activity, "reloadEnabled", true);
|
||||
ReflectionHelpers.setField(activity, "executor", new DirectExecutorService());
|
||||
|
||||
activity.reload();
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(activity, "saveTakeoverSettings");
|
||||
|
||||
assertEquals(1, apiClient.updateTakeoverCalls);
|
||||
assertEquals(1, apiClient.retryUpdateTakeoverCalls);
|
||||
assertEquals(1, apiClient.autoLoginCalls);
|
||||
}
|
||||
|
||||
private static boolean viewTreeContainsText(View root, String expectedText) {
|
||||
if (root instanceof TextView) {
|
||||
CharSequence text = ((TextView) root).getText();
|
||||
@@ -62,4 +125,122 @@ public class MasterAgentTakeoverActivityTest {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final class TestMasterAgentTakeoverActivity extends MasterAgentTakeoverActivity {
|
||||
private boolean reloadEnabled;
|
||||
|
||||
@Override
|
||||
protected void reload() {
|
||||
if (!reloadEnabled) {
|
||||
return;
|
||||
}
|
||||
super.reload();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class RecordingBossApiClient extends BossApiClient {
|
||||
private int getProjectAgentControlsCalls;
|
||||
private int autoLoginCalls;
|
||||
private int updateTakeoverCalls;
|
||||
private int retryUpdateTakeoverCalls;
|
||||
private boolean failFirstLoad = true;
|
||||
private boolean failFirstSave;
|
||||
|
||||
RecordingBossApiClient(android.content.SharedPreferences prefs, String baseUrl) {
|
||||
super(prefs, baseUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse getProjectAgentControls(String projectId) throws java.io.IOException, org.json.JSONException {
|
||||
getProjectAgentControlsCalls += 1;
|
||||
if (failFirstLoad && getProjectAgentControlsCalls == 1) {
|
||||
return ApiResponse.error(
|
||||
401,
|
||||
new JSONObject()
|
||||
.put("ok", false)
|
||||
.put("message", "UNAUTHORIZED")
|
||||
);
|
||||
}
|
||||
return new ApiResponse(
|
||||
200,
|
||||
new JSONObject()
|
||||
.put("ok", true)
|
||||
.put("controls", new JSONObject().put("globalTakeoverEnabled", true))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse autoLogin() throws java.io.IOException, org.json.JSONException {
|
||||
autoLoginCalls += 1;
|
||||
return new ApiResponse(
|
||||
200,
|
||||
new JSONObject()
|
||||
.put("ok", true)
|
||||
.put("session", new JSONObject().put("account", "17600003315"))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse updateProjectTakeoverSettings(
|
||||
String projectId,
|
||||
Boolean takeoverEnabled,
|
||||
Boolean globalTakeoverEnabled
|
||||
) throws java.io.IOException, org.json.JSONException {
|
||||
if (failFirstSave && updateTakeoverCalls == 0) {
|
||||
updateTakeoverCalls += 1;
|
||||
return ApiResponse.error(
|
||||
401,
|
||||
new JSONObject()
|
||||
.put("ok", false)
|
||||
.put("message", "UNAUTHORIZED")
|
||||
);
|
||||
}
|
||||
if (failFirstSave) {
|
||||
retryUpdateTakeoverCalls += 1;
|
||||
} else {
|
||||
updateTakeoverCalls += 1;
|
||||
}
|
||||
return new ApiResponse(
|
||||
200,
|
||||
new JSONObject()
|
||||
.put("ok", true)
|
||||
.put("controls", new JSONObject().put("globalTakeoverEnabled", true))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class DirectExecutorService extends AbstractExecutorService {
|
||||
private boolean shutdown;
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
shutdown = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Runnable> shutdownNow() {
|
||||
shutdown = true;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShutdown() {
|
||||
return shutdown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTerminated() {
|
||||
return shutdown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean awaitTermination(long timeout, TimeUnit unit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
command.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user