| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- import { describe, it, expect, vi, beforeEach } from 'vitest';
- import { renderHook, waitFor } from '@testing-library/react';
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
- import { useFileManagement } from '../../src/hooks/useFileManagement';
- // 完整的mock响应对象
- const createMockResponse = (status: number, data?: any) => ({
- status,
- ok: status >= 200 && status < 300,
- body: null,
- bodyUsed: false,
- statusText: status === 200 ? 'OK' : status === 201 ? 'Created' : status === 204 ? 'No Content' : 'Error',
- headers: new Headers(),
- url: '',
- redirected: false,
- type: 'basic' as ResponseType,
- json: async () => data || {},
- text: async () => '',
- blob: async () => new Blob(),
- arrayBuffer: async () => new ArrayBuffer(0),
- formData: async () => new FormData(),
- clone: function() { return this; }
- });
- // Mock API客户端
- vi.mock('../../src/api/fileClient', () => {
- const mockFileClient = {
- index: {
- $get: vi.fn(() => Promise.resolve({ status: 200, body: null })),
- },
- ':id': {
- $get: vi.fn(() => Promise.resolve({ status: 200, body: null })),
- $put: vi.fn(() => Promise.resolve({ status: 200, body: null })),
- $delete: vi.fn(() => Promise.resolve({ status: 204, body: null })),
- },
- };
- const mockFileClientManager = {
- get: vi.fn(() => mockFileClient),
- };
- return {
- fileClientManager: mockFileClientManager,
- fileClient: mockFileClient,
- };
- });
- // Mock toast
- vi.mock('sonner', () => ({
- toast: {
- success: vi.fn(),
- error: vi.fn(),
- warning: vi.fn(),
- },
- }));
- describe('useFileManagement', () => {
- let queryClient: QueryClient;
- beforeEach(() => {
- queryClient = new QueryClient({
- defaultOptions: {
- queries: { retry: false },
- mutations: { retry: false },
- },
- });
- vi.clearAllMocks();
- });
- const wrapper = ({ children }: { children: React.ReactNode }) => (
- <QueryClientProvider client={queryClient}>
- {children}
- </QueryClientProvider>
- );
- const mockFiles = [
- {
- id: 1,
- name: 'test-file-1.jpg',
- type: 'image/jpeg',
- size: 1024,
- fullUrl: 'http://example.com/test-file-1.jpg',
- uploadTime: '2024-01-01T00:00:00Z',
- },
- {
- id: 2,
- name: 'test-file-2.pdf',
- type: 'application/pdf',
- size: 2048,
- fullUrl: 'http://example.com/test-file-2.pdf',
- uploadTime: '2024-01-01T00:00:00Z',
- },
- ];
- it('应该初始化文件管理钩子', () => {
- const { result } = renderHook(() => useFileManagement(), { wrapper });
- expect(result.current.files).toEqual([]);
- expect(result.current.isLoading).toBe(true);
- expect(result.current.searchText).toBe('');
- });
- it('应该获取文件列表', async () => {
- const { fileClient } = await import('../../src/api/fileClient');
- (fileClient.index.$get as any).mockResolvedValue(createMockResponse(200, {
- data: mockFiles,
- pagination: { current: 1, pageSize: 10, total: 2 }
- }));
- const { result } = renderHook(() => useFileManagement(), { wrapper });
- await waitFor(() => {
- expect(result.current.isLoading).toBe(false);
- });
- expect(result.current.files).toEqual(mockFiles);
- expect(result.current.pagination.total).toBe(2);
- });
- it('应该处理搜索', async () => {
- const { fileClient } = await import('../../src/api/fileClient');
- (fileClient.index.$get as any).mockResolvedValue(createMockResponse(200, {
- data: [mockFiles[0]],
- pagination: { current: 1, pageSize: 10, total: 1 }
- }));
- const { result } = renderHook(() => useFileManagement(), { wrapper });
- result.current.handleSearch('test');
- await waitFor(() => {
- expect(result.current.searchText).toBe('test');
- });
- expect(fileClient.index.$get).toHaveBeenCalledWith({
- query: {
- page: 1,
- pageSize: 10,
- keyword: 'test'
- }
- });
- });
- it('应该处理分页', async () => {
- const { fileClient } = await import('../../src/api/fileClient');
- (fileClient.index.$get as any).mockResolvedValue(createMockResponse(200, {
- data: mockFiles,
- pagination: { current: 2, pageSize: 5, total: 2 }
- }));
- const { result } = renderHook(() => useFileManagement(), { wrapper });
- result.current.handlePageChange(2, 5);
- await waitFor(() => {
- expect(result.current.pagination.current).toBe(2);
- expect(result.current.pagination.pageSize).toBe(5);
- });
- });
- it('应该更新文件信息', async () => {
- const { fileClient } = await import('../../src/api/fileClient');
- const { toast } = await import('sonner');
- (fileClient[':id'].$put as any).mockResolvedValue(createMockResponse(200, {
- id: 1,
- name: 'updated-file.jpg',
- description: 'Updated description'
- }));
- const { result } = renderHook(() => useFileManagement(), { wrapper });
- await result.current.updateFile({
- id: 1,
- data: {
- name: 'updated-file.jpg',
- description: 'Updated description'
- }
- });
- expect(fileClient[':id'].$put).toHaveBeenCalledWith({
- param: { id: 1 },
- json: {
- name: 'updated-file.jpg',
- description: 'Updated description'
- }
- });
- expect(toast.success).toHaveBeenCalledWith('文件信息更新成功');
- });
- it('应该删除文件', async () => {
- const { fileClient } = await import('../../src/api/fileClient');
- const { toast } = await import('sonner');
- (fileClient[':id'].$delete as any).mockResolvedValue(createMockResponse(204));
- const { result } = renderHook(() => useFileManagement(), { wrapper });
- await result.current.deleteFile(1);
- expect(fileClient[':id'].$delete).toHaveBeenCalledWith({
- param: { id: 1 }
- });
- expect(toast.success).toHaveBeenCalledWith('文件删除成功');
- });
- it('应该检查文件是否可预览', () => {
- const { result } = renderHook(() => useFileManagement(), { wrapper });
- expect(result.current.isPreviewable('image/jpeg')).toBe(true);
- expect(result.current.isPreviewable('video/mp4')).toBe(true);
- expect(result.current.isPreviewable('application/pdf')).toBe(false);
- expect(result.current.isPreviewable(null)).toBe(false);
- });
- it('应该处理文件预览', () => {
- const { result } = renderHook(() => useFileManagement(), { wrapper });
- const windowOpenSpy = vi.spyOn(window, 'open').mockImplementation(() => null);
- const file = {
- id: 1,
- name: 'test.jpg',
- type: 'image/jpeg',
- fullUrl: 'http://example.com/test.jpg'
- } as any;
- result.current.handlePreview(file);
- expect(windowOpenSpy).toHaveBeenCalledWith('http://example.com/test.jpg', '_blank');
- windowOpenSpy.mockRestore();
- });
- it('应该处理文件下载', () => {
- const { result } = renderHook(() => useFileManagement(), { wrapper });
- const createElementSpy = vi.spyOn(document, 'createElement');
- const appendChildSpy = vi.spyOn(document.body, 'appendChild');
- const removeChildSpy = vi.spyOn(document.body, 'removeChild');
- const file = {
- id: 1,
- name: 'test.jpg',
- fullUrl: 'http://example.com/test.jpg'
- } as any;
- result.current.handleDownload(file);
- expect(createElementSpy).toHaveBeenCalledWith('a');
- expect(appendChildSpy).toHaveBeenCalled();
- expect(removeChildSpy).toHaveBeenCalled();
- createElementSpy.mockRestore();
- appendChildSpy.mockRestore();
- removeChildSpy.mockRestore();
- });
- });
|