AreaSelect.test.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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 { FormProvider, useForm } from 'react-hook-form';
  5. import { AreaSelect } from '../../src/components/AreaSelect';
  6. // Mock API客户端
  7. vi.mock('../../src/api/areaClient', () => ({
  8. areaClientManager: {
  9. get: vi.fn(() => ({
  10. index: {
  11. $get: vi.fn(() => Promise.resolve({
  12. status: 200,
  13. json: () => Promise.resolve({
  14. data: [
  15. { id: 1, name: '北京市', level: 1 },
  16. { id: 2, name: '上海市', level: 1 }
  17. ]
  18. })
  19. }))
  20. }
  21. }))
  22. }
  23. }));
  24. // 测试组件包装器
  25. const TestWrapper = ({ children }: { children: React.ReactNode }) => {
  26. const queryClient = new QueryClient({
  27. defaultOptions: {
  28. queries: {
  29. retry: false,
  30. },
  31. },
  32. });
  33. // 创建一个简单的form context
  34. const methods = useForm();
  35. return (
  36. <QueryClientProvider client={queryClient}>
  37. <FormProvider {...methods}>
  38. {children}
  39. </FormProvider>
  40. </QueryClientProvider>
  41. );
  42. };
  43. describe('AreaSelect 组件测试', () => {
  44. beforeEach(() => {
  45. vi.clearAllMocks();
  46. });
  47. it('应该正确渲染AreaSelect组件', () => {
  48. render(
  49. <TestWrapper>
  50. <AreaSelect />
  51. </TestWrapper>
  52. );
  53. expect(screen.getByText('选择所在省份')).toBeInTheDocument();
  54. expect(screen.getByText('选择所在城市')).toBeInTheDocument();
  55. expect(screen.getByText('选择所在区县')).toBeInTheDocument();
  56. });
  57. it('当required=true时,省份应该显示必填标记,城市和区县不应该显示必填标记(未选择省份时)', () => {
  58. render(
  59. <TestWrapper>
  60. <AreaSelect required={true} />
  61. </TestWrapper>
  62. );
  63. // 检查省份标签是否包含星号
  64. const provinceLabel = screen.getByText('省份');
  65. expect(provinceLabel.innerHTML).toContain('*');
  66. // 检查城市标签不应该包含星号(因为还没有选择省份)
  67. const cityLabel = screen.getByText('城市');
  68. expect(cityLabel.innerHTML).not.toContain('*');
  69. // 检查区县标签不应该包含星号
  70. const districtLabel = screen.getByText('区县');
  71. expect(districtLabel.innerHTML).not.toContain('*');
  72. });
  73. it('当required=false时,所有字段都不应该显示必填标记', () => {
  74. render(
  75. <TestWrapper>
  76. <AreaSelect required={false} />
  77. </TestWrapper>
  78. );
  79. const provinceLabel = screen.getByText('省份');
  80. expect(provinceLabel.innerHTML).not.toContain('*');
  81. const cityLabel = screen.getByText('城市');
  82. expect(cityLabel.innerHTML).not.toContain('*');
  83. const districtLabel = screen.getByText('区县');
  84. expect(districtLabel.innerHTML).not.toContain('*');
  85. });
  86. it('当选择了城市时,区县字段不应该显示必填标记(即使required=true)', () => {
  87. // 这个测试验证区县字段永远不会显示必填标记
  88. // 即使required=true且选择了城市,区县字段也不应该显示星号
  89. render(
  90. <TestWrapper>
  91. <AreaSelect required={true} />
  92. </TestWrapper>
  93. );
  94. // 检查区县标签不应该包含星号
  95. const districtLabel = screen.getByText('区县');
  96. expect(districtLabel.innerHTML).not.toContain('*');
  97. });
  98. it('应该正确处理onChange回调', () => {
  99. const handleChange = vi.fn();
  100. render(
  101. <TestWrapper>
  102. <AreaSelect onChange={handleChange} />
  103. </TestWrapper>
  104. );
  105. // 验证组件渲染正常
  106. expect(screen.getByText('选择所在省份')).toBeInTheDocument();
  107. // onChange会在用户交互时被调用,这里我们只验证组件能接收onChange prop
  108. expect(handleChange).not.toHaveBeenCalled();
  109. });
  110. it('应该支持禁用状态', () => {
  111. render(
  112. <TestWrapper>
  113. <AreaSelect disabled={true} />
  114. </TestWrapper>
  115. );
  116. // 验证组件渲染正常
  117. expect(screen.getByText('选择所在省份')).toBeInTheDocument();
  118. // 禁用状态会在UI中体现,这里我们只验证组件能接收disabled prop
  119. });
  120. it('应该正确处理初始值', () => {
  121. const initialValue = {
  122. provinceId: 1,
  123. cityId: 3,
  124. districtId: 5
  125. };
  126. render(
  127. <TestWrapper>
  128. <AreaSelect value={initialValue} />
  129. </TestWrapper>
  130. );
  131. // 验证组件渲染正常 - 查找FormDescription中的文本
  132. expect(screen.getByText('选择所在省份')).toBeInTheDocument();
  133. // 初始值会在组件内部处理,这里我们只验证组件能接收value prop
  134. });
  135. });