126 lines
3.6 KiB
TypeScript
126 lines
3.6 KiB
TypeScript
import type { Page } from "@playwright/test";
|
|
|
|
type MockAgentApiOptions = {
|
|
model?: {
|
|
id: string;
|
|
label: string;
|
|
description: string;
|
|
icon: "bolt" | "sparkle";
|
|
};
|
|
sessions?: Array<Record<string, unknown>>;
|
|
};
|
|
|
|
export async function mockAgentApi(page: Page, options: MockAgentApiOptions = {}) {
|
|
const model = options.model ?? {
|
|
id: "test/model",
|
|
label: "测试模型",
|
|
description: "Playwright 浏览器测试",
|
|
icon: "bolt" as const
|
|
};
|
|
const triggeredSessions = new Map<string, { sessionId: string; triggerId: string }>();
|
|
await page.route("**/api/v1/agent/chat/**", async (route) => {
|
|
const pathname = new URL(route.request().url()).pathname;
|
|
|
|
if (pathname.endsWith("/session") && route.request().method() === "POST") {
|
|
const body = route.request().postDataJSON() as {
|
|
trigger_context?: { trigger_id?: string };
|
|
};
|
|
const triggerId = body.trigger_context?.trigger_id;
|
|
const existing = triggerId ? triggeredSessions.get(triggerId) : undefined;
|
|
const sessionId = existing?.sessionId ?? `browser-session-${triggeredSessions.size + 1}`;
|
|
if (triggerId && !existing) triggeredSessions.set(triggerId, { sessionId, triggerId });
|
|
await route.fulfill({
|
|
status: existing ? 200 : 201,
|
|
json: {
|
|
session_id: sessionId,
|
|
title: "水质投诉事件调查",
|
|
status: "active",
|
|
created_at: "2026-09-22T02:00:00Z",
|
|
updated_at: "2026-09-22T02:00:00Z",
|
|
created: !existing,
|
|
event_duplicate: Boolean(existing),
|
|
trigger_id: triggerId
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
const sessionMatch = pathname.match(/\/session\/([^/]+)$/);
|
|
if (sessionMatch && route.request().method() === "GET") {
|
|
await route.fulfill({
|
|
json: {
|
|
id: sessionMatch[1],
|
|
session_id: sessionMatch[1],
|
|
title: "水质投诉事件调查",
|
|
status: "active",
|
|
created_at: "2026-09-22T02:00:00Z",
|
|
updated_at: "2026-09-22T02:00:00Z",
|
|
messages: [],
|
|
is_streaming: false
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (pathname.endsWith("/stream")) {
|
|
await route.fulfill({
|
|
status: 200,
|
|
headers: {
|
|
"Cache-Control": "no-cache",
|
|
"Content-Type": "text/event-stream",
|
|
"X-Vercel-AI-UI-Message-Stream": "v1"
|
|
},
|
|
body: [
|
|
{ type: "start", messageId: "assistant-browser-test" },
|
|
{ type: "text-start", id: "answer" },
|
|
{ type: "text-delta", id: "answer", delta: "已收到工况汇总请求。" },
|
|
{ type: "text-end", id: "answer" },
|
|
{ type: "finish", finishReason: "stop" }
|
|
]
|
|
.map((part) => `data: ${JSON.stringify(part)}\n\n`)
|
|
.join("")
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (pathname.endsWith("/sessions")) {
|
|
await route.fulfill({ json: { sessions: options.sessions ?? [] } });
|
|
return;
|
|
}
|
|
|
|
if (pathname.endsWith("/models")) {
|
|
await route.fulfill({
|
|
json: {
|
|
default_model: model.id,
|
|
models: [model]
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (pathname.endsWith("/ui-registry")) {
|
|
await route.fulfill({
|
|
json: {
|
|
schema_version: "agent-ui-registry@1",
|
|
chart_grammars: [],
|
|
components: [],
|
|
actions: []
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (pathname.endsWith("/frontend-action-registry")) {
|
|
await route.fulfill({
|
|
json: {
|
|
schema_version: "frontend-action-registry@1",
|
|
actions: []
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
await route.fulfill({ json: {} });
|
|
});
|
|
}
|