Files
paseo/packages/app/src/utils/tool-call-parsers.test.ts
T
Mohamed Boudra f073be0b98 feat(app): improve tool call sheet with word-level diff and better UX
- Add word-level highlighting using LCS algorithm for edit diffs
- Match diff colors to explorer sidebar (GitHub-style rgba backgrounds)
- Use discriminated union for tool call parsing (shell, edit, generic)
- Add horizontal scroll for bash/command output instead of wrapping
- Remove status badge from bottom sheet header
- Fix sheet snap points (60%/95%) and disable dynamic sizing
- Add min-width to diff viewer for full-width backgrounds

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-01-10 23:37:13 +07:00

161 lines
5.7 KiB
TypeScript

import { describe, test, expect } from "vitest";
import {
extractKeyValuePairs,
parseToolCallDisplay,
type ToolCallDisplay,
} from "./tool-call-parsers";
describe("tool-call-parsers - real runtime shapes", () => {
// Real data captured from Claude agent test: "shows the command inside pending tool calls"
// Run: npx vitest run claude-agent.test.ts -t "shows the command"
test("bash tool call - input shape", () => {
// REAL shape from Claude SDK timeline event (status: pending/completed)
const bashInput = {
command: "pwd",
description: "Print working directory",
};
const pairs = extractKeyValuePairs(bashInput);
expect(pairs).toContainEqual({ key: "command", value: "pwd" });
expect(pairs).toContainEqual({ key: "description", value: "Print working directory" });
});
test("bash tool call - output shape (completed)", () => {
// REAL shape from Claude SDK timeline event (status: completed)
// NOTE: output already has type: "command" discriminator!
const bashOutput = {
type: "command",
command: "pwd",
output: "/private/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/claude-agent-e2e-9tnmUm",
};
const pairs = extractKeyValuePairs(bashOutput);
expect(pairs).toContainEqual({ key: "type", value: "command" });
expect(pairs).toContainEqual({ key: "command", value: "pwd" });
expect(pairs).toContainEqual({ key: "output", value: expect.stringContaining("claude-agent") });
});
});
describe("parseToolCallDisplay", () => {
test("parses completed bash tool call into shell type", () => {
const input = { command: "pwd", description: "Print working directory" };
const result = { type: "command", command: "pwd", output: "/some/path" };
const display: ToolCallDisplay = parseToolCallDisplay(input, result);
expect(display.type).toBe("shell");
if (display.type === "shell") {
expect(display.command).toBe("pwd");
expect(display.output).toBe("/some/path");
}
});
test("parses pending bash tool call into shell type with empty output", () => {
// When tool is pending, we have input but no result yet
const input = { command: "pwd", description: "Print working directory" };
const result = undefined;
const display: ToolCallDisplay = parseToolCallDisplay(input, result);
expect(display.type).toBe("shell");
if (display.type === "shell") {
expect(display.command).toBe("pwd");
expect(display.output).toBe("");
}
});
test("handles command as array", () => {
const input = { command: ["git", "status"] };
const result = { type: "command", output: "On branch main" };
const display: ToolCallDisplay = parseToolCallDisplay(input, result);
expect(display.type).toBe("shell");
if (display.type === "shell") {
expect(display.command).toBe("git status");
expect(display.output).toBe("On branch main");
}
});
test("parses non-command tool call into generic type", () => {
const input = { file_path: "/some/file.txt" };
const result = { content: "file contents here", lineCount: 42 };
const display: ToolCallDisplay = parseToolCallDisplay(input, result);
expect(display.type).toBe("generic");
if (display.type === "generic") {
expect(display.input).toContainEqual({ key: "file_path", value: "/some/file.txt" });
expect(display.output).toContainEqual({ key: "content", value: "file contents here" });
expect(display.output).toContainEqual({ key: "lineCount", value: "42" });
}
});
test("handles file_write output as generic", () => {
const input = { file_path: "/some/file.txt", content: "new content" };
const result = { type: "file_write", filePath: "/some/file.txt" };
const display: ToolCallDisplay = parseToolCallDisplay(input, result);
expect(display.type).toBe("generic");
});
test("handles undefined input and result gracefully", () => {
const display: ToolCallDisplay = parseToolCallDisplay(undefined, undefined);
expect(display.type).toBe("generic");
if (display.type === "generic") {
expect(display.input).toEqual([]);
expect(display.output).toEqual([]);
}
});
test("parses edit tool call into edit type with old_string/new_string", () => {
const input = {
file_path: "/some/file.txt",
old_string: "const foo = 1;",
new_string: "const foo = 2;",
};
const result = {
type: "file_edit",
filePath: "/some/file.txt",
};
const display: ToolCallDisplay = parseToolCallDisplay(input, result);
expect(display.type).toBe("edit");
if (display.type === "edit") {
expect(display.filePath).toBe("/some/file.txt");
expect(display.oldString).toBe("const foo = 1;");
expect(display.newString).toBe("const foo = 2;");
}
});
test("parses edit tool call with old_str/new_str variants", () => {
const input = {
file_path: "/some/file.txt",
old_str: "line 1",
new_str: "line 2",
};
const result = undefined;
const display: ToolCallDisplay = parseToolCallDisplay(input, result);
expect(display.type).toBe("edit");
if (display.type === "edit") {
expect(display.filePath).toBe("/some/file.txt");
expect(display.oldString).toBe("line 1");
expect(display.newString).toBe("line 2");
}
});
test("parses pending edit tool call (no result yet)", () => {
const input = {
file_path: "/some/file.txt",
old_string: "old content",
new_string: "new content",
};
const display: ToolCallDisplay = parseToolCallDisplay(input, undefined);
expect(display.type).toBe("edit");
if (display.type === "edit") {
expect(display.filePath).toBe("/some/file.txt");
expect(display.oldString).toBe("old content");
expect(display.newString).toBe("new content");
}
});
});