deer-flow/frontend/tests/e2e/tool-call-details.spec.ts
blue 1ee93cd186
feat(frontend): add expandable generic tool details in debug mode (#5309)
* feat(frontend): add expandable generic tool details in debug mode

* fix: address tool call details review feedback

* fix: preserve existing ellipsis keys in tool previews

* fix(frontend): preserve tool preview property names

* fix(frontend): keep bounded tool previews structurally complete

* fix(frontend): avoid repeated array preview truncation markers

* fix(frontend): preserve precision in tool result previews

* fix(frontend): coalesce generated array tail markers
2026-09-12 09:16:37 +08:00

136 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { expect, test } from "@playwright/test";
import { mockLangGraphAPI } from "./utils/mock-api";
const threadId = "00000000-0000-0000-0000-000000004389";
for (const { debug, content, status, label } of [
{
debug: false,
content: "denied: " + "x".repeat(20000),
status: "error",
label: "Debug disabled",
},
{
debug: true,
content: "denied: " + "x".repeat(20000),
status: "error",
label: "bounded error",
},
{
debug: true,
content: '{"run_id":9223372036854775807,"ratio":0.1234567890123456789}',
status: "success",
label: "nested numeric precision",
},
{
debug: true,
content: "9223372036854775807",
status: "success",
label: "top-level numeric precision",
},
] as const) {
test(`generic tool details: ${label}`, async ({ page }) => {
await page.addInitScript((enabled) => {
localStorage.setItem(
"deerflow.local-settings",
JSON.stringify({
tokenUsage: {
headerTotal: true,
inlineMode: enabled ? "step_debug" : "per_turn",
},
}),
);
}, debug);
mockLangGraphAPI(page, {
threads: [
{
thread_id: threadId,
title: "Tool details",
messages: [
{ type: "human", id: "human", content: "Look up the run" },
{
type: "ai",
id: "ai-tool",
content: "",
tool_calls: [
{
id: "call-4389",
name: "mcp_lookup",
args: { run_id: "run-4389" },
},
],
},
{
type: "tool",
id: "tool-result",
tool_call_id: "call-4389",
status,
content,
},
{ type: "ai", id: "answer", content: "The lookup failed." },
],
},
],
});
// 默认 mock 关闭了 Token Usage这里启用入口但不提供任何调用统计。
await page.route("**/api/models", (route) =>
route.fulfill({ json: { models: [], token_usage: { enabled: true } } }),
);
await page.goto(`/workspace/chats/${threadId}`);
await expect(
page.getByText("The lookup failed.", { exact: true }),
).toBeVisible();
const trigger = page.getByRole("button", {
name: "Tool details: mcp_lookup (call-4389)",
exact: true,
});
if (!debug) {
await expect(trigger).toHaveCount(0);
return;
}
await expect(trigger).toHaveAttribute("aria-expanded", "false");
await expect(
page.getByRole("region", { name: "Input", exact: true }),
).toHaveCount(0);
await trigger.click();
await expect(
page.getByRole("region", { name: "Input", exact: true }),
).toContainText("run-4389");
await expect(
page.getByRole("region", { name: "Call ID", exact: true }),
).toContainText("call-4389");
const error = page.getByRole("region", {
name: status === "error" ? "Error" : "Result",
exact: true,
});
if (status === "success") {
expect(await error.locator("pre").textContent()).toBe(content);
await expect(
error.getByText("Preview truncated", { exact: false }),
).toHaveCount(0);
await page
.context()
.grantPermissions(["clipboard-read", "clipboard-write"]);
await error
.getByRole("button", { name: "Copy to clipboard: Result", exact: true })
.click();
await expect
.poll(() => page.evaluate(() => navigator.clipboard.readText()))
.toBe(content);
return;
}
await expect(error).toContainText("denied:");
await expect(error).toContainText("Preview truncated");
expect(
(await error.locator("pre").textContent())?.length,
).toBeLessThanOrEqual(12000);
await page.screenshot({
path: test.info().outputPath("tool-details.png"),
fullPage: true,
});
await trigger.click();
await expect(error).toHaveCount(0);
});
}