test: 补充单元测试提升代码覆盖率
新增测试文件: - 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
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
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'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user