import React from 'react'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import HomePage from '../../src/pages/home/index'
// Mock Taro 导航
const mockNavigateTo = jest.fn()
jest.mock('@tarojs/taro', () => ({
navigateTo: mockNavigateTo
}))
// Mock AreaPicker 组件
jest.mock('../../src/components/AreaPicker', () => ({
AreaPicker: jest.fn(({ visible, onClose, onConfirm, value, title }) => {
if (!visible) return null
return (
{title}
)
})
}))
// Mock TabBarLayout 组件
jest.mock('@/layouts/tab-bar-layout', () => ({
TabBarLayout: jest.fn(({ children, activeKey, className }) => (
{children}
))
}))
// 创建测试用的 QueryClient
const createTestQueryClient = () => new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
})
// 包装组件
const Wrapper = ({ children }: { children: React.ReactNode }) => {
const queryClient = createTestQueryClient()
return (
{children}
)
}
describe('首页组合查询逻辑测试', () => {
beforeEach(() => {
jest.clearAllMocks()
})
describe('组合查询映射逻辑', () => {
test('应该正确映射大巴拼车组合查询参数', async () => {
render(
)
// 设置出发地和目的地
const startLocationButton = screen.getByText('出发地').closest('button')
fireEvent.click(startLocationButton!)
const confirmButton = screen.getByTestId('area-picker-confirm')
fireEvent.click(confirmButton)
const endLocationButton = screen.getByText('目的地').closest('button')
fireEvent.click(endLocationButton!)
fireEvent.click(confirmButton)
// 等待状态更新
await waitFor(() => {
expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
})
// 默认选择大巴拼车,点击查询
const searchButton = screen.getByText('查询路线')
fireEvent.click(searchButton)
// 验证导航参数
expect(mockNavigateTo).toHaveBeenCalledWith({
url: expect.stringContaining('vehicleType=bus')
})
expect(mockNavigateTo).toHaveBeenCalledWith({
url: expect.stringContaining('travelMode=carpool')
})
})
test('应该正确映射商务车组合查询参数', async () => {
render(
)
// 设置出发地和目的地
const startLocationButton = screen.getByText('出发地').closest('button')
fireEvent.click(startLocationButton!)
const confirmButton = screen.getByTestId('area-picker-confirm')
fireEvent.click(confirmButton)
const endLocationButton = screen.getByText('目的地').closest('button')
fireEvent.click(endLocationButton!)
fireEvent.click(confirmButton)
// 等待状态更新
await waitFor(() => {
expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
})
// 选择商务车
const businessOption = screen.getByText('商务车')
fireEvent.click(businessOption)
// 点击查询
const searchButton = screen.getByText('查询路线')
fireEvent.click(searchButton)
// 验证导航参数 - 商务车支持拼车和包车两种出行方式
expect(mockNavigateTo).toHaveBeenCalledWith({
url: expect.stringContaining('vehicleType=business')
})
expect(mockNavigateTo).toHaveBeenCalledWith({
url: expect.stringContaining('travelMode=carpool,charter')
})
})
test('应该正确映射包车组合查询参数', async () => {
render(
)
// 设置出发地和目的地
const startLocationButton = screen.getByText('出发地').closest('button')
fireEvent.click(startLocationButton!)
const confirmButton = screen.getByTestId('area-picker-confirm')
fireEvent.click(confirmButton)
const endLocationButton = screen.getByText('目的地').closest('button')
fireEvent.click(endLocationButton!)
fireEvent.click(confirmButton)
// 等待状态更新
await waitFor(() => {
expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
})
// 选择包车
const charterOption = screen.getByText('包车')
fireEvent.click(charterOption)
// 点击查询
const searchButton = screen.getByText('查询路线')
fireEvent.click(searchButton)
// 验证导航参数 - 包车支持大巴和商务车两种车型
expect(mockNavigateTo).toHaveBeenCalledWith({
url: expect.stringContaining('vehicleType=bus,business')
})
expect(mockNavigateTo).toHaveBeenCalledWith({
url: expect.stringContaining('travelMode=charter')
})
})
test('应该正确显示组合查询选项', () => {
render(
)
// 验证三个组合查询选项都存在
expect(screen.getByText('大巴拼车')).toBeInTheDocument()
expect(screen.getByText('商务车')).toBeInTheDocument()
expect(screen.getByText('包车')).toBeInTheDocument()
})
test('应该正确显示组合查询选项的选中状态', () => {
render(
)
// 默认选中大巴拼车
const busOption = screen.getByText('大巴拼车')
expect(busOption.parentElement).toHaveClass('bg-gradient-to-r')
expect(busOption.parentElement).toHaveClass('text-white')
// 选择商务车
const businessOption = screen.getByText('商务车')
fireEvent.click(businessOption)
// 验证商务车被选中,大巴拼车取消选中
expect(businessOption.parentElement).toHaveClass('bg-gradient-to-r')
expect(businessOption.parentElement).toHaveClass('text-white')
expect(busOption.parentElement).not.toHaveClass('text-white')
})
})
describe('组合查询参数传递', () => {
test('应该正确传递完整的组合查询参数', async () => {
render(
)
// 设置出发地和目的地
const startLocationButton = screen.getByText('出发地').closest('button')
fireEvent.click(startLocationButton!)
const confirmButton = screen.getByTestId('area-picker-confirm')
fireEvent.click(confirmButton)
const endLocationButton = screen.getByText('目的地').closest('button')
fireEvent.click(endLocationButton!)
fireEvent.click(confirmButton)
// 等待状态更新
await waitFor(() => {
expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
})
// 选择包车
const charterOption = screen.getByText('包车')
fireEvent.click(charterOption)
// 点击查询
const searchButton = screen.getByText('查询路线')
fireEvent.click(searchButton)
// 验证完整的导航参数
const navigateCall = mockNavigateTo.mock.calls[0][0]
const url = navigateCall.url
expect(url).toContain('startAreaIds=[1,11,101]')
expect(url).toContain('endAreaIds=[1,11,101]')
expect(url).toContain('date=')
expect(url).toContain('vehicleType=bus,business')
expect(url).toContain('travelMode=charter')
})
test('应该正确传递商务车多值出行方式参数', async () => {
render(
)
// 设置出发地和目的地
const startLocationButton = screen.getByText('出发地').closest('button')
fireEvent.click(startLocationButton!)
const confirmButton = screen.getByTestId('area-picker-confirm')
fireEvent.click(confirmButton)
const endLocationButton = screen.getByText('目的地').closest('button')
fireEvent.click(endLocationButton!)
fireEvent.click(confirmButton)
// 等待状态更新
await waitFor(() => {
expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
})
// 选择商务车
const businessOption = screen.getByText('商务车')
fireEvent.click(businessOption)
// 点击查询
const searchButton = screen.getByText('查询路线')
fireEvent.click(searchButton)
// 验证商务车支持多值出行方式参数
const navigateCall = mockNavigateTo.mock.calls[0][0]
const url = navigateCall.url
expect(url).toContain('vehicleType=business')
expect(url).toContain('travelMode=carpool,charter')
})
test('应该正确传递包车多值车型参数', async () => {
render(
)
// 设置出发地和目的地
const startLocationButton = screen.getByText('出发地').closest('button')
fireEvent.click(startLocationButton!)
const confirmButton = screen.getByTestId('area-picker-confirm')
fireEvent.click(confirmButton)
const endLocationButton = screen.getByText('目的地').closest('button')
fireEvent.click(endLocationButton!)
fireEvent.click(confirmButton)
// 等待状态更新
await waitFor(() => {
expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
})
// 选择包车
const charterOption = screen.getByText('包车')
fireEvent.click(charterOption)
// 点击查询
const searchButton = screen.getByText('查询路线')
fireEvent.click(searchButton)
// 验证包车支持多值车型参数
const navigateCall = mockNavigateTo.mock.calls[0][0]
const url = navigateCall.url
expect(url).toContain('vehicleType=bus,business')
expect(url).toContain('travelMode=charter')
})
})
describe('组合查询样式验证', () => {
test('应该为不同组合查询选项应用正确的样式', () => {
render(
)
const busOption = screen.getByText('大巴拼车')
const businessOption = screen.getByText('商务车')
const charterOption = screen.getByText('包车')
// 默认选中大巴拼车
expect(busOption.parentElement).toHaveClass('bg-gradient-to-r')
expect(busOption.parentElement).toHaveClass('text-white')
// 选择商务车
fireEvent.click(businessOption)
expect(businessOption.parentElement).toHaveClass('bg-gradient-to-r')
expect(businessOption.parentElement).toHaveClass('text-white')
// 选择包车
fireEvent.click(charterOption)
expect(charterOption.parentElement).toHaveClass('bg-gradient-to-r')
expect(charterOption.parentElement).toHaveClass('text-white')
})
test('应该正确切换组合查询选项的选中状态', () => {
render(
)
const busOption = screen.getByText('大巴拼车')
const businessOption = screen.getByText('商务车')
const charterOption = screen.getByText('包车')
// 初始状态:大巴拼车选中
expect(busOption.parentElement).toHaveClass('text-white')
expect(businessOption.parentElement).not.toHaveClass('text-white')
expect(charterOption.parentElement).not.toHaveClass('text-white')
// 选择商务车
fireEvent.click(businessOption)
expect(busOption.parentElement).not.toHaveClass('text-white')
expect(businessOption.parentElement).toHaveClass('text-white')
expect(charterOption.parentElement).not.toHaveClass('text-white')
// 选择包车
fireEvent.click(charterOption)
expect(busOption.parentElement).not.toHaveClass('text-white')
expect(businessOption.parentElement).not.toHaveClass('text-white')
expect(charterOption.parentElement).toHaveClass('text-white')
})
})
describe('组合查询边界情况', () => {
test('应该正确处理默认组合查询参数', () => {
render(
)
// 验证默认参数
const busOption = screen.getByText('大巴拼车')
expect(busOption.parentElement).toHaveClass('text-white')
// 验证默认参数设置
expect(mockNavigateTo).not.toHaveBeenCalled()
})
test('应该正确处理组合查询参数变化', async () => {
render(
)
// 设置出发地和目的地
const startLocationButton = screen.getByText('出发地').closest('button')
fireEvent.click(startLocationButton!)
const confirmButton = screen.getByTestId('area-picker-confirm')
fireEvent.click(confirmButton)
const endLocationButton = screen.getByText('目的地').closest('button')
fireEvent.click(endLocationButton!)
fireEvent.click(confirmButton)
// 等待状态更新
await waitFor(() => {
expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
})
// 测试从大巴拼车切换到商务车
const busOption = screen.getByText('大巴拼车')
const businessOption = screen.getByText('商务车')
// 初始选择大巴拼车
expect(busOption.parentElement).toHaveClass('text-white')
// 切换到商务车
fireEvent.click(businessOption)
expect(businessOption.parentElement).toHaveClass('text-white')
expect(busOption.parentElement).not.toHaveClass('text-white')
// 点击查询
const searchButton = screen.getByText('查询路线')
fireEvent.click(searchButton)
// 验证商务车参数
const navigateCall = mockNavigateTo.mock.calls[0][0]
const url = navigateCall.url
expect(url).toContain('vehicleType=business')
expect(url).toContain('travelMode=carpool,charter')
expect(url).not.toContain('vehicleType=bus')
expect(url).not.toContain('travelMode=carpool')
})
})
})