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 { UserSelector } from '../../src/components/UserSelector'; import { userClient } from '../../src/api/userClient'; // 完整的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/userClient', () => { const mockUserClient = { $get: vi.fn(() => Promise.resolve({ status: 200, body: null, json: async () => ({ data: [], pagination: { total: 0, page: 1, pageSize: 100 } }) })), }; const mockUserClientManager = { get: vi.fn(() => mockUserClient), }; return { userClientManager: mockUserClientManager, userClient: mockUserClient, }; }); const createTestQueryClient = () => new QueryClient({ defaultOptions: { queries: { retry: false, enabled: true, }, }, }); const renderWithProviders = (component: React.ReactElement) => { const queryClient = createTestQueryClient(); return render( {component as any} ); }; describe('用户选择器集成测试', () => { beforeEach(() => { vi.clearAllMocks(); }); it('应该加载并显示用户列表', async () => { const mockUsers = { data: [ { id: 1, username: 'user1', name: 'User One', email: 'user1@example.com', phone: '1234567890', }, { id: 2, username: 'user2', name: 'User Two', email: 'user2@example.com', phone: '0987654321', }, ], pagination: { total: 2, page: 1, pageSize: 100, }, }; // Mock user list API (userClient.$get as any).mockResolvedValue(createMockResponse(200, mockUsers)); renderWithProviders(); // Open select dropdown to trigger API call const selectTrigger = screen.getByTestId('user-selector'); fireEvent.click(selectTrigger); // Wait for API call and loading to complete await waitFor(() => { expect(userClient.$get).toHaveBeenCalledWith({ query: { page: 1, pageSize: 100, }, }); }); // Verify select trigger is rendered expect(selectTrigger).toBeInTheDocument(); }); it('应该处理用户选择', async () => { const mockUsers = { data: [ { id: 1, username: 'user1', name: 'User One', email: 'user1@example.com', phone: '1234567890', }, ], pagination: { total: 1, page: 1, pageSize: 100, }, }; const mockOnChange = vi.fn(); // Mock user list API (userClient.$get as any).mockResolvedValue(createMockResponse(200, mockUsers)); renderWithProviders( ); // Wait for API call await waitFor(() => { expect(userClient.$get).toHaveBeenCalledWith({ query: { page: 1, pageSize: 100, }, }); }); // Verify select trigger is rendered const selectTrigger = screen.getByTestId('user-selector'); expect(selectTrigger).toBeInTheDocument(); // Verify onChange callback is properly passed expect(mockOnChange).not.toHaveBeenCalled(); }); it('应该显示自定义占位符', async () => { const mockUsers = { data: [], pagination: { total: 0, page: 1, pageSize: 100, }, }; // Mock empty user list (userClient.$get as any).mockResolvedValue(createMockResponse(200, mockUsers)); renderWithProviders( ); // Open select dropdown to trigger API call const selectTrigger = screen.getByTestId('user-selector'); fireEvent.click(selectTrigger); // Wait for API call await waitFor(() => { expect(userClient.$get).toHaveBeenCalled(); }); // Verify custom placeholder is shown expect(selectTrigger).toHaveTextContent('请选择用户'); }); it('应该处理禁用状态', async () => { const mockUsers = { data: [ { id: 1, username: 'user1', name: 'User One', email: 'user1@example.com', phone: '1234567890', }, ], pagination: { total: 1, page: 1, pageSize: 100, }, }; // Mock user list API (userClient.$get as any).mockResolvedValue(createMockResponse(200, mockUsers)); renderWithProviders( ); // Verify select is disabled immediately (no need to wait for API call) const selectTrigger = screen.getByTestId('user-selector'); expect(selectTrigger).toBeDisabled(); }); it('应该处理API错误', async () => { // Mock API error (userClient.$get as any).mockRejectedValue(new Error('API Error')); renderWithProviders(); // Should handle error without crashing await waitFor(() => { expect(screen.getByTestId('user-selector')).toBeInTheDocument(); }); }); it('应该显示预选值', async () => { const mockUsers = { data: [ { id: 1, username: 'user1', name: 'User One', email: 'user1@example.com', phone: '1234567890', }, { id: 2, username: 'user2', name: 'User Two', email: 'user2@example.com', phone: '0987654321', }, ], pagination: { total: 2, page: 1, pageSize: 100, }, }; // Mock user list API (userClient.$get as any).mockResolvedValue(createMockResponse(200, mockUsers)); renderWithProviders( ); // Wait for data to load await waitFor(() => { expect(userClient.$get).toHaveBeenCalled(); }); // Verify the select has the correct value const selectTrigger = screen.getByTestId('user-selector'); expect(selectTrigger).toHaveAttribute('data-state', 'closed'); }); });