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(
{component}
);
};
describe('SupplierSelector', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('应该渲染供应商选择器', () => {
renderWithProviders();
const selectTrigger = screen.getByTestId('supplier-selector');
expect(selectTrigger).toBeInTheDocument();
});
it('应该显示自定义占位符', () => {
renderWithProviders(
);
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();
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();
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();
// 验证组件渲染
const selectTrigger = screen.getByTestId('supplier-selector');
expect(selectTrigger).toBeInTheDocument();
// 等待API调用完成
await waitFor(() => {
expect(supplierClient.$get).toHaveBeenCalled();
});
});
it('应该支持禁用状态', () => {
renderWithProviders(
);
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(
);
await waitFor(() => {
expect(supplierClient.$get).toHaveBeenCalledWith({
query: { page: 1, pageSize: 100 }
});
});
// 验证API调用,不测试下拉菜单的UI交互
expect(supplierClient.$get).toHaveBeenCalledTimes(1);
});
});