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:
2025-12-11 20:37:03 +08:00
parent f8b0cd4bec
commit bca19b7741
24 changed files with 6347 additions and 4 deletions
+274
View File
@@ -0,0 +1,274 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { todoManager } from '../../../../src/tools/todo/todo-manager.js';
import type { SessionManager } from '../../../../src/session/index.js';
import type { Todo } from '../../../../src/session/types.js';
describe('TodoManager', () => {
let mockSessionManager: SessionManager;
let mockTodos: Todo[];
beforeEach(() => {
mockTodos = [];
mockSessionManager = {
getTodos: vi.fn(() => mockTodos),
setTodos: vi.fn(async (todos: Todo[]) => {
mockTodos = todos;
}),
} as unknown as SessionManager;
// 重置 todoManager 状态
todoManager.setSessionManager(mockSessionManager);
});
describe('setSessionManager', () => {
it('设置会话管理器后 isInitialized 返回 true', () => {
const freshManager = {
getTodos: vi.fn(() => []),
setTodos: vi.fn(),
} as unknown as SessionManager;
todoManager.setSessionManager(freshManager);
expect(todoManager.isInitialized()).toBe(true);
});
});
describe('getTodos', () => {
it('返回空数组当没有 todo', () => {
const todos = todoManager.getTodos();
expect(todos).toEqual([]);
});
it('返回现有的 todo 列表', () => {
mockTodos = [
{ id: '1', content: 'Task 1', status: 'pending', createdAt: '', updatedAt: '' },
{ id: '2', content: 'Task 2', status: 'completed', createdAt: '', updatedAt: '' },
];
const todos = todoManager.getTodos();
expect(todos).toHaveLength(2);
expect(todos[0].content).toBe('Task 1');
expect(todos[1].content).toBe('Task 2');
});
it('正确调用 sessionManager.getTodos', () => {
todoManager.getTodos();
expect(mockSessionManager.getTodos).toHaveBeenCalled();
});
});
describe('setTodos', () => {
it('更新 todo 列表', async () => {
const newTodos: Todo[] = [
{ id: '1', content: 'New Task', status: 'pending', createdAt: '', updatedAt: '' },
];
await todoManager.setTodos(newTodos);
expect(mockSessionManager.setTodos).toHaveBeenCalledWith(newTodos);
expect(mockTodos).toHaveLength(1);
});
it('可以设置空列表', async () => {
mockTodos = [
{ id: '1', content: 'Task', status: 'pending', createdAt: '', updatedAt: '' },
];
await todoManager.setTodos([]);
expect(mockTodos).toHaveLength(0);
});
});
describe('addTodo', () => {
it('添加新的 todo(默认状态 pending', async () => {
const todo = await todoManager.addTodo('新任务');
expect(todo.content).toBe('新任务');
expect(todo.status).toBe('pending');
expect(todo.id).toBeDefined();
expect(todo.createdAt).toBeDefined();
expect(todo.updatedAt).toBeDefined();
expect(mockTodos).toHaveLength(1);
});
it('添加指定状态的 todo', async () => {
const todo = await todoManager.addTodo('进行中的任务', 'in_progress');
expect(todo.content).toBe('进行中的任务');
expect(todo.status).toBe('in_progress');
});
it('添加已完成状态的 todo', async () => {
const todo = await todoManager.addTodo('已完成任务', 'completed');
expect(todo.status).toBe('completed');
});
it('生成唯一 ID', async () => {
const todo1 = await todoManager.addTodo('Task 1');
const todo2 = await todoManager.addTodo('Task 2');
expect(todo1.id).not.toBe(todo2.id);
});
it('追加到现有列表', async () => {
mockTodos = [
{ id: 'existing', content: 'Existing', status: 'pending', createdAt: '', updatedAt: '' },
];
await todoManager.addTodo('New Task');
expect(mockTodos).toHaveLength(2);
expect(mockTodos[0].content).toBe('Existing');
expect(mockTodos[1].content).toBe('New Task');
});
});
describe('updateTodoStatus', () => {
beforeEach(() => {
mockTodos = [
{ id: 'todo-1', content: 'Task 1', status: 'pending', createdAt: '2024-01-01', updatedAt: '2024-01-01' },
{ id: 'todo-2', content: 'Task 2', status: 'pending', createdAt: '2024-01-01', updatedAt: '2024-01-01' },
];
});
it('更新存在的 todo 状态', async () => {
const result = await todoManager.updateTodoStatus('todo-1', 'completed');
expect(result).toBe(true);
expect(mockTodos[0].status).toBe('completed');
});
it('更新 updatedAt 时间戳', async () => {
const originalUpdatedAt = mockTodos[0].updatedAt;
await todoManager.updateTodoStatus('todo-1', 'in_progress');
expect(mockTodos[0].updatedAt).not.toBe(originalUpdatedAt);
});
it('不存在的 todo 返回 false', async () => {
const result = await todoManager.updateTodoStatus('non-existent', 'completed');
expect(result).toBe(false);
});
it('可以更新为任意状态', async () => {
await todoManager.updateTodoStatus('todo-1', 'in_progress');
expect(mockTodos[0].status).toBe('in_progress');
await todoManager.updateTodoStatus('todo-1', 'completed');
expect(mockTodos[0].status).toBe('completed');
await todoManager.updateTodoStatus('todo-1', 'pending');
expect(mockTodos[0].status).toBe('pending');
});
});
describe('deleteTodo', () => {
beforeEach(() => {
mockTodos = [
{ id: 'todo-1', content: 'Task 1', status: 'pending', createdAt: '', updatedAt: '' },
{ id: 'todo-2', content: 'Task 2', status: 'completed', createdAt: '', updatedAt: '' },
{ id: 'todo-3', content: 'Task 3', status: 'in_progress', createdAt: '', updatedAt: '' },
];
});
it('删除存在的 todo', async () => {
const result = await todoManager.deleteTodo('todo-2');
expect(result).toBe(true);
expect(mockTodos).toHaveLength(2);
expect(mockTodos.find(t => t.id === 'todo-2')).toBeUndefined();
});
it('删除第一个 todo', async () => {
const result = await todoManager.deleteTodo('todo-1');
expect(result).toBe(true);
expect(mockTodos[0].id).toBe('todo-2');
});
it('删除最后一个 todo', async () => {
const result = await todoManager.deleteTodo('todo-3');
expect(result).toBe(true);
expect(mockTodos).toHaveLength(2);
});
it('不存在的 todo 返回 false', async () => {
const result = await todoManager.deleteTodo('non-existent');
expect(result).toBe(false);
expect(mockTodos).toHaveLength(3);
});
it('删除后其他 todo 保持不变', async () => {
await todoManager.deleteTodo('todo-2');
expect(mockTodos[0].content).toBe('Task 1');
expect(mockTodos[1].content).toBe('Task 3');
});
});
describe('clearTodos', () => {
it('清空所有 todo', async () => {
mockTodos = [
{ id: '1', content: 'Task 1', status: 'pending', createdAt: '', updatedAt: '' },
{ id: '2', content: 'Task 2', status: 'completed', createdAt: '', updatedAt: '' },
];
await todoManager.clearTodos();
expect(mockTodos).toHaveLength(0);
expect(mockSessionManager.setTodos).toHaveBeenCalledWith([]);
});
it('空列表时调用也不报错', async () => {
mockTodos = [];
await expect(todoManager.clearTodos()).resolves.not.toThrow();
expect(mockTodos).toHaveLength(0);
});
});
describe('isInitialized', () => {
it('初始化后返回 true', () => {
expect(todoManager.isInitialized()).toBe(true);
});
});
describe('边界情况', () => {
it('处理包含特殊字符的 content', async () => {
const specialContent = '任务: "测试" & <script>alert(1)</script>';
const todo = await todoManager.addTodo(specialContent);
expect(todo.content).toBe(specialContent);
});
it('处理非常长的 content', async () => {
const longContent = 'A'.repeat(10000);
const todo = await todoManager.addTodo(longContent);
expect(todo.content).toBe(longContent);
});
it('处理空字符串 content', async () => {
const todo = await todoManager.addTodo('');
expect(todo.content).toBe('');
});
it('连续操作保持数据一致性', async () => {
await todoManager.addTodo('Task 1');
await todoManager.addTodo('Task 2');
await todoManager.updateTodoStatus(mockTodos[0].id, 'completed');
await todoManager.deleteTodo(mockTodos[1].id);
await todoManager.addTodo('Task 3');
expect(mockTodos).toHaveLength(2);
expect(mockTodos[0].status).toBe('completed');
expect(mockTodos[1].content).toBe('Task 3');
});
});
});