test: 添加一大堆测试文件

This commit is contained in:
claude-code-best
2026-04-02 20:28:08 +08:00
parent 6f5623b26c
commit ce29527a67
33 changed files with 3502 additions and 329 deletions

View File

@@ -1,201 +1,207 @@
import { describe, expect, test } from "bun:test";
import { describe, expect, test } from 'bun:test'
import {
buildTool,
toolMatchesName,
findToolByName,
getEmptyToolPermissionContext,
filterToolProgressMessages,
} from "../Tool";
} from '../Tool'
// Minimal tool definition for testing buildTool
function makeMinimalToolDef(overrides: Record<string, unknown> = {}) {
return {
name: "TestTool",
inputSchema: { type: "object" as const } as any,
name: 'TestTool',
inputSchema: { type: 'object' as const } as any,
maxResultSizeChars: 10000,
call: async () => ({ data: "ok" }),
description: async () => "A test tool",
prompt: async () => "test prompt",
mapToolResultToToolResultBlockParam: (content: unknown, toolUseID: string) => ({
type: "tool_result" as const,
call: async () => ({ data: 'ok' }),
description: async () => 'A test tool',
prompt: async () => 'test prompt',
mapToolResultToToolResultBlockParam: (
content: unknown,
toolUseID: string,
) => ({
type: 'tool_result' as const,
tool_use_id: toolUseID,
content: String(content),
}),
renderToolUseMessage: () => null,
...overrides,
};
}
}
describe("buildTool", () => {
test("fills in default isEnabled as true", () => {
const tool = buildTool(makeMinimalToolDef());
expect(tool.isEnabled()).toBe(true);
});
describe('buildTool', () => {
test('fills in default isEnabled as true', () => {
const tool = buildTool(makeMinimalToolDef())
expect(tool.isEnabled()).toBe(true)
})
test("fills in default isConcurrencySafe as false", () => {
const tool = buildTool(makeMinimalToolDef());
expect(tool.isConcurrencySafe({})).toBe(false);
});
test('fills in default isConcurrencySafe as false', () => {
const tool = buildTool(makeMinimalToolDef())
expect(tool.isConcurrencySafe({})).toBe(false)
})
test("fills in default isReadOnly as false", () => {
const tool = buildTool(makeMinimalToolDef());
expect(tool.isReadOnly({})).toBe(false);
});
test('fills in default isReadOnly as false', () => {
const tool = buildTool(makeMinimalToolDef())
expect(tool.isReadOnly({})).toBe(false)
})
test("fills in default isDestructive as false", () => {
const tool = buildTool(makeMinimalToolDef());
expect(tool.isDestructive!({})).toBe(false);
});
test('fills in default isDestructive as false', () => {
const tool = buildTool(makeMinimalToolDef())
expect(tool.isDestructive!({})).toBe(false)
})
test("fills in default checkPermissions as allow", async () => {
const tool = buildTool(makeMinimalToolDef());
const input = { foo: "bar" };
const result = await tool.checkPermissions(input, {} as any);
expect(result).toEqual({ behavior: "allow", updatedInput: input });
});
test('fills in default checkPermissions as allow', async () => {
const tool = buildTool(makeMinimalToolDef())
const input = { foo: 'bar' }
const result = await tool.checkPermissions(input, {} as any)
expect(result).toEqual({ behavior: 'allow', updatedInput: input })
})
test("fills in default userFacingName from tool name", () => {
const tool = buildTool(makeMinimalToolDef());
expect(tool.userFacingName(undefined)).toBe("TestTool");
});
test('fills in default userFacingName from tool name', () => {
const tool = buildTool(makeMinimalToolDef())
expect(tool.userFacingName(undefined)).toBe('TestTool')
})
test("fills in default toAutoClassifierInput as empty string", () => {
const tool = buildTool(makeMinimalToolDef());
expect(tool.toAutoClassifierInput({})).toBe("");
});
test('fills in default toAutoClassifierInput as empty string', () => {
const tool = buildTool(makeMinimalToolDef())
expect(tool.toAutoClassifierInput({})).toBe('')
})
test("preserves explicitly provided methods", () => {
test('preserves explicitly provided methods', () => {
const tool = buildTool(
makeMinimalToolDef({
isEnabled: () => false,
isConcurrencySafe: () => true,
isReadOnly: () => true,
})
);
expect(tool.isEnabled()).toBe(false);
expect(tool.isConcurrencySafe({})).toBe(true);
expect(tool.isReadOnly({})).toBe(true);
});
}),
)
expect(tool.isEnabled()).toBe(false)
expect(tool.isConcurrencySafe({})).toBe(true)
expect(tool.isReadOnly({})).toBe(true)
})
test("preserves all non-defaultable properties", () => {
const tool = buildTool(makeMinimalToolDef());
expect(tool.name).toBe("TestTool");
expect(tool.maxResultSizeChars).toBe(10000);
expect(typeof tool.call).toBe("function");
expect(typeof tool.description).toBe("function");
expect(typeof tool.prompt).toBe("function");
});
});
test('preserves all non-defaultable properties', () => {
const tool = buildTool(makeMinimalToolDef())
expect(tool.name).toBe('TestTool')
expect(tool.maxResultSizeChars).toBe(10000)
expect(typeof tool.call).toBe('function')
expect(typeof tool.description).toBe('function')
expect(typeof tool.prompt).toBe('function')
})
})
describe("toolMatchesName", () => {
test("returns true for exact name match", () => {
expect(toolMatchesName({ name: "Bash" }, "Bash")).toBe(true);
});
describe('toolMatchesName', () => {
test('returns true for exact name match', () => {
expect(toolMatchesName({ name: 'Bash' }, 'Bash')).toBe(true)
})
test("returns false for non-matching name", () => {
expect(toolMatchesName({ name: "Bash" }, "Read")).toBe(false);
});
test('returns false for non-matching name', () => {
expect(toolMatchesName({ name: 'Bash' }, 'Read')).toBe(false)
})
test("returns true when name matches an alias", () => {
test('returns true when name matches an alias', () => {
expect(
toolMatchesName({ name: "Bash", aliases: ["BashTool", "Shell"] }, "BashTool")
).toBe(true);
});
toolMatchesName(
{ name: 'Bash', aliases: ['BashTool', 'Shell'] },
'BashTool',
),
).toBe(true)
})
test("returns false when aliases is undefined", () => {
expect(toolMatchesName({ name: "Bash" }, "BashTool")).toBe(false);
});
test('returns false when aliases is undefined', () => {
expect(toolMatchesName({ name: 'Bash' }, 'BashTool')).toBe(false)
})
test("returns false when aliases is empty", () => {
expect(
toolMatchesName({ name: "Bash", aliases: [] }, "BashTool")
).toBe(false);
});
});
test('returns false when aliases is empty', () => {
expect(toolMatchesName({ name: 'Bash', aliases: [] }, 'BashTool')).toBe(
false,
)
})
})
describe("findToolByName", () => {
describe('findToolByName', () => {
const mockTools = [
buildTool(makeMinimalToolDef({ name: "Bash" })),
buildTool(makeMinimalToolDef({ name: "Read", aliases: ["FileRead"] })),
buildTool(makeMinimalToolDef({ name: "Edit" })),
];
buildTool(makeMinimalToolDef({ name: 'Bash' })),
buildTool(makeMinimalToolDef({ name: 'Read', aliases: ['FileRead'] })),
buildTool(makeMinimalToolDef({ name: 'Edit' })),
]
test("finds tool by primary name", () => {
const tool = findToolByName(mockTools, "Bash");
expect(tool).toBeDefined();
expect(tool!.name).toBe("Bash");
});
test('finds tool by primary name', () => {
const tool = findToolByName(mockTools, 'Bash')
expect(tool).toBeDefined()
expect(tool!.name).toBe('Bash')
})
test("finds tool by alias", () => {
const tool = findToolByName(mockTools, "FileRead");
expect(tool).toBeDefined();
expect(tool!.name).toBe("Read");
});
test('finds tool by alias', () => {
const tool = findToolByName(mockTools, 'FileRead')
expect(tool).toBeDefined()
expect(tool!.name).toBe('Read')
})
test("returns undefined when no match", () => {
expect(findToolByName(mockTools, "NonExistent")).toBeUndefined();
});
test('returns undefined when no match', () => {
expect(findToolByName(mockTools, 'NonExistent')).toBeUndefined()
})
test("returns first match when duplicates exist", () => {
test('returns first match when duplicates exist', () => {
const dupeTools = [
buildTool(makeMinimalToolDef({ name: "Bash", maxResultSizeChars: 100 })),
buildTool(makeMinimalToolDef({ name: "Bash", maxResultSizeChars: 200 })),
];
const tool = findToolByName(dupeTools, "Bash");
expect(tool!.maxResultSizeChars).toBe(100);
});
});
buildTool(makeMinimalToolDef({ name: 'Bash', maxResultSizeChars: 100 })),
buildTool(makeMinimalToolDef({ name: 'Bash', maxResultSizeChars: 200 })),
]
const tool = findToolByName(dupeTools, 'Bash')
expect(tool!.maxResultSizeChars).toBe(100)
})
})
describe("getEmptyToolPermissionContext", () => {
test("returns default permission mode", () => {
const ctx = getEmptyToolPermissionContext();
expect(ctx.mode).toBe("default");
});
describe('getEmptyToolPermissionContext', () => {
test('returns default permission mode', () => {
const ctx = getEmptyToolPermissionContext()
expect(ctx.mode).toBe('default')
})
test("returns empty maps and arrays", () => {
const ctx = getEmptyToolPermissionContext();
expect(ctx.additionalWorkingDirectories.size).toBe(0);
expect(ctx.alwaysAllowRules).toEqual({});
expect(ctx.alwaysDenyRules).toEqual({});
expect(ctx.alwaysAskRules).toEqual({});
});
test('returns empty maps and arrays', () => {
const ctx = getEmptyToolPermissionContext()
expect(ctx.additionalWorkingDirectories.size).toBe(0)
expect(ctx.alwaysAllowRules).toEqual({})
expect(ctx.alwaysDenyRules).toEqual({})
expect(ctx.alwaysAskRules).toEqual({})
})
test("returns isBypassPermissionsModeAvailable as false", () => {
const ctx = getEmptyToolPermissionContext();
expect(ctx.isBypassPermissionsModeAvailable).toBe(false);
});
});
test('returns isBypassPermissionsModeAvailable as false', () => {
const ctx = getEmptyToolPermissionContext()
expect(ctx.isBypassPermissionsModeAvailable).toBe(false)
})
})
describe("filterToolProgressMessages", () => {
test("filters out hook_progress messages", () => {
describe('filterToolProgressMessages', () => {
test('filters out hook_progress messages', () => {
const messages = [
{ data: { type: "hook_progress", hookName: "pre" } },
{ data: { type: "tool_progress", toolName: "Bash" } },
] as any[];
const result = filterToolProgressMessages(messages);
expect(result).toHaveLength(1);
expect((result[0]!.data as any).type).toBe("tool_progress");
});
{ data: { type: 'hook_progress', hookName: 'pre' } },
{ data: { type: 'tool_progress', toolName: 'Bash' } },
] as any[]
const result = filterToolProgressMessages(messages)
expect(result).toHaveLength(1)
expect((result[0]!.data as any).type).toBe('tool_progress')
})
test("keeps tool progress messages", () => {
test('keeps tool progress messages', () => {
const messages = [
{ data: { type: "tool_progress", toolName: "Bash" } },
{ data: { type: "tool_progress", toolName: "Read" } },
] as any[];
const result = filterToolProgressMessages(messages);
expect(result).toHaveLength(2);
});
{ data: { type: 'tool_progress', toolName: 'Bash' } },
{ data: { type: 'tool_progress', toolName: 'Read' } },
] as any[]
const result = filterToolProgressMessages(messages)
expect(result).toHaveLength(2)
})
test("returns empty array for empty input", () => {
expect(filterToolProgressMessages([])).toEqual([]);
});
test('returns empty array for empty input', () => {
expect(filterToolProgressMessages([])).toEqual([])
})
test("handles messages without type field", () => {
test('handles messages without type field', () => {
const messages = [
{ data: { toolName: "Bash" } },
{ data: { type: "hook_progress" } },
] as any[];
const result = filterToolProgressMessages(messages);
expect(result).toHaveLength(1);
});
});
{ data: { toolName: 'Bash' } },
{ data: { type: 'hook_progress' } },
] as any[]
const result = filterToolProgressMessages(messages)
expect(result).toHaveLength(1)
})
})