bca19b7741
新增测试文件: - agent/executor-extended.test.ts, presets/ - context/manager-extended.test.ts - core/agent.test.ts, providers.test.ts - lsp/cli.test.ts, client-extended.test.ts, index.test.ts - permission/file-prompt.test.ts, prompt.test.ts - skills/builtin/ - tools/filesystem/write_file-extended.test.ts - tools/git/git_commit-extended.test.ts - tools/load_description.test.ts - tools/todo/todo-manager.test.ts - tools/tool-search.test.ts - types/ - utils/config-extended.test.ts, diff-extended.test.ts 修改现有测试: - agent/manager.test.ts - tools/skill/skill.test.ts - utils/config.test.ts, diff.test.ts, image.test.ts
206 lines
6.1 KiB
TypeScript
206 lines
6.1 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
|
// Mock fs
|
|
vi.mock('fs', () => ({
|
|
readFileSync: vi.fn(),
|
|
}));
|
|
|
|
import * as fs from 'fs';
|
|
import { loadDescription } from '../../../src/tools/load_description.js';
|
|
|
|
describe('loadDescription', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe('带分类的工具', () => {
|
|
it('加载 shell 类工具描述', () => {
|
|
vi.mocked(fs.readFileSync).mockReturnValue(' Bash 工具描述 ');
|
|
|
|
const result = loadDescription('bash');
|
|
|
|
expect(result).toBe('Bash 工具描述');
|
|
expect(fs.readFileSync).toHaveBeenCalledWith(
|
|
expect.stringContaining('descriptions/shell/bash.txt'),
|
|
'utf-8'
|
|
);
|
|
});
|
|
|
|
it('加载 filesystem 类工具描述', () => {
|
|
vi.mocked(fs.readFileSync).mockReturnValue('读取文件描述');
|
|
|
|
const result = loadDescription('read_file');
|
|
|
|
expect(result).toBe('读取文件描述');
|
|
expect(fs.readFileSync).toHaveBeenCalledWith(
|
|
expect.stringContaining('descriptions/filesystem/read_file.txt'),
|
|
'utf-8'
|
|
);
|
|
});
|
|
|
|
it('加载 write_file 描述', () => {
|
|
vi.mocked(fs.readFileSync).mockReturnValue('写入文件描述');
|
|
|
|
loadDescription('write_file');
|
|
|
|
expect(fs.readFileSync).toHaveBeenCalledWith(
|
|
expect.stringContaining('descriptions/filesystem/write_file.txt'),
|
|
'utf-8'
|
|
);
|
|
});
|
|
|
|
it('加载 edit_file 描述', () => {
|
|
vi.mocked(fs.readFileSync).mockReturnValue('编辑文件描述');
|
|
|
|
loadDescription('edit_file');
|
|
|
|
expect(fs.readFileSync).toHaveBeenCalledWith(
|
|
expect.stringContaining('descriptions/filesystem/edit_file.txt'),
|
|
'utf-8'
|
|
);
|
|
});
|
|
|
|
it('加载 git 类工具描述', () => {
|
|
vi.mocked(fs.readFileSync).mockReturnValue('Git status 描述');
|
|
|
|
loadDescription('git_status');
|
|
|
|
expect(fs.readFileSync).toHaveBeenCalledWith(
|
|
expect.stringContaining('descriptions/git/git_status.txt'),
|
|
'utf-8'
|
|
);
|
|
});
|
|
|
|
it('加载 web 类工具描述', () => {
|
|
vi.mocked(fs.readFileSync).mockReturnValue('Web search 描述');
|
|
|
|
loadDescription('web_search');
|
|
|
|
expect(fs.readFileSync).toHaveBeenCalledWith(
|
|
expect.stringContaining('descriptions/web/web_search.txt'),
|
|
'utf-8'
|
|
);
|
|
});
|
|
|
|
it('加载 todo 类工具描述', () => {
|
|
vi.mocked(fs.readFileSync).mockReturnValue('Todo read 描述');
|
|
|
|
loadDescription('todo_read');
|
|
|
|
expect(fs.readFileSync).toHaveBeenCalledWith(
|
|
expect.stringContaining('descriptions/todo/todo_read.txt'),
|
|
'utf-8'
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('不带分类的工具', () => {
|
|
it('未知工具使用根目录', () => {
|
|
vi.mocked(fs.readFileSync).mockReturnValue('未知工具描述');
|
|
|
|
loadDescription('unknown_tool');
|
|
|
|
expect(fs.readFileSync).toHaveBeenCalledWith(
|
|
expect.stringContaining('descriptions/unknown_tool.txt'),
|
|
'utf-8'
|
|
);
|
|
// 确保不包含子目录
|
|
expect(fs.readFileSync).not.toHaveBeenCalledWith(
|
|
expect.stringContaining('descriptions/filesystem/unknown_tool.txt'),
|
|
'utf-8'
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('错误处理', () => {
|
|
it('文件不存在时抛出错误', () => {
|
|
vi.mocked(fs.readFileSync).mockImplementation(() => {
|
|
throw new Error('ENOENT');
|
|
});
|
|
|
|
expect(() => loadDescription('nonexistent')).toThrow('无法加载工具描述文件');
|
|
});
|
|
|
|
it('错误信息包含文件路径', () => {
|
|
vi.mocked(fs.readFileSync).mockImplementation(() => {
|
|
throw new Error('ENOENT');
|
|
});
|
|
|
|
expect(() => loadDescription('some_tool')).toThrow('some_tool.txt');
|
|
});
|
|
});
|
|
|
|
describe('内容处理', () => {
|
|
it('去除前后空白', () => {
|
|
vi.mocked(fs.readFileSync).mockReturnValue('\n\n 内容 \n\n');
|
|
|
|
const result = loadDescription('bash');
|
|
|
|
expect(result).toBe('内容');
|
|
});
|
|
|
|
it('保留中间空白', () => {
|
|
vi.mocked(fs.readFileSync).mockReturnValue('第一行\n第二行\n第三行');
|
|
|
|
const result = loadDescription('bash');
|
|
|
|
expect(result).toBe('第一行\n第二行\n第三行');
|
|
});
|
|
|
|
it('空文件返回空字符串', () => {
|
|
vi.mocked(fs.readFileSync).mockReturnValue(' ');
|
|
|
|
const result = loadDescription('bash');
|
|
|
|
expect(result).toBe('');
|
|
});
|
|
});
|
|
|
|
describe('所有映射的工具', () => {
|
|
const toolCategories = [
|
|
// shell
|
|
{ tool: 'bash', category: 'shell' },
|
|
// filesystem
|
|
{ tool: 'read_file', category: 'filesystem' },
|
|
{ tool: 'write_file', category: 'filesystem' },
|
|
{ tool: 'edit_file', category: 'filesystem' },
|
|
{ tool: 'list_directory', category: 'filesystem' },
|
|
{ tool: 'create_directory', category: 'filesystem' },
|
|
{ tool: 'search_files', category: 'filesystem' },
|
|
{ tool: 'grep_content', category: 'filesystem' },
|
|
{ tool: 'get_file_info', category: 'filesystem' },
|
|
{ tool: 'move_file', category: 'filesystem' },
|
|
{ tool: 'copy_file', category: 'filesystem' },
|
|
{ tool: 'delete_file', category: 'filesystem' },
|
|
// web
|
|
{ tool: 'web_search', category: 'web' },
|
|
{ tool: 'web_extract', category: 'web' },
|
|
// git
|
|
{ tool: 'git_status', category: 'git' },
|
|
{ tool: 'git_diff', category: 'git' },
|
|
{ tool: 'git_log', category: 'git' },
|
|
{ tool: 'git_branch', category: 'git' },
|
|
{ tool: 'git_add', category: 'git' },
|
|
{ tool: 'git_commit', category: 'git' },
|
|
{ tool: 'git_push', category: 'git' },
|
|
{ tool: 'git_pull', category: 'git' },
|
|
{ tool: 'git_checkout', category: 'git' },
|
|
{ tool: 'git_stash', category: 'git' },
|
|
// todo
|
|
{ tool: 'todo_read', category: 'todo' },
|
|
{ tool: 'todo_write', category: 'todo' },
|
|
];
|
|
|
|
it.each(toolCategories)('$tool 映射到 $category 目录', ({ tool, category }) => {
|
|
vi.mocked(fs.readFileSync).mockReturnValue('描述');
|
|
|
|
loadDescription(tool);
|
|
|
|
expect(fs.readFileSync).toHaveBeenCalledWith(
|
|
expect.stringContaining(`descriptions/${category}/${tool}.txt`),
|
|
'utf-8'
|
|
);
|
|
});
|
|
});
|
|
});
|