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
+264
View File
@@ -0,0 +1,264 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { getModelFactory, providers } from '../../../src/core/providers.js';
// Mock AI SDK providers
vi.mock('@ai-sdk/anthropic', () => ({
createAnthropic: vi.fn(() => {
const modelFn = (model: string) => ({ modelId: `anthropic:${model}` });
return modelFn;
}),
}));
vi.mock('@ai-sdk/deepseek', () => ({
createDeepSeek: vi.fn(() => {
const modelFn = (model: string) => ({ modelId: `deepseek:${model}` });
return modelFn;
}),
}));
vi.mock('@ai-sdk/openai', () => ({
createOpenAI: vi.fn(() => {
const modelFn = (model: string) => ({ modelId: `openai:${model}` });
return modelFn;
}),
}));
vi.mock('qwen-ai-provider-v5', () => ({
createQwen: vi.fn(() => {
const modelFn = (model: string) => ({ modelId: `qwen:${model}` });
return modelFn;
}),
}));
import { createAnthropic } from '@ai-sdk/anthropic';
import { createDeepSeek } from '@ai-sdk/deepseek';
import { createOpenAI } from '@ai-sdk/openai';
import { createQwen } from 'qwen-ai-provider-v5';
describe('providers', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('providers 注册表', () => {
it('包含所有支持的 provider 类型', () => {
expect(providers).toHaveProperty('anthropic');
expect(providers).toHaveProperty('deepseek');
expect(providers).toHaveProperty('openai');
});
it('每个 provider 是一个工厂函数', () => {
expect(typeof providers.anthropic).toBe('function');
expect(typeof providers.deepseek).toBe('function');
expect(typeof providers.openai).toBe('function');
});
});
describe('Anthropic provider', () => {
it('创建 Anthropic 客户端', () => {
const factory = providers.anthropic({
apiKey: 'test-api-key',
});
expect(createAnthropic).toHaveBeenCalledWith({
apiKey: 'test-api-key',
baseURL: undefined,
});
expect(typeof factory).toBe('function');
});
it('支持自定义 baseUrl', () => {
providers.anthropic({
apiKey: 'test-api-key',
baseUrl: 'https://custom.anthropic.com',
});
expect(createAnthropic).toHaveBeenCalledWith({
apiKey: 'test-api-key',
baseURL: 'https://custom.anthropic.com',
});
});
it('返回的工厂函数可以创建模型', () => {
const factory = providers.anthropic({
apiKey: 'test-api-key',
});
const model = factory('claude-3-opus');
expect(model).toEqual({ modelId: 'anthropic:claude-3-opus' });
});
});
describe('DeepSeek provider', () => {
it('创建 DeepSeek 客户端', () => {
const factory = providers.deepseek({
apiKey: 'test-deepseek-key',
});
expect(createDeepSeek).toHaveBeenCalledWith({
apiKey: 'test-deepseek-key',
baseURL: undefined,
});
expect(typeof factory).toBe('function');
});
it('支持自定义 baseUrl', () => {
providers.deepseek({
apiKey: 'test-deepseek-key',
baseUrl: 'https://custom.deepseek.com',
});
expect(createDeepSeek).toHaveBeenCalledWith({
apiKey: 'test-deepseek-key',
baseURL: 'https://custom.deepseek.com',
});
});
it('返回的工厂函数可以创建模型', () => {
const factory = providers.deepseek({
apiKey: 'test-deepseek-key',
});
const model = factory('deepseek-chat');
expect(model).toEqual({ modelId: 'deepseek:deepseek-chat' });
});
});
describe('OpenAI provider', () => {
it('创建 OpenAI 客户端(标准 URL', () => {
const factory = providers.openai({
apiKey: 'test-openai-key',
});
expect(createOpenAI).toHaveBeenCalledWith({
apiKey: 'test-openai-key',
baseURL: undefined,
});
expect(createQwen).not.toHaveBeenCalled();
expect(typeof factory).toBe('function');
});
it('支持自定义 baseUrl(非 DashScope', () => {
providers.openai({
apiKey: 'test-openai-key',
baseUrl: 'https://custom.openai.com/v1',
});
expect(createOpenAI).toHaveBeenCalledWith({
apiKey: 'test-openai-key',
baseURL: 'https://custom.openai.com/v1',
});
expect(createQwen).not.toHaveBeenCalled();
});
it('返回的工厂函数可以创建模型', () => {
const factory = providers.openai({
apiKey: 'test-openai-key',
});
const model = factory('gpt-4');
expect(model).toEqual({ modelId: 'openai:gpt-4' });
});
});
describe('DashScope (Qwen) 检测', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('检测 dashscope URL 并使用 Qwen provider', () => {
providers.openai({
apiKey: 'test-qwen-key',
baseUrl: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
});
expect(createQwen).toHaveBeenCalledWith({
apiKey: 'test-qwen-key',
baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
});
expect(createOpenAI).not.toHaveBeenCalled();
});
it('检测包含 dashscope 的任意 URL', () => {
providers.openai({
apiKey: 'test-qwen-key',
baseUrl: 'https://api.dashscope.example.com/v1',
});
expect(createQwen).toHaveBeenCalled();
expect(createOpenAI).not.toHaveBeenCalled();
});
it('Qwen 工厂函数可以创建模型', () => {
const factory = providers.openai({
apiKey: 'test-qwen-key',
baseUrl: 'https://dashscope.aliyuncs.com/v1',
});
const model = factory('qwen-turbo');
expect(model).toEqual({ modelId: 'qwen:qwen-turbo' });
});
});
});
describe('getModelFactory', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('获取 Anthropic 模型工厂', () => {
const factory = getModelFactory('anthropic', {
apiKey: 'test-key',
});
expect(typeof factory).toBe('function');
expect(createAnthropic).toHaveBeenCalled();
});
it('获取 DeepSeek 模型工厂', () => {
const factory = getModelFactory('deepseek', {
apiKey: 'test-key',
});
expect(typeof factory).toBe('function');
expect(createDeepSeek).toHaveBeenCalled();
});
it('获取 OpenAI 模型工厂', () => {
const factory = getModelFactory('openai', {
apiKey: 'test-key',
});
expect(typeof factory).toBe('function');
expect(createOpenAI).toHaveBeenCalled();
});
it('传递正确的选项给 provider', () => {
getModelFactory('anthropic', {
apiKey: 'my-api-key',
baseUrl: 'https://my-proxy.com',
});
expect(createAnthropic).toHaveBeenCalledWith({
apiKey: 'my-api-key',
baseURL: 'https://my-proxy.com',
});
});
it('不支持的 provider 抛出错误', () => {
expect(() => {
getModelFactory('unsupported' as any, {
apiKey: 'test-key',
});
}).toThrow('不支持的 provider: unsupported');
});
it('返回的工厂函数可以创建模型实例', () => {
const factory = getModelFactory('anthropic', {
apiKey: 'test-key',
});
const model = factory('claude-3-sonnet');
expect(model).toEqual({ modelId: 'anthropic:claude-3-sonnet' });
});
});