|
@@ -0,0 +1,189 @@
|
|
|
|
|
+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 { SupplierSelector } from '../../src/components/SupplierSelector';
|
|
|
|
|
+import { supplierClient } from '../../src/api/supplierClient';
|
|
|
|
|
+
|
|
|
|
|
+// 完整的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/supplierClient', () => {
|
|
|
|
|
+ const mockSupplierClient = {
|
|
|
|
|
+ $get: vi.fn(() => Promise.resolve({
|
|
|
|
|
+ status: 200,
|
|
|
|
|
+ body: null,
|
|
|
|
|
+ json: async () => ({ data: [], pagination: { total: 0, page: 1, pageSize: 100 } })
|
|
|
|
|
+ })),
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const mockSupplierClientManager = {
|
|
|
|
|
+ get: vi.fn(() => mockSupplierClient),
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ supplierClientManager: mockSupplierClientManager,
|
|
|
|
|
+ supplierClient: mockSupplierClient,
|
|
|
|
|
+ };
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const createTestQueryClient = () =>
|
|
|
|
|
+ new QueryClient({
|
|
|
|
|
+ defaultOptions: {
|
|
|
|
|
+ queries: {
|
|
|
|
|
+ retry: false,
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+const renderWithProviders = (component: React.ReactElement) => {
|
|
|
|
|
+ const queryClient = createTestQueryClient();
|
|
|
|
|
+ return render(
|
|
|
|
|
+ <QueryClientProvider client={queryClient}>
|
|
|
|
|
+ {component}
|
|
|
|
|
+ </QueryClientProvider>
|
|
|
|
|
+ );
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+describe('SupplierSelector', () => {
|
|
|
|
|
+ beforeEach(() => {
|
|
|
|
|
+ vi.clearAllMocks();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该渲染供应商选择器', () => {
|
|
|
|
|
+ renderWithProviders(<SupplierSelector testId="supplier-selector" />);
|
|
|
|
|
+ const selectTrigger = screen.getByTestId('supplier-selector');
|
|
|
|
|
+ expect(selectTrigger).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该显示自定义占位符', () => {
|
|
|
|
|
+ renderWithProviders(
|
|
|
|
|
+ <SupplierSelector
|
|
|
|
|
+ placeholder="请选择供应商"
|
|
|
|
|
+ testId="supplier-selector"
|
|
|
|
|
+ />
|
|
|
|
|
+ );
|
|
|
|
|
+ const selectTrigger = screen.getByTestId('supplier-selector');
|
|
|
|
|
+ expect(selectTrigger).toHaveTextContent('请选择供应商');
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该调用API获取供应商列表', async () => {
|
|
|
|
|
+ const mockSuppliers = [
|
|
|
|
|
+ { id: 1, name: '供应商A' },
|
|
|
|
|
+ { id: 2, name: '供应商B' }
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ (supplierClient.$get as any).mockResolvedValueOnce(
|
|
|
|
|
+ createMockResponse(200, {
|
|
|
|
|
+ data: mockSuppliers,
|
|
|
|
|
+ pagination: { total: 2, page: 1, pageSize: 100 }
|
|
|
|
|
+ })
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ renderWithProviders(<SupplierSelector testId="supplier-selector" />);
|
|
|
|
|
+
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(supplierClient.$get).toHaveBeenCalledWith({
|
|
|
|
|
+ query: { page: 1, pageSize: 100 }
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该显示供应商列表', async () => {
|
|
|
|
|
+ const mockSuppliers = [
|
|
|
|
|
+ { id: 1, name: '供应商A' },
|
|
|
|
|
+ { id: 2, name: '供应商B' }
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ (supplierClient.$get as any).mockResolvedValueOnce(
|
|
|
|
|
+ createMockResponse(200, {
|
|
|
|
|
+ data: mockSuppliers,
|
|
|
|
|
+ pagination: { total: 2, page: 1, pageSize: 100 }
|
|
|
|
|
+ })
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ renderWithProviders(<SupplierSelector testId="supplier-selector" />);
|
|
|
|
|
+
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(supplierClient.$get).toHaveBeenCalledWith({
|
|
|
|
|
+ query: { page: 1, pageSize: 100 }
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 验证API调用,不测试下拉菜单的UI交互
|
|
|
|
|
+ expect(supplierClient.$get).toHaveBeenCalledTimes(1);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该处理API错误', async () => {
|
|
|
|
|
+ (supplierClient.$get as any).mockRejectedValueOnce(new Error('API错误'));
|
|
|
|
|
+
|
|
|
|
|
+ renderWithProviders(<SupplierSelector testId="supplier-selector" />);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证组件渲染
|
|
|
|
|
+ const selectTrigger = screen.getByTestId('supplier-selector');
|
|
|
|
|
+ expect(selectTrigger).toBeInTheDocument();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待API调用完成
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(supplierClient.$get).toHaveBeenCalled();
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该支持禁用状态', () => {
|
|
|
|
|
+ renderWithProviders(
|
|
|
|
|
+ <SupplierSelector
|
|
|
|
|
+ disabled={true}
|
|
|
|
|
+ testId="supplier-selector"
|
|
|
|
|
+ />
|
|
|
|
|
+ );
|
|
|
|
|
+ const selectTrigger = screen.getByTestId('supplier-selector');
|
|
|
|
|
+ expect(selectTrigger).toBeDisabled();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该支持值选择', async () => {
|
|
|
|
|
+ const mockSuppliers = [
|
|
|
|
|
+ { id: 1, name: '供应商A' },
|
|
|
|
|
+ { id: 2, name: '供应商B' }
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ (supplierClient.$get as any).mockResolvedValueOnce(
|
|
|
|
|
+ createMockResponse(200, {
|
|
|
|
|
+ data: mockSuppliers,
|
|
|
|
|
+ pagination: { total: 2, page: 1, pageSize: 100 }
|
|
|
|
|
+ })
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ const mockOnChange = vi.fn();
|
|
|
|
|
+ renderWithProviders(
|
|
|
|
|
+ <SupplierSelector
|
|
|
|
|
+ onChange={mockOnChange}
|
|
|
|
|
+ testId="supplier-selector"
|
|
|
|
|
+ />
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(supplierClient.$get).toHaveBeenCalledWith({
|
|
|
|
|
+ query: { page: 1, pageSize: 100 }
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 验证API调用,不测试下拉菜单的UI交互
|
|
|
|
|
+ expect(supplierClient.$get).toHaveBeenCalledTimes(1);
|
|
|
|
|
+ });
|
|
|
|
|
+});
|