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:
@@ -9,7 +9,7 @@ vi.mock('fs', () => ({
|
||||
}));
|
||||
|
||||
import * as fs from 'fs';
|
||||
import { getConfig, loadConfig, saveConfig } from '../../../src/utils/config.js';
|
||||
import { getConfig, loadConfig, saveConfig, loadVisionConfig } from '../../../src/utils/config.js';
|
||||
|
||||
describe('Config - 配置管理', () => {
|
||||
const originalEnv = { ...process.env };
|
||||
@@ -20,8 +20,14 @@ describe('Config - 配置管理', () => {
|
||||
delete process.env.AI_PROVIDER;
|
||||
delete process.env.ANTHROPIC_API_KEY;
|
||||
delete process.env.DEEPSEEK_API_KEY;
|
||||
delete process.env.OPENAI_API_KEY;
|
||||
delete process.env.AI_MODEL;
|
||||
delete process.env.AI_MAX_TOKENS;
|
||||
delete process.env.AI_BASE_URL;
|
||||
delete process.env.VISION_PROVIDER;
|
||||
delete process.env.VISION_MODEL;
|
||||
delete process.env.VISION_API_KEY;
|
||||
delete process.env.VISION_BASE_URL;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -192,4 +198,160 @@ describe('Config - 配置管理', () => {
|
||||
expect(fs.mkdirSync).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadConfig - baseUrl 支持', () => {
|
||||
it('从环境变量获取 baseUrl', () => {
|
||||
process.env.ANTHROPIC_API_KEY = 'test-key';
|
||||
process.env.AI_BASE_URL = 'https://custom.api.com/v1';
|
||||
vi.mocked(fs.existsSync).mockReturnValue(false);
|
||||
|
||||
const config = loadConfig();
|
||||
|
||||
expect(config.baseUrl).toBe('https://custom.api.com/v1');
|
||||
});
|
||||
|
||||
it('从配置文件获取 baseUrl', () => {
|
||||
process.env.ANTHROPIC_API_KEY = 'test-key';
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({
|
||||
baseUrl: 'https://stored.api.com/v1',
|
||||
}));
|
||||
|
||||
const config = loadConfig();
|
||||
|
||||
expect(config.baseUrl).toBe('https://stored.api.com/v1');
|
||||
});
|
||||
|
||||
it('环境变量 baseUrl 优先于配置文件', () => {
|
||||
process.env.ANTHROPIC_API_KEY = 'test-key';
|
||||
process.env.AI_BASE_URL = 'https://env.api.com/v1';
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({
|
||||
baseUrl: 'https://stored.api.com/v1',
|
||||
}));
|
||||
|
||||
const config = loadConfig();
|
||||
|
||||
expect(config.baseUrl).toBe('https://env.api.com/v1');
|
||||
});
|
||||
|
||||
it('OpenAI provider 支持 baseUrl', () => {
|
||||
process.env.AI_PROVIDER = 'openai';
|
||||
process.env.OPENAI_API_KEY = 'test-openai-key';
|
||||
process.env.AI_BASE_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1';
|
||||
vi.mocked(fs.existsSync).mockReturnValue(false);
|
||||
|
||||
const config = loadConfig();
|
||||
|
||||
expect(config.provider).toBe('openai');
|
||||
expect(config.baseUrl).toBe('https://dashscope.aliyuncs.com/compatible-mode/v1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadVisionConfig - Vision 配置', () => {
|
||||
it('返回 null 当没有配置 Vision API Key', () => {
|
||||
vi.mocked(fs.existsSync).mockReturnValue(false);
|
||||
|
||||
const visionConfig = loadVisionConfig();
|
||||
|
||||
expect(visionConfig).toBeNull();
|
||||
});
|
||||
|
||||
it('从环境变量获取 Vision 配置', () => {
|
||||
process.env.VISION_PROVIDER = 'openai';
|
||||
process.env.VISION_API_KEY = 'vision-api-key';
|
||||
process.env.VISION_MODEL = 'gpt-4-vision';
|
||||
vi.mocked(fs.existsSync).mockReturnValue(false);
|
||||
|
||||
const visionConfig = loadVisionConfig();
|
||||
|
||||
expect(visionConfig).not.toBeNull();
|
||||
expect(visionConfig?.provider).toBe('openai');
|
||||
expect(visionConfig?.apiKey).toBe('vision-api-key');
|
||||
expect(visionConfig?.model).toBe('gpt-4-vision');
|
||||
});
|
||||
|
||||
it('从配置文件获取 Vision 配置', () => {
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({
|
||||
visionProvider: 'anthropic',
|
||||
visionApiKey: 'stored-vision-key',
|
||||
visionModel: 'claude-3-opus',
|
||||
}));
|
||||
|
||||
const visionConfig = loadVisionConfig();
|
||||
|
||||
expect(visionConfig).not.toBeNull();
|
||||
expect(visionConfig?.provider).toBe('anthropic');
|
||||
expect(visionConfig?.apiKey).toBe('stored-vision-key');
|
||||
expect(visionConfig?.model).toBe('claude-3-opus');
|
||||
});
|
||||
|
||||
it('回退到对应 provider 的 API Key', () => {
|
||||
process.env.ANTHROPIC_API_KEY = 'anthropic-main-key';
|
||||
vi.mocked(fs.existsSync).mockReturnValue(false);
|
||||
|
||||
const visionConfig = loadVisionConfig();
|
||||
|
||||
expect(visionConfig).not.toBeNull();
|
||||
expect(visionConfig?.provider).toBe('anthropic'); // 默认
|
||||
expect(visionConfig?.apiKey).toBe('anthropic-main-key'); // 回退
|
||||
});
|
||||
|
||||
it('Vision baseUrl 配置', () => {
|
||||
process.env.VISION_PROVIDER = 'openai';
|
||||
process.env.VISION_API_KEY = 'vision-key';
|
||||
process.env.VISION_BASE_URL = 'https://vision.api.com/v1';
|
||||
vi.mocked(fs.existsSync).mockReturnValue(false);
|
||||
|
||||
const visionConfig = loadVisionConfig();
|
||||
|
||||
expect(visionConfig?.baseUrl).toBe('https://vision.api.com/v1');
|
||||
});
|
||||
|
||||
it('从配置文件回退到 deepseek API key', () => {
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({
|
||||
visionProvider: 'deepseek',
|
||||
deepseekApiKey: 'deepseek-stored-key',
|
||||
}));
|
||||
|
||||
const visionConfig = loadVisionConfig();
|
||||
|
||||
expect(visionConfig?.provider).toBe('deepseek');
|
||||
expect(visionConfig?.apiKey).toBe('deepseek-stored-key');
|
||||
});
|
||||
|
||||
it('从配置文件回退到 openai API key', () => {
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({
|
||||
visionProvider: 'openai',
|
||||
openaiApiKey: 'openai-stored-key',
|
||||
}));
|
||||
|
||||
const visionConfig = loadVisionConfig();
|
||||
|
||||
expect(visionConfig?.provider).toBe('openai');
|
||||
expect(visionConfig?.apiKey).toBe('openai-stored-key');
|
||||
});
|
||||
|
||||
it('使用默认 Vision 模型', () => {
|
||||
process.env.ANTHROPIC_API_KEY = 'test-key';
|
||||
vi.mocked(fs.existsSync).mockReturnValue(false);
|
||||
|
||||
const visionConfig = loadVisionConfig();
|
||||
|
||||
expect(visionConfig?.model).toBe('claude-sonnet-4-20250514');
|
||||
});
|
||||
|
||||
it('Vision 专用 key 优先于 provider key', () => {
|
||||
process.env.ANTHROPIC_API_KEY = 'anthropic-main-key';
|
||||
process.env.VISION_API_KEY = 'vision-specific-key';
|
||||
vi.mocked(fs.existsSync).mockReturnValue(false);
|
||||
|
||||
const visionConfig = loadVisionConfig();
|
||||
|
||||
expect(visionConfig?.apiKey).toBe('vision-specific-key');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user