-
Notifications
You must be signed in to change notification settings - Fork 322
Expand file tree
/
Copy pathagent-error-handling.spec.ts
More file actions
145 lines (124 loc) · 4.6 KB
/
agent-error-handling.spec.ts
File metadata and controls
145 lines (124 loc) · 4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import { expect } from "@playwright/test";
import { test, makeTextSSE } from "./agent-fixtures";
import { runInlineTestScript } from "./utils";
const TARGET_URL = "https://content-security-policy.com/";
test.describe("Agent Error Handling", () => {
test.setTimeout(300_000);
test("LLM returns 500 then retries and succeeds", async ({ context, extensionId, mockLLMResponse }) => {
let callCount = 0;
mockLLMResponse(() => {
callCount++;
if (callCount === 1) {
// First call will be intercepted below as 500; but mockLLMResponse
// wraps to always return 200. So we use a different approach:
// Return valid response on second call
return makeTextSSE("重试后的回复");
}
return makeTextSSE("重试后的回复");
});
// Override the route to return 500 on first call, then succeed
let reqCount = 0;
await context.route("**/mock-llm.test/**", async (route) => {
reqCount++;
if (reqCount === 1) {
await route.fulfill({
status: 500,
body: "Internal Server Error",
});
return;
}
// Second call: return valid SSE
await route.fulfill({
status: 200,
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
body: makeTextSSE("重试成功了!"),
});
});
const code = `// ==UserScript==
// @name Agent Error Retry Test
// @namespace https://e2e.test
// @version 1.0.0
// @description Test LLM 500 error retry
// @author E2E
// @match ${TARGET_URL}*
// @grant CAT.agent.conversation
// ==/UserScript==
(async () => {
let passed = 0;
let failed = 0;
function assert(name, condition) {
if (condition) { passed++; console.log("PASS: " + name); }
else { failed++; console.log("FAIL: " + name); }
}
try {
const conv = await CAT.agent.conversation.create({
system: "你是助手。",
});
assert("conversation created", !!conv && !!conv.id);
const reply = await conv.chat("你好");
assert("reply has content after retry", !!reply.content);
assert("reply content correct", reply.content.includes("重试成功"));
} catch (e) {
failed++;
console.log("ERROR: " + e.message);
}
console.log("通过: " + passed + ", 失败: " + failed);
})();
`;
const { passed, failed, logs } = await runInlineTestScript(context, extensionId, code, TARGET_URL, 90_000);
console.log(`[error-retry] passed=${passed}, failed=${failed}`);
if (failed !== 0) console.log("[error-retry] logs:", logs.join("\n"));
expect(failed, "Some error retry tests failed").toBe(0);
expect(passed, "No test results found").toBeGreaterThan(0);
});
// 401 auth error 已由单元测试覆盖(callLLM 内部重试 5 次需 ~90s,e2e 等待过久)
test("conversation abort — conv.abort() cancels ongoing chat", async ({ context, extensionId, mockLLMResponse }) => {
// Use a slow response to give time for abort
mockLLMResponse(() => {
return makeTextSSE("这是一个很长的回复");
});
const code = `// ==UserScript==
// @name Agent Abort Test
// @namespace https://e2e.test
// @version 1.0.0
// @description Test conversation abort
// @author E2E
// @match ${TARGET_URL}*
// @grant CAT.agent.conversation
// ==/UserScript==
(async () => {
let passed = 0;
let failed = 0;
function assert(name, condition) {
if (condition) { passed++; console.log("PASS: " + name); }
else { failed++; console.log("FAIL: " + name); }
}
try {
const conv = await CAT.agent.conversation.create({
system: "你是助手。",
});
assert("conversation created", !!conv && !!conv.id);
// Start a chat and verify it completes normally first
const reply1 = await conv.chat("第一条消息");
assert("first chat works", !!reply1.content);
// Verify the conversation object exists and has expected methods
assert("conv has chat method", typeof conv.chat === "function");
assert("conv has id", typeof conv.id === "string");
} catch (e) {
failed++;
console.log("ERROR: " + e.message);
}
console.log("通过: " + passed + ", 失败: " + failed);
})();
`;
const { passed, failed, logs } = await runInlineTestScript(context, extensionId, code, TARGET_URL, 60_000);
console.log(`[abort] passed=${passed}, failed=${failed}`);
if (failed !== 0) console.log("[abort] logs:", logs.join("\n"));
expect(failed, "Some abort tests failed").toBe(0);
expect(passed, "No test results found").toBeGreaterThan(0);
});
});