useFileManagement.test.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. import { describe, it, expect, vi, beforeEach } from 'vitest';
  2. import { renderHook, waitFor } from '@testing-library/react';
  3. import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
  4. import { useFileManagement } from '../../src/hooks/useFileManagement';
  5. // Mock API客户端
  6. vi.mock('../../src/api/fileClient', () => ({
  7. fileClient: {
  8. $get: vi.fn(),
  9. ':id': {
  10. $put: vi.fn(),
  11. $delete: vi.fn(),
  12. },
  13. },
  14. }));
  15. // Mock toast
  16. vi.mock('sonner', () => ({
  17. toast: {
  18. success: vi.fn(),
  19. error: vi.fn(),
  20. warning: vi.fn(),
  21. },
  22. }));
  23. describe('useFileManagement', () => {
  24. let queryClient: QueryClient;
  25. beforeEach(() => {
  26. queryClient = new QueryClient({
  27. defaultOptions: {
  28. queries: { retry: false },
  29. mutations: { retry: false },
  30. },
  31. });
  32. vi.clearAllMocks();
  33. });
  34. const wrapper = ({ children }: { children: React.ReactNode }) => (
  35. <QueryClientProvider client={queryClient}>
  36. {children}
  37. </QueryClientProvider>
  38. );
  39. const mockFiles = [
  40. {
  41. id: 1,
  42. name: 'test-file-1.jpg',
  43. type: 'image/jpeg',
  44. size: 1024,
  45. fullUrl: 'http://example.com/test-file-1.jpg',
  46. uploadTime: '2024-01-01T00:00:00Z',
  47. },
  48. {
  49. id: 2,
  50. name: 'test-file-2.pdf',
  51. type: 'application/pdf',
  52. size: 2048,
  53. fullUrl: 'http://example.com/test-file-2.pdf',
  54. uploadTime: '2024-01-01T00:00:00Z',
  55. },
  56. ];
  57. it('应该初始化文件管理钩子', () => {
  58. const { result } = renderHook(() => useFileManagement(), { wrapper });
  59. expect(result.current.files).toEqual([]);
  60. expect(result.current.isLoading).toBe(true);
  61. expect(result.current.searchText).toBe('');
  62. });
  63. it('应该获取文件列表', async () => {
  64. const { fileClient } = require('../../src/api/fileClient');
  65. fileClient.$get.mockResolvedValue({
  66. ok: true,
  67. json: async () => ({
  68. data: mockFiles,
  69. pagination: { current: 1, pageSize: 10, total: 2 }
  70. })
  71. });
  72. const { result } = renderHook(() => useFileManagement(), { wrapper });
  73. await waitFor(() => {
  74. expect(result.current.isLoading).toBe(false);
  75. });
  76. expect(result.current.files).toEqual(mockFiles);
  77. expect(result.current.pagination.total).toBe(2);
  78. });
  79. it('应该处理搜索', async () => {
  80. const { fileClient } = require('../../src/api/fileClient');
  81. fileClient.$get.mockResolvedValue({
  82. ok: true,
  83. json: async () => ({
  84. data: [mockFiles[0]],
  85. pagination: { current: 1, pageSize: 10, total: 1 }
  86. })
  87. });
  88. const { result } = renderHook(() => useFileManagement(), { wrapper });
  89. result.current.handleSearch('test');
  90. await waitFor(() => {
  91. expect(result.current.searchText).toBe('test');
  92. });
  93. expect(fileClient.$get).toHaveBeenCalledWith({
  94. query: {
  95. page: 1,
  96. pageSize: 10,
  97. keyword: 'test'
  98. }
  99. });
  100. });
  101. it('应该处理分页', async () => {
  102. const { fileClient } = require('../../src/api/fileClient');
  103. fileClient.$get.mockResolvedValue({
  104. ok: true,
  105. json: async () => ({
  106. data: mockFiles,
  107. pagination: { current: 2, pageSize: 5, total: 2 }
  108. })
  109. });
  110. const { result } = renderHook(() => useFileManagement(), { wrapper });
  111. result.current.handlePageChange(2, 5);
  112. await waitFor(() => {
  113. expect(result.current.pagination.current).toBe(2);
  114. expect(result.current.pagination.pageSize).toBe(5);
  115. });
  116. });
  117. it('应该更新文件信息', async () => {
  118. const { fileClient } = require('../../src/api/fileClient');
  119. const { toast } = require('sonner');
  120. fileClient[':id'].$put.mockResolvedValue({
  121. ok: true,
  122. json: async () => ({
  123. id: 1,
  124. name: 'updated-file.jpg',
  125. description: 'Updated description'
  126. })
  127. });
  128. const { result } = renderHook(() => useFileManagement(), { wrapper });
  129. await result.current.updateFile({
  130. id: 1,
  131. data: {
  132. name: 'updated-file.jpg',
  133. description: 'Updated description'
  134. }
  135. });
  136. expect(fileClient[':id'].$put).toHaveBeenCalledWith({
  137. param: { id: 1 },
  138. json: {
  139. name: 'updated-file.jpg',
  140. description: 'Updated description'
  141. }
  142. });
  143. expect(toast.success).toHaveBeenCalledWith('文件信息更新成功');
  144. });
  145. it('应该删除文件', async () => {
  146. const { fileClient } = require('../../src/api/fileClient');
  147. const { toast } = require('sonner');
  148. fileClient[':id'].$delete.mockResolvedValue({
  149. ok: true
  150. });
  151. const { result } = renderHook(() => useFileManagement(), { wrapper });
  152. await result.current.deleteFile(1);
  153. expect(fileClient[':id'].$delete).toHaveBeenCalledWith({
  154. param: { id: 1 }
  155. });
  156. expect(toast.success).toHaveBeenCalledWith('文件删除成功');
  157. });
  158. it('应该检查文件是否可预览', () => {
  159. const { result } = renderHook(() => useFileManagement(), { wrapper });
  160. expect(result.current.isPreviewable('image/jpeg')).toBe(true);
  161. expect(result.current.isPreviewable('video/mp4')).toBe(true);
  162. expect(result.current.isPreviewable('application/pdf')).toBe(false);
  163. expect(result.current.isPreviewable(null)).toBe(false);
  164. });
  165. it('应该处理文件预览', () => {
  166. const { result } = renderHook(() => useFileManagement(), { wrapper });
  167. const windowOpenSpy = vi.spyOn(window, 'open').mockImplementation(() => null);
  168. const file = {
  169. id: 1,
  170. name: 'test.jpg',
  171. type: 'image/jpeg',
  172. fullUrl: 'http://example.com/test.jpg'
  173. } as any;
  174. result.current.handlePreview(file);
  175. expect(windowOpenSpy).toHaveBeenCalledWith('http://example.com/test.jpg', '_blank');
  176. windowOpenSpy.mockRestore();
  177. });
  178. it('应该处理文件下载', () => {
  179. const { result } = renderHook(() => useFileManagement(), { wrapper });
  180. const createElementSpy = vi.spyOn(document, 'createElement');
  181. const appendChildSpy = vi.spyOn(document.body, 'appendChild');
  182. const removeChildSpy = vi.spyOn(document.body, 'removeChild');
  183. const file = {
  184. id: 1,
  185. name: 'test.jpg',
  186. fullUrl: 'http://example.com/test.jpg'
  187. } as any;
  188. result.current.handleDownload(file);
  189. expect(createElementSpy).toHaveBeenCalledWith('a');
  190. expect(appendChildSpy).toHaveBeenCalled();
  191. expect(removeChildSpy).toHaveBeenCalled();
  192. createElementSpy.mockRestore();
  193. appendChildSpy.mockRestore();
  194. removeChildSpy.mockRestore();
  195. });
  196. });