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, beforeEach, vi } from 'vitest';
|
|
import { skillTool, updateSkillDescription } from '../../../../src/tools/skill/skill.js';
|
|
import { getSkillRegistry, resetSkillRegistry } from '../../../../src/skills/registry.js';
|
|
import type { Skill } from '../../../../src/skills/types.js';
|
|
|
|
// Mock loader to prevent file system access
|
|
vi.mock('../../../../src/skills/loader.js', () => ({
|
|
skillLoader: {
|
|
loadFromDirectory: vi.fn().mockResolvedValue([]),
|
|
getUserSkillsDir: vi.fn().mockReturnValue('/mock/user/skills'),
|
|
getProjectSkillsDir: vi.fn().mockReturnValue('/mock/project/skills'),
|
|
},
|
|
}));
|
|
|
|
// Mock builtin skills
|
|
vi.mock('../../../../src/skills/builtin/index.js', () => ({
|
|
builtinSkills: [
|
|
{
|
|
name: 'code-review',
|
|
description: '代码审查',
|
|
promptTemplate: '请审查以下代码:\n\n{{code}}\n\n重点:{{focus}}',
|
|
parameters: {
|
|
code: { type: 'string', required: true, description: '代码' },
|
|
focus: { type: 'string', required: false, default: '代码质量', description: '审查重点' },
|
|
},
|
|
category: 'development',
|
|
source: 'builtin',
|
|
enabled: true,
|
|
},
|
|
{
|
|
name: 'disabled-skill',
|
|
description: '禁用的 Skill',
|
|
promptTemplate: '不应该执行',
|
|
source: 'builtin',
|
|
enabled: false,
|
|
},
|
|
],
|
|
}));
|
|
|
|
describe('skillTool - Skill 工具', () => {
|
|
beforeEach(async () => {
|
|
vi.clearAllMocks();
|
|
resetSkillRegistry();
|
|
// 初始化注册表
|
|
const registry = getSkillRegistry();
|
|
await registry.initialize();
|
|
});
|
|
|
|
describe('工具定义', () => {
|
|
it('有正确的名称', () => {
|
|
expect(skillTool.name).toBe('skill');
|
|
});
|
|
|
|
it('有正确的元数据', () => {
|
|
expect(skillTool.metadata.category).toBe('agent');
|
|
expect(skillTool.metadata.keywords).toContain('skill');
|
|
});
|
|
|
|
it('skill_name 参数是必须的', () => {
|
|
expect(skillTool.parameters.skill_name.required).toBe(true);
|
|
});
|
|
|
|
it('params 参数是可选的', () => {
|
|
expect(skillTool.parameters.params.required).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('execute - 执行', () => {
|
|
it('成功执行 Skill 并渲染模板', async () => {
|
|
const result = await skillTool.execute({
|
|
skill_name: 'code-review',
|
|
params: {
|
|
code: 'function add(a, b) { return a + b; }',
|
|
focus: '性能',
|
|
},
|
|
});
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.output).toContain('function add');
|
|
expect(result.output).toContain('性能');
|
|
expect(result.metadata?.skill).toBe('code-review');
|
|
});
|
|
|
|
it('使用默认参数值', async () => {
|
|
const result = await skillTool.execute({
|
|
skill_name: 'code-review',
|
|
params: {
|
|
code: 'const x = 1;',
|
|
},
|
|
});
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.output).toContain('代码质量'); // 默认值
|
|
});
|
|
|
|
it('Skill 不存在时返回错误', async () => {
|
|
const result = await skillTool.execute({
|
|
skill_name: 'non-existent',
|
|
params: {},
|
|
});
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('不存在');
|
|
});
|
|
|
|
it('Skill 不存在时提供建议', async () => {
|
|
const result = await skillTool.execute({
|
|
skill_name: 'code-rev', // 类似 code-review
|
|
params: {},
|
|
});
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('code-review'); // 建议
|
|
});
|
|
|
|
it('缺少必需参数时返回错误', async () => {
|
|
const result = await skillTool.execute({
|
|
skill_name: 'code-review',
|
|
params: {}, // 缺少 code 参数
|
|
});
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('缺少必需参数');
|
|
});
|
|
|
|
it('禁用的 Skill 返回错误', async () => {
|
|
const result = await skillTool.execute({
|
|
skill_name: 'disabled-skill',
|
|
params: {},
|
|
});
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('禁用');
|
|
});
|
|
|
|
it('返回正确的 metadata', async () => {
|
|
const result = await skillTool.execute({
|
|
skill_name: 'code-review',
|
|
params: { code: 'test' },
|
|
});
|
|
|
|
expect(result.metadata?.skill).toBe('code-review');
|
|
expect(result.metadata?.category).toBe('development');
|
|
expect(result.metadata?.source).toBe('builtin');
|
|
});
|
|
});
|
|
|
|
describe('工具描述', () => {
|
|
it('更新后描述包含可用 Skill 列表', () => {
|
|
// beforeEach 中已初始化 registry,现在更新描述
|
|
updateSkillDescription();
|
|
|
|
expect(skillTool.description).toContain('code-review');
|
|
expect(skillTool.description).toContain('代码审查');
|
|
});
|
|
|
|
it('更新后描述包含分类信息', () => {
|
|
updateSkillDescription();
|
|
expect(skillTool.description).toContain('[development]');
|
|
});
|
|
|
|
it('更新后描述包含使用示例', () => {
|
|
updateSkillDescription();
|
|
expect(skillTool.description).toContain('使用示例');
|
|
expect(skillTool.description).toContain('skill_name');
|
|
});
|
|
|
|
it('禁用的 Skill 不在描述中', () => {
|
|
updateSkillDescription();
|
|
expect(skillTool.description).not.toContain('disabled-skill');
|
|
});
|
|
});
|
|
|
|
describe('updateSkillDescription', () => {
|
|
it('调用后描述被更新', async () => {
|
|
updateSkillDescription();
|
|
|
|
// 描述应该包含当前注册的 Skill
|
|
expect(skillTool.description).toContain('code-review');
|
|
expect(typeof skillTool.description).toBe('string');
|
|
});
|
|
});
|
|
|
|
describe('边界情况', () => {
|
|
it('params 为 undefined 时使用空对象', async () => {
|
|
const result = await skillTool.execute({
|
|
skill_name: 'code-review',
|
|
// 不提供 params
|
|
});
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('缺少必需参数');
|
|
});
|
|
|
|
it('skill_name 为空字符串时返回错误', async () => {
|
|
const result = await skillTool.execute({
|
|
skill_name: '',
|
|
params: {},
|
|
});
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('不存在');
|
|
});
|
|
});
|
|
});
|