import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import FileSelector from '../../src/components/FileSelector';
// Mock API客户端
vi.mock('../../src/api/fileClient', () => ({
fileClient: {
$get: vi.fn(),
':id': {
$get: vi.fn(),
},
},
}));
// Mock 文件上传组件
vi.mock('../../src/components/MinioUploader', () => ({
default: () =>
MinioUploader
,
}));
describe('FileSelector', () => {
let queryClient: QueryClient;
beforeEach(() => {
queryClient = new QueryClient({
defaultOptions: {
queries: { retry: false },
mutations: { retry: false },
},
});
vi.clearAllMocks();
});
const renderWithQueryClient = (component: React.ReactElement) => {
return render(
{component}
);
};
const mockFiles = [
{
id: 1,
name: 'test-image.jpg',
type: 'image/jpeg',
size: 1024,
fullUrl: 'http://example.com/test-image.jpg',
uploadTime: '2024-01-01T00:00:00Z',
},
{
id: 2,
name: 'test-document.pdf',
type: 'application/pdf',
size: 2048,
fullUrl: 'http://example.com/test-document.pdf',
uploadTime: '2024-01-01T00:00:00Z',
},
];
it('应该渲染文件选择器', () => {
renderWithQueryClient(
{}} />
);
expect(screen.getByText('选择文件')).toBeInTheDocument();
});
it('应该打开选择对话框', async () => {
const { fileClient } = require('../../src/api/fileClient');
fileClient.$get.mockResolvedValue({
ok: true,
json: async () => ({
data: mockFiles,
pagination: { current: 1, pageSize: 50, total: 2 }
})
});
renderWithQueryClient(
{}} />
);
const selectButton = screen.getByText('选择文件');
fireEvent.click(selectButton);
await waitFor(() => {
expect(screen.getByText('选择文件')).toBeInTheDocument();
expect(screen.getByText('上传新文件或从已有文件中选择')).toBeInTheDocument();
});
});
it('应该显示已选文件预览', async () => {
const { fileClient } = require('../../src/api/fileClient');
fileClient[':id'].$get.mockResolvedValue({
ok: true,
json: async () => mockFiles[0]
});
renderWithQueryClient(
{}} showPreview={true} />
);
await waitFor(() => {
expect(screen.getByText('更换文件')).toBeInTheDocument();
});
});
it('应该支持多选模式', async () => {
const { fileClient } = require('../../src/api/fileClient');
fileClient.$get.mockResolvedValue({
ok: true,
json: async () => ({
data: mockFiles,
pagination: { current: 1, pageSize: 50, total: 2 }
})
});
const onChange = vi.fn();
renderWithQueryClient(
);
await waitFor(() => {
expect(screen.getByText('已选择 2 个文件')).toBeInTheDocument();
});
});
it('应该过滤文件类型', async () => {
const { fileClient } = require('../../src/api/fileClient');
fileClient.$get.mockResolvedValue({
ok: true,
json: async () => ({
data: mockFiles,
pagination: { current: 1, pageSize: 50, total: 2 }
})
});
renderWithQueryClient(
{}}
filterType="image"
/>
);
const selectButton = screen.getByText('选择文件');
fireEvent.click(selectButton);
await waitFor(() => {
expect(fileClient.$get).toHaveBeenCalledWith({
query: {
page: 1,
pageSize: 50,
keyword: 'image'
}
});
});
});
it('应该处理文件选择确认', async () => {
const { fileClient } = require('../../src/api/fileClient');
fileClient.$get.mockResolvedValue({
ok: true,
json: async () => ({
data: mockFiles,
pagination: { current: 1, pageSize: 50, total: 2 }
})
});
const onChange = vi.fn();
renderWithQueryClient(
);
const selectButton = screen.getByText('选择文件');
fireEvent.click(selectButton);
await waitFor(() => {
const fileItems = screen.getAllByText('test-image.jpg');
fireEvent.click(fileItems[0]);
});
const confirmButton = screen.getByText('确认选择');
fireEvent.click(confirmButton);
expect(onChange).toHaveBeenCalledWith(1);
});
});