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
|
import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import type { ToolCall } from "../reducer";
import { ToolCallCard, contentText, toolContentText } from "./ToolCallCard";
function call(overrides: Partial<ToolCall>): ToolCall {
return {
toolCallId: "c1",
title: "A tool call",
toolKind: "other",
status: "completed",
contents: [],
locations: [],
...overrides,
};
}
describe("ToolCallCard", () => {
it("renders execute output verbatim in a monospace block", () => {
const { container } = render(
<ToolCallCard
call={call({
toolKind: "execute",
contents: [
{
type: "content",
content: { type: "text", text: "* main\n remote/origin" },
},
],
})}
/>,
);
const output = container.querySelector("pre.tool-output");
expect(output).not.toBeNull();
// Verbatim: the "* " prefix must not have become a markdown list.
expect(output?.textContent).toBe("* main\n remote/origin");
expect(container.querySelector("ul li")).toBeNull();
});
it("renders backticked commands in the title as monospace code", () => {
const { container } = render(
<ToolCallCard
call={call({ toolKind: "execute", title: "Run `ls .memory/`" })}
/>,
);
const code = container.querySelector(".tool-title code.inline-code");
expect(code?.textContent).toBe("ls .memory/");
});
it("renders non-execute text content as markdown", () => {
const { container } = render(
<ToolCallCard
call={call({
toolKind: "read",
contents: [
{
type: "content",
content: { type: "text", text: "**bold** result" },
},
],
})}
/>,
);
expect(container.querySelector("pre.tool-output")).toBeNull();
expect(screen.getByText("bold")).toBeDefined();
});
});
describe("toolContentText", () => {
it("returns the text of content blocks", () => {
expect(
contentText({ type: "content", content: { type: "text", text: "hi" } }),
).toBe("hi");
});
it("flattens a diff into labelled path, old and new sections", () => {
expect(
contentText({ type: "diff", path: "a.go", oldText: "x", newText: "y" }),
).toBe("Path: a.go\n\nOld:\nx\n\nNew:\ny");
});
it("omits diff sections that are absent", () => {
expect(contentText({ type: "diff", path: "a.go", newText: "y" })).toBe(
"Path: a.go\n\nNew:\ny",
);
});
it("ignores terminal blocks and joins the rest with blank lines", () => {
expect(
toolContentText([
{ type: "terminal", terminalId: "t1" },
{ type: "content", content: { type: "text", text: "one" } },
{ type: "content", content: { type: "text", text: "" } },
{ type: "content", content: { type: "text", text: "two" } },
]),
).toBe("one\n\ntwo");
});
it("hides the copy button when the call has no textual content", () => {
render(
<ToolCallCard
call={call({ contents: [{ type: "terminal", terminalId: "t1" }] })}
/>,
);
expect(screen.queryByLabelText("Copy tool output")).toBeNull();
});
});
|