Files
ai-terminal-assistant/tests/unit/tools/todo/todowrite.test.ts
T
kurihada 729fb2d42a feat: 添加完整的单元测试套件
- 新增 vitest 测试框架配置
- 添加 54 个测试文件,共 951 个测试用例
- 覆盖核心模块:
  - Agent: executor, registry, config-loader, permission-merger
  - Context: manager, compaction, prune, token-counter
  - Permission: manager, bash/file/git/web checkers, wildcard
  - Session: manager, storage
  - Tools: filesystem (12个), git (10个), web, shell, todo, task
  - LSP: client, server, language
  - Utils: config, diff
  - UI: terminal
2025-12-11 14:45:24 +08:00

172 lines
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect, beforeEach, vi } from 'vitest';
// 使用可变的引用对象来绕过 hoisting 问题
const mockState = {
isInitialized: vi.fn().mockReturnValue(true),
getTodos: vi.fn().mockReturnValue([]),
setTodos: vi.fn().mockResolvedValue(undefined),
};
vi.mock('../../../../src/tools/todo/todo-manager.js', () => ({
todoManager: {
isInitialized: () => mockState.isInitialized(),
getTodos: () => mockState.getTodos(),
setTodos: (todos: any) => mockState.setTodos(todos),
},
}));
import { todoWriteTool } from '../../../../src/tools/todo/todowrite.js';
describe('todoWriteTool - Todo 写入工具', () => {
beforeEach(() => {
vi.clearAllMocks();
mockState.isInitialized.mockReturnValue(true);
mockState.getTodos.mockReturnValue([]);
});
describe('工具定义', () => {
it('有正确的名称', () => {
expect(todoWriteTool.name).toBe('todowrite');
});
it('有正确的元数据', () => {
expect(todoWriteTool.metadata.category).toBe('core');
expect(todoWriteTool.metadata.keywords).toContain('todo');
expect(todoWriteTool.metadata.keywords).toContain('task');
expect(todoWriteTool.metadata.keywords).toContain('write');
});
it('定义了必需的 todos 参数', () => {
expect(todoWriteTool.parameters.todos.required).toBe(true);
});
});
describe('execute - 执行', () => {
it('成功创建待办列表', async () => {
const result = await todoWriteTool.execute({
todos: [
{ content: '任务1', status: 'pending' },
{ content: '任务2', status: 'in_progress' },
],
});
expect(result.success).toBe(true);
expect(result.output).toContain('待办事项已更新');
expect(mockState.setTodos).toHaveBeenCalled();
});
it('返回正确的统计信息', async () => {
const result = await todoWriteTool.execute({
todos: [
{ content: '任务1', status: 'pending' },
{ content: '任务2', status: 'in_progress' },
{ content: '任务3', status: 'completed' },
],
});
expect(result.success).toBe(true);
// pendingCount 包含所有非 completed 状态的任务(pending + in_progress
expect(result.metadata?.pendingCount).toBe(2);
expect(result.metadata?.inProgressCount).toBe(1);
expect(result.metadata?.completedCount).toBe(1);
});
it('更新现有任务', async () => {
mockState.getTodos.mockReturnValue([
{ id: 'existing-1', content: '任务1', status: 'pending', createdAt: '2024-01-01', updatedAt: '2024-01-01' },
]);
const result = await todoWriteTool.execute({
todos: [
{ content: '任务1', status: 'completed' },
],
});
expect(result.success).toBe(true);
const savedTodos = mockState.setTodos.mock.calls[0][0];
expect(savedTodos[0].id).toBe('existing-1'); // 保留原有 ID
expect(savedTodos[0].status).toBe('completed');
});
it('未初始化时返回错误', async () => {
mockState.isInitialized.mockReturnValue(false);
const result = await todoWriteTool.execute({
todos: [{ content: '任务', status: 'pending' }],
});
expect(result.success).toBe(false);
expect(result.error).toContain('会话管理器未初始化');
});
it('todos 非数组返回错误', async () => {
const result = await todoWriteTool.execute({
todos: 'not an array',
});
expect(result.success).toBe(false);
expect(result.error).toContain('todos 参数必须是数组');
});
it('无效的待办项格式返回错误', async () => {
const result = await todoWriteTool.execute({
todos: [
{ content: '有效任务', status: 'pending' },
{ content: '', status: 'pending' }, // 空内容
],
});
expect(result.success).toBe(false);
expect(result.error).toContain('第 2 个待办事项格式无效');
});
it('无效的状态值返回错误', async () => {
const result = await todoWriteTool.execute({
todos: [
{ content: '任务', status: 'invalid_status' },
],
});
expect(result.success).toBe(false);
expect(result.error).toContain('格式无效');
});
it('缺少 content 返回错误', async () => {
const result = await todoWriteTool.execute({
todos: [
{ status: 'pending' },
],
});
expect(result.success).toBe(false);
expect(result.error).toContain('格式无效');
});
it('为新任务生成 ID', async () => {
const result = await todoWriteTool.execute({
todos: [
{ content: '新任务', status: 'pending' },
],
});
expect(result.success).toBe(true);
const savedTodos = mockState.setTodos.mock.calls[0][0];
expect(savedTodos[0].id).toBeDefined();
expect(savedTodos[0].id.length).toBeGreaterThan(0);
});
it('设置创建和更新时间', async () => {
const result = await todoWriteTool.execute({
todos: [
{ content: '新任务', status: 'pending' },
],
});
expect(result.success).toBe(true);
const savedTodos = mockState.setTodos.mock.calls[0][0];
expect(savedTodos[0].createdAt).toBeDefined();
expect(savedTodos[0].updatedAt).toBeDefined();
});
});
});