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 { SystemConfigManagement } from '../../src/components/SystemConfigManagement'; import { systemConfigClientManager } from '../../src/api/systemConfigClient'; // 完整的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 client vi.mock('../../src/api/systemConfigClient', () => { const mockSystemConfigClient = { index: { $get: vi.fn(() => Promise.resolve(createMockResponse(200, { data: [ { id: 1, configKey: 'wx.mini.app.id', configValue: 'wx1234567890', description: '微信小程序AppID', tenantId: 1, createdBy: 1, updatedBy: 1, createdAt: '2024-01-01T00:00:00Z', updatedAt: '2024-01-01T00:00:00Z' } ], pagination: { page: 1, pageSize: 10, total: 1, totalPages: 1 } }))), $post: vi.fn(() => Promise.resolve(createMockResponse(201, { id: 2, configKey: 'wx.mini.app.secret', configValue: 'secret123' }))), }, ':id': { $put: vi.fn(() => Promise.resolve(createMockResponse(200, { id: 1, configKey: 'wx.mini.app.id', configValue: 'updated_value' }))), $delete: vi.fn(() => Promise.resolve(createMockResponse(204))), }, }; const mockSystemConfigClientManager = { get: vi.fn(() => mockSystemConfigClient), }; return { systemConfigClientManager: mockSystemConfigClientManager, systemConfigClient: mockSystemConfigClient, }; }); // Mock toast vi.mock('sonner', () => ({ toast: { success: vi.fn(() => {}), error: vi.fn(() => {}), }, })); const createTestQueryClient = () => new QueryClient({ defaultOptions: { queries: { retry: false, }, }, }); const renderWithProviders = (component: React.ReactElement) => { const queryClient = createTestQueryClient(); return render( {component as any} ); }; describe('系统配置管理集成测试', () => { beforeEach(() => { vi.clearAllMocks(); }); it('应该完成完整的系统配置CRUD流程', async () => { const mockSystemConfigs = { data: [ { id: 1, configKey: 'wx.mini.app.id', configValue: 'wx1234567890', description: '微信小程序AppID', tenantId: 1, createdBy: 1, updatedBy: 1, createdAt: '2024-01-01T00:00:00Z', updatedAt: '2024-01-01T00:00:00Z' }, ], pagination: { total: 1, page: 1, pageSize: 10, }, }; const { toast } = await import('sonner'); // Mock initial system config list const client = systemConfigClientManager.get(); (client.index.$get as any).mockResolvedValue({ ...createMockResponse(200), json: async () => mockSystemConfigs }); renderWithProviders(); // Wait for initial data to load await waitFor(() => { expect(screen.getByText('wx.mini.app.id')).toBeInTheDocument(); }); // Test create system config const createButton = screen.getByText('创建配置'); fireEvent.click(createButton); // Fill create form const configKeyInput = screen.getByTestId('config-key-input'); const configValueInput = screen.getByTestId('config-value-input'); const descriptionInput = screen.getByTestId('description-input'); fireEvent.change(configKeyInput, { target: { value: 'wx.mini.app.secret' } }); fireEvent.change(configValueInput, { target: { value: 'secret123' } }); fireEvent.change(descriptionInput, { target: { value: '微信小程序AppSecret' } }); // Mock successful creation (client.index.$post as any).mockResolvedValue(createMockResponse(201, { id: 2, configKey: 'wx.mini.app.secret', configValue: 'secret123' })); const submitButton = screen.getByTestId('create-submit-button'); fireEvent.click(submitButton); await waitFor(() => { expect(client.index.$post).toHaveBeenCalledWith({ json: { configKey: 'wx.mini.app.secret', configValue: 'secret123', description: '微信小程序AppSecret' }, }); expect(toast.success).toHaveBeenCalledWith('系统配置创建成功'); }); // Test edit system config const editButton = screen.getByTestId('edit-button-1'); fireEvent.click(editButton); // Verify edit form is populated await waitFor(() => { expect(screen.getByDisplayValue('wx.mini.app.id')).toBeInTheDocument(); }); // Update system config const updateConfigValueInput = screen.getByDisplayValue('wx1234567890'); fireEvent.change(updateConfigValueInput, { target: { value: 'updated_value' } }); // Mock successful update (client[':id']['$put'] as any).mockResolvedValue(createMockResponse(200)); const updateButton = screen.getByTestId('update-submit-button'); fireEvent.click(updateButton); await waitFor(() => { expect(client[':id']['$put']).toHaveBeenCalledWith({ param: { id: 1 }, json: { configKey: 'wx.mini.app.id', configValue: 'updated_value', description: '微信小程序AppID' }, }); expect(toast.success).toHaveBeenCalledWith('系统配置更新成功'); }); // Test delete system config const deleteButton = screen.getByTestId('delete-button-1'); fireEvent.click(deleteButton); // Confirm deletion expect(screen.getByText('确认删除')).toBeInTheDocument(); // Mock successful deletion (client[':id']['$delete'] as any).mockResolvedValue({ status: 204, ok: true, body: null, bodyUsed: false, statusText: 'No Content', headers: new Headers(), url: '', redirected: false, type: 'basic' as ResponseType, json: async () => ({}), text: async () => '', blob: async () => new Blob(), arrayBuffer: async () => new ArrayBuffer(0), formData: async () => new FormData(), clone: function() { return this; } }); const confirmDeleteButton = screen.getByTestId('confirm-delete-button'); fireEvent.click(confirmDeleteButton); await waitFor(() => { expect(client[':id']['$delete']).toHaveBeenCalledWith({ param: { id: 1 }, }); expect(toast.success).toHaveBeenCalledWith('系统配置删除成功'); }); }); it('应该优雅处理API错误', async () => { const client = systemConfigClientManager.get(); const { toast } = await import('sonner'); // Mock API error (client.index.$get as any).mockRejectedValue(new Error('API Error')); renderWithProviders(); // Should handle error without crashing await waitFor(() => { expect(screen.getByText('系统配置管理')).toBeInTheDocument(); }); // Test create system config error const createButton = screen.getByText('创建配置'); fireEvent.click(createButton); const configKeyInput = screen.getByTestId('config-key-input'); const configValueInput = screen.getByTestId('config-value-input'); fireEvent.change(configKeyInput, { target: { value: 'wx.mini.app.id' } }); fireEvent.change(configValueInput, { target: { value: 'test_value' } }); // Mock creation error (client.index.$post as any).mockRejectedValue(new Error('Creation failed')); const submitButton = screen.getByTestId('create-submit-button'); fireEvent.click(submitButton); await waitFor(() => { expect(toast.error).toHaveBeenCalledWith('Creation failed'); }); }); it('应该处理搜索功能', async () => { const client = systemConfigClientManager.get(); const mockSystemConfigs = { data: [], pagination: { total: 0, page: 1, pageSize: 10 }, }; (client.index.$get as any).mockResolvedValue(createMockResponse(200, mockSystemConfigs)); renderWithProviders(); // Test search const searchInput = screen.getByTestId('search-input'); fireEvent.change(searchInput, { target: { value: '微信' } }); const searchButton = screen.getByText('搜索'); fireEvent.click(searchButton); await waitFor(() => { expect(client.index.$get).toHaveBeenCalledWith({ query: { page: 1, pageSize: 10, keyword: '微信', }, }); }); }); });