import React from 'react' import { render, screen, fireEvent, waitFor } from '@testing-library/react' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { AreaCascader } from '../../src/components/AreaCascader' // Mock API 客户端 const mockAreaClient = { provinces: { $get: jest.fn() }, cities: { $get: jest.fn() }, districts: { $get: jest.fn() } } jest.mock('../../src/api', () => ({ areaClient: mockAreaClient })) // 创建测试用的 QueryClient const createTestQueryClient = () => new QueryClient({ defaultOptions: { queries: { retry: false, }, }, }) // 包装组件 const Wrapper = ({ children }: { children: React.ReactNode }) => { const queryClient = createTestQueryClient() return ( {children} ) } // 模拟数据 const mockProvinces = { success: true, data: { provinces: [ { id: 1, name: '北京市' }, { id: 2, name: '上海市' }, { id: 3, name: '广东省' } ] }, message: '' } const mockCities = { success: true, data: { cities: [ { id: 11, name: '北京市' }, { id: 12, name: '朝阳区' }, { id: 13, name: '海淀区' } ] }, message: '' } const mockDistricts = { success: true, data: { districts: [ { id: 101, name: '朝阳区' }, { id: 102, name: '海淀区' }, { id: 103, name: '西城区' } ] }, message: '' } describe('AreaCascader 组件', () => { beforeEach(() => { // 重置所有 mock jest.clearAllMocks() // 设置默认的 mock 返回值 mockAreaClient.provinces.$get.mockResolvedValue({ status: 200, json: async () => mockProvinces }) mockAreaClient.cities.$get.mockResolvedValue({ status: 200, json: async () => mockCities }) mockAreaClient.districts.$get.mockResolvedValue({ status: 200, json: async () => mockDistricts }) }) test('应该正确渲染组件', async () => { const onChange = jest.fn() render( ) // 检查选择器标签 expect(screen.getByText('省份')).toBeInTheDocument() expect(screen.getByText('城市')).toBeInTheDocument() expect(screen.getByText('区县')).toBeInTheDocument() // 检查默认占位符 expect(screen.getByText('请选择省市区')).toBeInTheDocument() // 等待数据加载 await waitFor(() => { expect(mockAreaClient.provinces.$get).toHaveBeenCalled() }) }) test('应该显示自定义占位符', () => { const onChange = jest.fn() render( ) expect(screen.getByText('选择出发地')).toBeInTheDocument() }) test('应该初始化选择值', async () => { const onChange = jest.fn() render( ) // 等待数据加载 await waitFor(() => { expect(mockAreaClient.provinces.$get).toHaveBeenCalled() }) // 检查是否调用了城市和区县查询 await waitFor(() => { expect(mockAreaClient.cities.$get).toHaveBeenCalledWith({ query: { provinceId: 1 } }) }) await waitFor(() => { expect(mockAreaClient.districts.$get).toHaveBeenCalledWith({ query: { cityId: 11 } }) }) }) test('应该处理省份选择', async () => { const onChange = jest.fn() render( ) // 等待数据加载 await waitFor(() => { expect(mockAreaClient.provinces.$get).toHaveBeenCalled() }) // 模拟选择省份 const provincePicker = screen.getByText('请选择省份') fireEvent.click(provincePicker) // 这里我们模拟 Picker 的 onChange 事件 // 在实际测试中,可能需要更复杂的模拟 }) test('应该正确显示已选择的省市区文本', async () => { const onChange = jest.fn() render( ) // 等待数据加载 await waitFor(() => { expect(mockAreaClient.provinces.$get).toHaveBeenCalled() }) await waitFor(() => { expect(mockAreaClient.cities.$get).toHaveBeenCalled() }) await waitFor(() => { expect(mockAreaClient.districts.$get).toHaveBeenCalled() }) // 检查显示文本 await waitFor(() => { expect(screen.getByText('北京市 北京市 朝阳区')).toBeInTheDocument() }) }) test('应该处理部分选择的情况', async () => { const onChange = jest.fn() render( ) // 等待数据加载 await waitFor(() => { expect(mockAreaClient.provinces.$get).toHaveBeenCalled() }) await waitFor(() => { expect(mockAreaClient.cities.$get).toHaveBeenCalled() }) // 检查显示文本 await waitFor(() => { expect(screen.getByText('北京市 北京市')).toBeInTheDocument() }) }) test('应该处理只有省份选择的情况', async () => { const onChange = jest.fn() render( ) // 等待数据加载 await waitFor(() => { expect(mockAreaClient.provinces.$get).toHaveBeenCalled() }) // 检查显示文本 await waitFor(() => { expect(screen.getByText('北京市')).toBeInTheDocument() }) }) test('应该处理 API 错误', async () => { // 模拟 API 错误 mockAreaClient.provinces.$get.mockResolvedValue({ status: 500, json: async () => ({ success: false, message: '服务器错误' }) }) const onChange = jest.fn() render( ) // 组件应该正常渲染,即使 API 调用失败 expect(screen.getByText('省份')).toBeInTheDocument() // 等待 API 调用 await waitFor(() => { expect(mockAreaClient.provinces.$get).toHaveBeenCalled() }) }) test('应该禁用城市选择器当没有选择省份时', async () => { const onChange = jest.fn() render( ) // 等待数据加载 await waitFor(() => { expect(mockAreaClient.provinces.$get).toHaveBeenCalled() }) // 检查城市选择器是否被禁用 const cityPicker = screen.getByText('请选择城市') expect(cityPicker.parentElement).toHaveClass('bg-gray-100') expect(cityPicker.parentElement).toHaveClass('text-gray-400') }) test('应该禁用区县选择器当没有选择城市时', async () => { const onChange = jest.fn() render( ) // 等待数据加载 await waitFor(() => { expect(mockAreaClient.provinces.$get).toHaveBeenCalled() }) // 检查区县选择器是否被禁用 const districtPicker = screen.getByText('请选择区县') expect(districtPicker.parentElement).toHaveClass('bg-gray-100') expect(districtPicker.parentElement).toHaveClass('text-gray-400') }) })