Files
ai-terminal-assistant/packages/core/tests/unit/tools/tool-search.test.ts
T
kurihada 5e32375f0e feat: 重构为 Monorepo 架构并实现 HTTP Server
架构变更:
- 采用 pnpm workspaces 实现 Monorepo 结构
- 将现有代码迁移到 packages/core
- 新增 packages/server HTTP 服务层

Server 功能:
- REST API: 会话管理、工具管理、配置管理
- WebSocket: 实时双向通信支持
- SSE: 服务端事件推送
- Hono + Bun 作为运行时

API 端点:
- GET/POST /api/sessions - 会话 CRUD
- GET/POST /api/sessions/:id/messages - 消息管理
- GET /api/sessions/:id/events - SSE 事件流
- WS /api/ws/:sessionId - WebSocket 连接
- GET/POST /api/tools - 工具管理
- GET/PUT /api/config - 配置管理
2025-12-12 10:42:20 +08:00

144 lines
4.9 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { toolSearchTool } from '../../../src/tools/tool-search.js';
// Mock toolRegistry
vi.mock('../../../src/tools/registry.js', () => ({
toolRegistry: {
search: vi.fn(),
},
}));
import { toolRegistry } from '../../../src/tools/registry.js';
describe('toolSearchTool', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('metadata', () => {
it('工具名为 tool_search', () => {
expect(toolSearchTool.name).toBe('tool_search');
});
it('有描述信息', () => {
expect(toolSearchTool.description).toBeDefined();
expect(toolSearchTool.description.length).toBeGreaterThan(0);
});
it('描述中包含功能类别', () => {
expect(toolSearchTool.description).toContain('文件操作');
expect(toolSearchTool.description).toContain('目录操作');
expect(toolSearchTool.description).toContain('Shell');
});
it('有 query 参数', () => {
expect(toolSearchTool.parameters.query).toBeDefined();
expect(toolSearchTool.parameters.query.type).toBe('string');
expect(toolSearchTool.parameters.query.required).toBe(true);
});
it('metadata 设置正确', () => {
expect(toolSearchTool.metadata).toBeDefined();
expect(toolSearchTool.metadata?.category).toBe('core');
expect(toolSearchTool.metadata?.deferLoading).toBe(false);
});
it('metadata 包含搜索关键词', () => {
expect(toolSearchTool.metadata?.keywords).toContain('search');
expect(toolSearchTool.metadata?.keywords).toContain('搜索');
});
});
describe('execute', () => {
it('空 query 返回错误', async () => {
const result = await toolSearchTool.execute({ query: '' });
expect(result.success).toBe(false);
expect(result.error).toBe('请提供搜索关键词');
});
it('空白 query 返回错误', async () => {
const result = await toolSearchTool.execute({ query: ' ' });
expect(result.success).toBe(false);
expect(result.error).toBe('请提供搜索关键词');
});
it('undefined query 返回错误', async () => {
const result = await toolSearchTool.execute({});
expect(result.success).toBe(false);
expect(result.error).toBe('请提供搜索关键词');
});
it('没有匹配结果时返回提示', async () => {
vi.mocked(toolRegistry.search).mockReturnValue([]);
const result = await toolSearchTool.execute({ query: 'nonexistent' });
expect(result.success).toBe(true);
expect(result.output).toContain('没有找到');
expect(result.output).toContain('nonexistent');
});
it('有匹配结果时返回工具列表', async () => {
vi.mocked(toolRegistry.search).mockReturnValue([
{ name: 'read_file', description: '读取文件', category: 'filesystem' },
{ name: 'write_file', description: '写入文件', category: 'filesystem' },
] as any);
const result = await toolSearchTool.execute({ query: '文件' });
expect(result.success).toBe(true);
expect(result.output).toContain('找到 2 个相关工具');
expect(result.output).toContain('read_file');
expect(result.output).toContain('write_file');
expect(result.output).toContain('[filesystem]');
});
it('返回结果包含使用提示', async () => {
vi.mocked(toolRegistry.search).mockReturnValue([
{ name: 'bash', description: '执行命令', category: 'shell' },
] as any);
const result = await toolSearchTool.execute({ query: '命令' });
expect(result.output).toContain('可以直接调用');
});
it('调用 registry.search 时传递正确参数', async () => {
vi.mocked(toolRegistry.search).mockReturnValue([]);
await toolSearchTool.execute({ query: '搜索关键词' });
expect(toolRegistry.search).toHaveBeenCalledWith('搜索关键词', 5);
});
it('搜索结果格式化正确', async () => {
vi.mocked(toolRegistry.search).mockReturnValue([
{ name: 'grep_content', description: '搜索文件内容', category: 'filesystem' },
] as any);
const result = await toolSearchTool.execute({ query: 'grep' });
expect(result.output).toContain('- grep_content: 搜索文件内容 [filesystem]');
});
it('多个搜索结果正确排列', async () => {
vi.mocked(toolRegistry.search).mockReturnValue([
{ name: 'tool1', description: 'desc1', category: 'cat1' },
{ name: 'tool2', description: 'desc2', category: 'cat2' },
{ name: 'tool3', description: 'desc3', category: 'cat3' },
] as any);
const result = await toolSearchTool.execute({ query: 'test' });
expect(result.output).toContain('找到 3 个相关工具');
// 验证每个工具都在输出中
expect(result.output).toContain('tool1');
expect(result.output).toContain('tool2');
expect(result.output).toContain('tool3');
});
});
});