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 { OrderManagement } from '../../src/components/OrderManagement'; import { adminOrderClient } from '../../src/api/orderClient'; // 完整的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/orderClient', () => { const mockAdminOrderClient = { $get: vi.fn(() => Promise.resolve({ status: 200, body: null })), ':id': { $put: vi.fn(() => Promise.resolve({ status: 200, body: null })), }, }; const mockOrderClientManager = { getAdminOrderClient: vi.fn(() => mockAdminOrderClient), }; return { orderClientManager: mockOrderClientManager, adminOrderClient: mockAdminOrderClient, }; }); // 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('应该加载订单列表并显示数据', async () => { const mockOrders = { data: [ { id: 1, orderNo: 'ORDER001', user: { username: 'testuser' }, userPhone: '13800138000', recevierName: '张三', receiverMobile: '13800138001', amount: 100.00, payAmount: 100.00, freightAmount: 0.00, state: 0, payState: 2, orderType: 1, payType: 1, address: '北京市朝阳区', remark: '测试订单', createdAt: '2024-01-01T00:00:00Z', }, ], pagination: { total: 1, page: 1, pageSize: 10, }, }; // Mock initial order list (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders)); renderWithProviders(); // Wait for initial data to load await waitFor(() => { expect(screen.getByText('ORDER001')).toBeInTheDocument(); expect(screen.getByText('testuser')).toBeInTheDocument(); expect(screen.getByText('张三')).toBeInTheDocument(); // Use getAllByText for amount since there are multiple elements with the same text const amountElements = screen.getAllByText('¥100.00'); expect(amountElements.length).toBeGreaterThan(0); }); // Verify API was called with correct parameters expect(adminOrderClient.$get).toHaveBeenCalledWith({ query: { page: 1, pageSize: 10, keyword: '', filters: undefined, }, }); }); it('应该处理订单搜索功能', async () => { const mockOrders = { data: [], pagination: { total: 0, page: 1, pageSize: 10 }, }; (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders)); renderWithProviders(); // Wait for search elements to be available (search area is always available even during loading) await waitFor(() => { expect(screen.getByTestId('order-search-input')).toBeInTheDocument(); expect(screen.getByTestId('order-search-button')).toBeInTheDocument(); }); // Test search const searchInput = screen.getByTestId('order-search-input'); fireEvent.change(searchInput, { target: { value: 'ORDER001' } }); const searchButton = screen.getByTestId('order-search-button'); fireEvent.click(searchButton); await waitFor(() => { expect(adminOrderClient.$get).toHaveBeenCalledWith({ query: { page: 1, pageSize: 10, keyword: 'ORDER001', filters: undefined, }, }); }); }); it('应该处理订单状态过滤', async () => { const mockOrders = { data: [], pagination: { total: 0, page: 1, pageSize: 10 }, }; (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders)); renderWithProviders(); // Wait for component to load await waitFor(() => { expect(screen.getByTestId('order-status-select')).toBeInTheDocument(); }); // Test status filter const statusSelect = screen.getByTestId('order-status-select'); fireEvent.click(statusSelect); const statusOption = screen.getByText('已发货'); fireEvent.click(statusOption); await waitFor(() => { expect(adminOrderClient.$get).toHaveBeenCalledWith({ query: { page: 1, pageSize: 10, keyword: '', filters: expect.stringContaining('"state":1'), }, }); }); }); it('应该处理支付状态过滤', async () => { const mockOrders = { data: [], pagination: { total: 0, page: 1, pageSize: 10 }, }; (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders)); renderWithProviders(); // Wait for component to load await waitFor(() => { expect(screen.getByTestId('order-pay-status-select')).toBeInTheDocument(); }); // Test pay status filter const payStatusSelect = screen.getByTestId('order-pay-status-select'); fireEvent.click(payStatusSelect); const payStatusOption = screen.getByText('支付成功'); fireEvent.click(payStatusOption); await waitFor(() => { expect(adminOrderClient.$get).toHaveBeenCalledWith({ query: { page: 1, pageSize: 10, keyword: '', filters: expect.stringContaining('"payState":2'), }, }); }); }); it('应该处理订单编辑功能', async () => { const { toast } = await import('sonner'); const mockOrders = { data: [ { id: 1, orderNo: 'ORDER001', state: 0, payState: 2, remark: '原始备注', user: { username: 'testuser' }, userPhone: '13800138000', recevierName: '张三', receiverMobile: '13800138001', amount: 100.00, payAmount: 100.00, freightAmount: 0.00, orderType: 1, payType: 1, address: '北京市朝阳区', createdAt: '2024-01-01T00:00:00Z', }, ], pagination: { total: 1, page: 1, pageSize: 10, }, }; (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders)); renderWithProviders(); // Wait for data to load await waitFor(() => { expect(screen.getByText('ORDER001')).toBeInTheDocument(); }); // Click edit button using test ID const editButtons = screen.getAllByTestId('order-edit-button'); fireEvent.click(editButtons[0]); // Wait for edit modal to open and form elements to be available await waitFor(() => { expect(screen.getByText('编辑订单')).toBeInTheDocument(); expect(screen.getByTestId('edit-order-status-select')).toBeInTheDocument(); expect(screen.getByTestId('edit-remark-textarea')).toBeInTheDocument(); }, { timeout: 5000 }); // Change order status const statusSelect = screen.getByTestId('edit-order-status-select'); fireEvent.click(statusSelect); // Use getAllByText and select the first option const newStatusOptions = screen.getAllByText('已发货'); fireEvent.click(newStatusOptions[0]); // Change remark const remarkTextarea = screen.getByTestId('edit-remark-textarea'); fireEvent.change(remarkTextarea, { target: { value: '更新后的备注' } }); // Mock successful update (adminOrderClient[':id']['$put'] as any).mockResolvedValue(createMockResponse(200)); // Submit form using test ID const saveButton = screen.getByTestId('order-save-button'); fireEvent.click(saveButton); await waitFor(() => { expect(adminOrderClient[':id']['$put']).toHaveBeenCalledWith({ param: { id: '1' }, json: { state: 0, payState: 2, remark: '更新后的备注', }, }); expect(toast.success).toHaveBeenCalledWith('订单更新成功'); }); }); it('应该处理订单详情查看', async () => { const mockOrders = { data: [ { id: 1, orderNo: 'ORDER001', state: 0, payState: 2, remark: '测试订单', user: { username: 'testuser' }, userPhone: '13800138000', recevierName: '张三', receiverMobile: '13800138001', amount: 100.00, payAmount: 100.00, freightAmount: 0.00, orderType: 1, payType: 1, address: '北京市朝阳区', createdAt: '2024-01-01T00:00:00Z', }, ], pagination: { total: 1, page: 1, pageSize: 10, }, }; (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders)); renderWithProviders(); // Wait for data to load await waitFor(() => { expect(screen.getByText('ORDER001')).toBeInTheDocument(); }); // Click view details button using test ID const viewButtons = screen.getAllByTestId('order-view-button'); fireEvent.click(viewButtons[0]); // Wait for detail modal to open await waitFor(() => { expect(screen.getByText('订单详情')).toBeInTheDocument(); }, { timeout: 5000 }); // Check modal content expect(screen.getByText('订单详情')).toBeInTheDocument(); // Use getAllByText for ORDER001 since there are multiple elements with the same text const orderNoElements = screen.getAllByText('ORDER001'); expect(orderNoElements.length).toBeGreaterThan(0); // Use getAllByText for 实物订单 since there are multiple elements with the same text const orderTypeElements = screen.getAllByText('实物订单'); expect(orderTypeElements.length).toBeGreaterThan(0); // Use getAllByText for amount since there are multiple elements with the same text const amountElements = screen.getAllByText('¥100.00'); expect(amountElements.length).toBeGreaterThan(0); expect(screen.getByText('测试订单')).toBeInTheDocument(); }); it('应该优雅处理API错误', async () => { const { toast } = await import('sonner'); // Mock API error (adminOrderClient.$get as any).mockRejectedValue(new Error('API Error')); renderWithProviders(); // Should handle error without crashing await waitFor(() => { expect(screen.getByText('订单管理')).toBeInTheDocument(); }); // Test edit error scenario const mockOrders = { data: [ { id: 1, orderNo: 'ORDER001', state: 0, payState: 2, remark: '测试订单', user: { username: 'testuser' }, userPhone: '13800138000', recevierName: '张三', receiverMobile: '13800138001', amount: 100.00, payAmount: 100.00, freightAmount: 0.00, orderType: 1, payType: 1, address: '北京市朝阳区', createdAt: '2024-01-01T00:00:00Z', }, ], pagination: { total: 1, page: 1, pageSize: 10, }, }; // Mock successful data load (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders)); // Re-render with data renderWithProviders(); await waitFor(() => { expect(screen.getByText('ORDER001')).toBeInTheDocument(); }); // Click edit button using test ID const editButtons = screen.getAllByTestId('order-edit-button'); fireEvent.click(editButtons[0]); await waitFor(() => { expect(screen.getByText('编辑订单')).toBeInTheDocument(); }); // Mock update error (adminOrderClient[':id']['$put'] as any).mockRejectedValue(new Error('Update failed')); // Submit form using test ID const saveButton = screen.getByTestId('order-save-button'); fireEvent.click(saveButton); await waitFor(() => { expect(toast.error).toHaveBeenCalledWith('更新失败,请重试'); }); }); });