supplier-selector.integration.test.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. import { describe, it, expect, vi, beforeEach } from 'vitest';
  2. import { render, screen, fireEvent, waitFor } from '@testing-library/react';
  3. import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
  4. import { SupplierSelector } from '../../src/components/SupplierSelector';
  5. import { supplierClient } from '../../src/api/supplierClient';
  6. // 完整的mock响应对象
  7. const createMockResponse = (status: number, data?: any) => ({
  8. status,
  9. ok: status >= 200 && status < 300,
  10. body: null,
  11. bodyUsed: false,
  12. statusText: status === 200 ? 'OK' : status === 201 ? 'Created' : status === 204 ? 'No Content' : 'Error',
  13. headers: new Headers(),
  14. url: '',
  15. redirected: false,
  16. type: 'basic' as ResponseType,
  17. json: async () => data || {},
  18. text: async () => '',
  19. blob: async () => new Blob(),
  20. arrayBuffer: async () => new ArrayBuffer(0),
  21. formData: async () => new FormData(),
  22. clone: function() { return this; }
  23. });
  24. // Mock API client
  25. vi.mock('../../src/api/supplierClient', () => {
  26. const mockSupplierClient = {
  27. index: {
  28. $get: vi.fn(() => Promise.resolve({
  29. status: 200,
  30. body: null,
  31. json: async () => ({ data: [], pagination: { total: 0, page: 1, pageSize: 100 } })
  32. })),
  33. },
  34. };
  35. const mockSupplierClientManager = {
  36. get: vi.fn(() => mockSupplierClient),
  37. };
  38. return {
  39. supplierClientManager: mockSupplierClientManager,
  40. supplierClient: mockSupplierClient,
  41. };
  42. });
  43. const createTestQueryClient = () =>
  44. new QueryClient({
  45. defaultOptions: {
  46. queries: {
  47. retry: false,
  48. },
  49. },
  50. });
  51. const renderWithProviders = (component: React.ReactElement) => {
  52. const queryClient = createTestQueryClient();
  53. return render(
  54. <QueryClientProvider client={queryClient}>
  55. {component}
  56. </QueryClientProvider>
  57. );
  58. };
  59. describe('SupplierSelector', () => {
  60. beforeEach(() => {
  61. vi.clearAllMocks();
  62. });
  63. it('应该渲染供应商选择器', () => {
  64. renderWithProviders(<SupplierSelector testId="supplier-selector" />);
  65. const selectTrigger = screen.getByTestId('supplier-selector');
  66. expect(selectTrigger).toBeInTheDocument();
  67. });
  68. it('应该显示自定义占位符', () => {
  69. renderWithProviders(
  70. <SupplierSelector
  71. placeholder="请选择供应商"
  72. testId="supplier-selector"
  73. />
  74. );
  75. const selectTrigger = screen.getByTestId('supplier-selector');
  76. expect(selectTrigger).toHaveTextContent('请选择供应商');
  77. });
  78. it('应该调用API获取供应商列表', async () => {
  79. const mockSuppliers = [
  80. { id: 1, name: '供应商A' },
  81. { id: 2, name: '供应商B' }
  82. ];
  83. (supplierClient.index.$get as any).mockResolvedValueOnce(
  84. createMockResponse(200, {
  85. data: mockSuppliers,
  86. pagination: { total: 2, page: 1, pageSize: 100 }
  87. })
  88. );
  89. renderWithProviders(<SupplierSelector testId="supplier-selector" />);
  90. await waitFor(() => {
  91. expect(supplierClient.index.$get).toHaveBeenCalledWith({
  92. query: { page: 1, pageSize: 100 }
  93. });
  94. });
  95. });
  96. it('应该显示供应商列表', async () => {
  97. const mockSuppliers = [
  98. { id: 1, name: '供应商A' },
  99. { id: 2, name: '供应商B' }
  100. ];
  101. (supplierClient.index.$get as any).mockResolvedValueOnce(
  102. createMockResponse(200, {
  103. data: mockSuppliers,
  104. pagination: { total: 2, page: 1, pageSize: 100 }
  105. })
  106. );
  107. renderWithProviders(<SupplierSelector testId="supplier-selector" />);
  108. await waitFor(() => {
  109. expect(supplierClient.index.$get).toHaveBeenCalledWith({
  110. query: { page: 1, pageSize: 100 }
  111. });
  112. });
  113. // 验证API调用,不测试下拉菜单的UI交互
  114. expect(supplierClient.index.$get).toHaveBeenCalledTimes(1);
  115. });
  116. it('应该处理API错误', async () => {
  117. (supplierClient.index.$get as any).mockRejectedValueOnce(new Error('API错误'));
  118. renderWithProviders(<SupplierSelector testId="supplier-selector" />);
  119. // 验证组件渲染
  120. const selectTrigger = screen.getByTestId('supplier-selector');
  121. expect(selectTrigger).toBeInTheDocument();
  122. // 等待API调用完成
  123. await waitFor(() => {
  124. expect(supplierClient.index.$get).toHaveBeenCalled();
  125. });
  126. });
  127. it('应该支持禁用状态', () => {
  128. renderWithProviders(
  129. <SupplierSelector
  130. disabled={true}
  131. testId="supplier-selector"
  132. />
  133. );
  134. const selectTrigger = screen.getByTestId('supplier-selector');
  135. expect(selectTrigger).toBeDisabled();
  136. });
  137. it('应该支持值选择', async () => {
  138. const mockSuppliers = [
  139. { id: 1, name: '供应商A' },
  140. { id: 2, name: '供应商B' }
  141. ];
  142. (supplierClient.index.$get as any).mockResolvedValueOnce(
  143. createMockResponse(200, {
  144. data: mockSuppliers,
  145. pagination: { total: 2, page: 1, pageSize: 100 }
  146. })
  147. );
  148. const mockOnChange = vi.fn();
  149. renderWithProviders(
  150. <SupplierSelector
  151. onChange={mockOnChange}
  152. testId="supplier-selector"
  153. />
  154. );
  155. await waitFor(() => {
  156. expect(supplierClient.index.$get).toHaveBeenCalledWith({
  157. query: { page: 1, pageSize: 100 }
  158. });
  159. });
  160. // 验证API调用,不测试下拉菜单的UI交互
  161. expect(supplierClient.index.$get).toHaveBeenCalledTimes(1);
  162. });
  163. });