mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-22 08:15:53 +00:00
test: Phase 2-4 — 添加 12 个测试文件 (+321 tests, 968 total)
Phase 2 (轻 Mock): envUtils, sleep/sequential, memoize, groupToolUses, dangerousPatterns, outputLimits Phase 3 (补全): zodToJsonSchema, PermissionMode, envValidation Phase 4 (工具模块): mcpStringUtils, destructiveCommandWarning, commandSemantics Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
152
src/utils/__tests__/groupToolUses.test.ts
Normal file
152
src/utils/__tests__/groupToolUses.test.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { applyGrouping } from "../groupToolUses";
|
||||
|
||||
// Helper: build minimal tool-use assistant message
|
||||
function makeToolUseMsg(
|
||||
uuid: string,
|
||||
messageId: string,
|
||||
toolUseId: string,
|
||||
toolName: string
|
||||
): any {
|
||||
return {
|
||||
type: "assistant",
|
||||
uuid,
|
||||
timestamp: Date.now(),
|
||||
message: {
|
||||
id: messageId,
|
||||
content: [{ type: "tool_use", id: toolUseId, name: toolName, input: {} }],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Helper: build minimal tool-result user message
|
||||
function makeToolResultMsg(uuid: string, toolUseId: string): any {
|
||||
return {
|
||||
type: "user",
|
||||
uuid,
|
||||
timestamp: Date.now(),
|
||||
message: {
|
||||
content: [{ type: "tool_result", tool_use_id: toolUseId, content: "ok" }],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Helper: build minimal text assistant message
|
||||
function makeTextMsg(uuid: string, text: string): any {
|
||||
return {
|
||||
type: "assistant",
|
||||
uuid,
|
||||
timestamp: Date.now(),
|
||||
message: { id: `msg-${uuid}`, content: [{ type: "text", text }] },
|
||||
};
|
||||
}
|
||||
|
||||
// Minimal tool definitions
|
||||
const groupableTool: any = { name: "Grep", renderGroupedToolUse: true };
|
||||
const nonGroupableTool: any = { name: "Bash", renderGroupedToolUse: undefined };
|
||||
|
||||
// ─── applyGrouping ────────────────────────────────────────────────────
|
||||
|
||||
describe("applyGrouping", () => {
|
||||
test("returns all messages in verbose mode", () => {
|
||||
const msgs = [
|
||||
makeToolUseMsg("u1", "m1", "tu1", "Grep"),
|
||||
makeToolUseMsg("u2", "m1", "tu2", "Grep"),
|
||||
];
|
||||
const result = applyGrouping(msgs, [groupableTool], true);
|
||||
expect(result.messages).toHaveLength(2);
|
||||
expect(result.messages).toBe(msgs); // same reference
|
||||
});
|
||||
|
||||
test("does not group when tool lacks renderGroupedToolUse", () => {
|
||||
const msgs = [
|
||||
makeToolUseMsg("u1", "m1", "tu1", "Bash"),
|
||||
makeToolUseMsg("u2", "m1", "tu2", "Bash"),
|
||||
];
|
||||
const result = applyGrouping(msgs, [nonGroupableTool]);
|
||||
expect(result.messages).toHaveLength(2);
|
||||
// Both messages should pass through as-is
|
||||
expect(result.messages[0]).toBe(msgs[0]);
|
||||
});
|
||||
|
||||
test("does not group single tool use", () => {
|
||||
const msgs = [makeToolUseMsg("u1", "m1", "tu1", "Grep")];
|
||||
const result = applyGrouping(msgs, [groupableTool]);
|
||||
expect(result.messages).toHaveLength(1);
|
||||
expect((result.messages[0] as any).type).toBe("assistant");
|
||||
});
|
||||
|
||||
test("groups 2+ tool uses of same type from same message", () => {
|
||||
const msgs = [
|
||||
makeToolUseMsg("u1", "m1", "tu1", "Grep"),
|
||||
makeToolUseMsg("u2", "m1", "tu2", "Grep"),
|
||||
makeToolUseMsg("u3", "m1", "tu3", "Grep"),
|
||||
];
|
||||
const result = applyGrouping(msgs, [groupableTool]);
|
||||
expect(result.messages).toHaveLength(1);
|
||||
const grouped = result.messages[0] as any;
|
||||
expect(grouped.type).toBe("grouped_tool_use");
|
||||
expect(grouped.toolName).toBe("Grep");
|
||||
expect(grouped.messages).toHaveLength(3);
|
||||
});
|
||||
|
||||
test("does not group tool uses from different messages", () => {
|
||||
const msgs = [
|
||||
makeToolUseMsg("u1", "m1", "tu1", "Grep"),
|
||||
makeToolUseMsg("u2", "m2", "tu2", "Grep"),
|
||||
];
|
||||
const result = applyGrouping(msgs, [groupableTool]);
|
||||
// Each belongs to a different message.id, so no group (< 2 per group)
|
||||
expect(result.messages).toHaveLength(2);
|
||||
});
|
||||
|
||||
test("collects tool results for grouped uses", () => {
|
||||
const msgs = [
|
||||
makeToolUseMsg("u1", "m1", "tu1", "Grep"),
|
||||
makeToolUseMsg("u2", "m1", "tu2", "Grep"),
|
||||
makeToolResultMsg("u3", "tu1"),
|
||||
makeToolResultMsg("u4", "tu2"),
|
||||
];
|
||||
const result = applyGrouping(msgs, [groupableTool]);
|
||||
const grouped = result.messages[0] as any;
|
||||
expect(grouped.type).toBe("grouped_tool_use");
|
||||
expect(grouped.results).toHaveLength(2);
|
||||
});
|
||||
|
||||
test("skips user messages whose tool_results are all grouped", () => {
|
||||
const msgs = [
|
||||
makeToolUseMsg("u1", "m1", "tu1", "Grep"),
|
||||
makeToolUseMsg("u2", "m1", "tu2", "Grep"),
|
||||
makeToolResultMsg("u3", "tu1"),
|
||||
makeToolResultMsg("u4", "tu2"),
|
||||
];
|
||||
const result = applyGrouping(msgs, [groupableTool]);
|
||||
// Only the grouped message should remain — result messages are consumed
|
||||
expect(result.messages).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("preserves non-grouped messages alongside groups", () => {
|
||||
const msgs = [
|
||||
makeTextMsg("u0", "thinking..."),
|
||||
makeToolUseMsg("u1", "m1", "tu1", "Grep"),
|
||||
makeToolUseMsg("u2", "m1", "tu2", "Grep"),
|
||||
makeTextMsg("u3", "done"),
|
||||
];
|
||||
const result = applyGrouping(msgs, [groupableTool]);
|
||||
expect(result.messages).toHaveLength(3); // text + grouped + text
|
||||
expect((result.messages[0] as any).type).toBe("assistant");
|
||||
expect((result.messages[1] as any).type).toBe("grouped_tool_use");
|
||||
expect((result.messages[2] as any).type).toBe("assistant");
|
||||
});
|
||||
|
||||
test("handles empty messages array", () => {
|
||||
const result = applyGrouping([], [groupableTool]);
|
||||
expect(result.messages).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("handles empty tools array", () => {
|
||||
const msgs = [makeToolUseMsg("u1", "m1", "tu1", "Grep")];
|
||||
const result = applyGrouping(msgs, []);
|
||||
expect(result.messages).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user