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:
@@ -1,11 +1,21 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import {
|
||||
isImagePath,
|
||||
extractImageReferences,
|
||||
formatFileSize,
|
||||
loadImage,
|
||||
loadImages,
|
||||
IMAGE_EXTENSIONS,
|
||||
} from '../../../src/utils/image.js';
|
||||
|
||||
// Mock fs/promises
|
||||
vi.mock('fs/promises', () => ({
|
||||
readFile: vi.fn(),
|
||||
stat: vi.fn(),
|
||||
}));
|
||||
|
||||
import * as fs from 'fs/promises';
|
||||
|
||||
describe('Image Utils - 图片处理工具', () => {
|
||||
describe('IMAGE_EXTENSIONS', () => {
|
||||
it('包含常见图片扩展名', () => {
|
||||
@@ -152,4 +162,200 @@ describe('Image Utils - 图片处理工具', () => {
|
||||
expect(formatFileSize(1024 * 1024 * 1024)).toBe('1024.0MB');
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadImage - 加载图片文件', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('成功加载 PNG 图片', async () => {
|
||||
const mockBuffer = Buffer.from('fake image data');
|
||||
vi.mocked(fs.readFile).mockResolvedValue(mockBuffer);
|
||||
vi.mocked(fs.stat).mockResolvedValue({ size: mockBuffer.length } as any);
|
||||
|
||||
const result = await loadImage('/test/image.png');
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.image).toBeDefined();
|
||||
expect(result.image?.filename).toBe('image.png');
|
||||
expect(result.image?.extension).toBe('.png');
|
||||
expect(result.image?.mimeType).toBe('image/png');
|
||||
expect(result.image?.base64).toBe(mockBuffer.toString('base64'));
|
||||
});
|
||||
|
||||
it('成功加载 JPG 图片', async () => {
|
||||
const mockBuffer = Buffer.from('fake jpg data');
|
||||
vi.mocked(fs.readFile).mockResolvedValue(mockBuffer);
|
||||
vi.mocked(fs.stat).mockResolvedValue({ size: mockBuffer.length } as any);
|
||||
|
||||
const result = await loadImage('/test/photo.jpg');
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.image?.mimeType).toBe('image/jpeg');
|
||||
});
|
||||
|
||||
it('成功加载 JPEG 图片', async () => {
|
||||
const mockBuffer = Buffer.from('fake jpeg data');
|
||||
vi.mocked(fs.readFile).mockResolvedValue(mockBuffer);
|
||||
vi.mocked(fs.stat).mockResolvedValue({ size: mockBuffer.length } as any);
|
||||
|
||||
const result = await loadImage('/test/photo.jpeg');
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.image?.mimeType).toBe('image/jpeg');
|
||||
});
|
||||
|
||||
it('成功加载 GIF 图片', async () => {
|
||||
const mockBuffer = Buffer.from('fake gif data');
|
||||
vi.mocked(fs.readFile).mockResolvedValue(mockBuffer);
|
||||
vi.mocked(fs.stat).mockResolvedValue({ size: mockBuffer.length } as any);
|
||||
|
||||
const result = await loadImage('/test/animation.gif');
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.image?.mimeType).toBe('image/gif');
|
||||
});
|
||||
|
||||
it('成功加载 WebP 图片', async () => {
|
||||
const mockBuffer = Buffer.from('fake webp data');
|
||||
vi.mocked(fs.readFile).mockResolvedValue(mockBuffer);
|
||||
vi.mocked(fs.stat).mockResolvedValue({ size: mockBuffer.length } as any);
|
||||
|
||||
const result = await loadImage('/test/modern.webp');
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.image?.mimeType).toBe('image/webp');
|
||||
});
|
||||
|
||||
it('返回正确的 dataUrl', async () => {
|
||||
const mockBuffer = Buffer.from('test data');
|
||||
vi.mocked(fs.readFile).mockResolvedValue(mockBuffer);
|
||||
vi.mocked(fs.stat).mockResolvedValue({ size: mockBuffer.length } as any);
|
||||
|
||||
const result = await loadImage('/test/image.png');
|
||||
|
||||
expect(result.image?.dataUrl).toBe(
|
||||
`data:image/png;base64,${mockBuffer.toString('base64')}`
|
||||
);
|
||||
});
|
||||
|
||||
it('不支持的格式返回错误', async () => {
|
||||
const result = await loadImage('/test/document.txt');
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toContain('不支持的图片格式');
|
||||
expect(result.error).toContain('.txt');
|
||||
});
|
||||
|
||||
it('文件不存在返回错误', async () => {
|
||||
const error = new Error('File not found');
|
||||
(error as any).code = 'ENOENT';
|
||||
vi.mocked(fs.readFile).mockRejectedValue(error);
|
||||
|
||||
const result = await loadImage('/nonexistent/image.png');
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toContain('图片文件不存在');
|
||||
});
|
||||
|
||||
it('读取文件错误返回错误信息', async () => {
|
||||
vi.mocked(fs.readFile).mockRejectedValue(new Error('Permission denied'));
|
||||
|
||||
const result = await loadImage('/test/image.png');
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toContain('加载图片失败');
|
||||
expect(result.error).toContain('Permission denied');
|
||||
});
|
||||
|
||||
it('处理相对路径', async () => {
|
||||
const mockBuffer = Buffer.from('test');
|
||||
vi.mocked(fs.readFile).mockResolvedValue(mockBuffer);
|
||||
vi.mocked(fs.stat).mockResolvedValue({ size: mockBuffer.length } as any);
|
||||
|
||||
const result = await loadImage('./relative/image.png', '/workdir');
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(fs.readFile).toHaveBeenCalledWith(
|
||||
expect.stringContaining('relative/image.png')
|
||||
);
|
||||
});
|
||||
|
||||
it('处理大写扩展名', async () => {
|
||||
const mockBuffer = Buffer.from('test');
|
||||
vi.mocked(fs.readFile).mockResolvedValue(mockBuffer);
|
||||
vi.mocked(fs.stat).mockResolvedValue({ size: mockBuffer.length } as any);
|
||||
|
||||
const result = await loadImage('/test/image.PNG');
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.image?.mimeType).toBe('image/png');
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadImages - 批量加载图片', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('成功加载多张图片', async () => {
|
||||
const mockBuffer = Buffer.from('test');
|
||||
vi.mocked(fs.readFile).mockResolvedValue(mockBuffer);
|
||||
vi.mocked(fs.stat).mockResolvedValue({ size: mockBuffer.length } as any);
|
||||
|
||||
const result = await loadImages(['/test/a.png', '/test/b.jpg']);
|
||||
|
||||
expect(result.images).toHaveLength(2);
|
||||
expect(result.errors).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('部分加载失败返回错误列表', async () => {
|
||||
const mockBuffer = Buffer.from('test');
|
||||
vi.mocked(fs.readFile).mockImplementation((path) => {
|
||||
if (String(path).includes('good')) {
|
||||
return Promise.resolve(mockBuffer);
|
||||
}
|
||||
const error = new Error('Not found');
|
||||
(error as any).code = 'ENOENT';
|
||||
return Promise.reject(error);
|
||||
});
|
||||
vi.mocked(fs.stat).mockResolvedValue({ size: mockBuffer.length } as any);
|
||||
|
||||
const result = await loadImages(['/test/good.png', '/test/bad.png']);
|
||||
|
||||
expect(result.images).toHaveLength(1);
|
||||
expect(result.errors).toHaveLength(1);
|
||||
expect(result.errors[0].path).toBe('/test/bad.png');
|
||||
});
|
||||
|
||||
it('空列表返回空结果', async () => {
|
||||
const result = await loadImages([]);
|
||||
|
||||
expect(result.images).toHaveLength(0);
|
||||
expect(result.errors).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('全部加载失败时 images 为空', async () => {
|
||||
const error = new Error('Not found');
|
||||
(error as any).code = 'ENOENT';
|
||||
vi.mocked(fs.readFile).mockRejectedValue(error);
|
||||
|
||||
const result = await loadImages(['/test/a.png', '/test/b.png']);
|
||||
|
||||
expect(result.images).toHaveLength(0);
|
||||
expect(result.errors).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('使用自定义工作目录', async () => {
|
||||
const mockBuffer = Buffer.from('test');
|
||||
vi.mocked(fs.readFile).mockResolvedValue(mockBuffer);
|
||||
vi.mocked(fs.stat).mockResolvedValue({ size: mockBuffer.length } as any);
|
||||
|
||||
await loadImages(['./image.png'], '/custom/workdir');
|
||||
|
||||
expect(fs.readFile).toHaveBeenCalledWith(
|
||||
expect.stringContaining('custom/workdir')
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user