import React from 'react' import { render, screen, fireEvent, waitFor } from '@testing-library/react' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { AreaPicker } from '../../src/components/AreaPicker' // 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('AreaPicker 组件', () => { 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 onClose = jest.fn() const onConfirm = jest.fn() render( ) // 检查标题 expect(screen.getByText('选择地区')).toBeInTheDocument() // 检查选择器标签 expect(screen.getByText('省份')).toBeInTheDocument() 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 onClose = jest.fn() const onConfirm = jest.fn() render( ) expect(screen.getByText('选择出发地')).toBeInTheDocument() }) test('应该初始化选择值', async () => { const onClose = jest.fn() const onConfirm = jest.fn() render( ) // 等待数据加载 await waitFor(() => { expect(mockAreaClient.provinces.$get).toHaveBeenCalled() }) // 检查是否调用了城市和区县查询 await waitFor(() => { expect(mockAreaClient.cities.$get).toHaveBeenCalledWith({ query: { provinceId: 1, page: 1, pageSize: 50 } }) }) await waitFor(() => { expect(mockAreaClient.districts.$get).toHaveBeenCalledWith({ query: { cityId: 11, page: 1, pageSize: 50 } }) }) }) test('应该处理取消操作', () => { const onClose = jest.fn() const onConfirm = jest.fn() render( ) const cancelButton = screen.getByText('取消') fireEvent.click(cancelButton) expect(onClose).toHaveBeenCalledTimes(1) expect(onConfirm).not.toHaveBeenCalled() }) test('应该处理确认操作', async () => { const onClose = jest.fn() const onConfirm = jest.fn() render( ) // 等待数据加载 await waitFor(() => { expect(mockAreaClient.provinces.$get).toHaveBeenCalled() }) const confirmButton = screen.getByText('确定') fireEvent.click(confirmButton) // 由于没有选择任何值,应该传递空数组 expect(onConfirm).toHaveBeenCalledWith([], []) expect(onClose).toHaveBeenCalledTimes(1) }) test('当不可见时应该返回 null', () => { const onClose = jest.fn() const onConfirm = jest.fn() const { container } = render( ) // 检查容器是否为空 expect(container.firstChild).toBeNull() }) test('应该处理 API 错误', async () => { // 模拟 API 错误 mockAreaClient.provinces.$get.mockResolvedValue({ status: 500, json: async () => ({ success: false, message: '服务器错误' }) }) const onClose = jest.fn() const onConfirm = jest.fn() render( ) // 组件应该正常渲染,即使 API 调用失败 expect(screen.getByText('选择地区')).toBeInTheDocument() // 等待 API 调用 await waitFor(() => { expect(mockAreaClient.provinces.$get).toHaveBeenCalled() }) }) test('应该正确显示已选择的省市区文本', async () => { const onClose = jest.fn() const onConfirm = 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() }) }) })