| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- import React from 'react'
- import { render, fireEvent, waitFor } from '@testing-library/react'
- import { LocationSearch } from '../../src/components/LocationSearch'
- // Mock API调用
- jest.mock('../../src/api', () => ({
- locationClient: {
- $get: jest.fn().mockImplementation(({ query }) => {
- if (query.keyword === '北京') {
- return Promise.resolve({
- status: 200,
- json: jest.fn().mockResolvedValue([
- {
- id: 1,
- name: '北京首都国际机场',
- province: '北京市',
- city: '北京市',
- district: '朝阳区',
- address: '北京市朝阳区首都机场路'
- },
- {
- id: 2,
- name: '北京南站',
- province: '北京市',
- city: '北京市',
- district: '丰台区',
- address: '北京市丰台区永外大街12号'
- }
- ])
- })
- }
- if (query.keyword === '上海') {
- return Promise.resolve({
- status: 200,
- json: jest.fn().mockResolvedValue([
- {
- id: 3,
- name: '上海虹桥机场',
- province: '上海市',
- city: '上海市',
- district: '长宁区',
- address: '上海市长宁区虹桥路2550号'
- }
- ])
- })
- }
- return Promise.resolve({
- status: 200,
- json: jest.fn().mockResolvedValue([])
- })
- })
- }
- }))
- describe('LocationSearch', () => {
- beforeEach(() => {
- jest.clearAllMocks()
- })
- it('应该正确渲染初始状态', () => {
- const { getByPlaceholderText } = render(<LocationSearch />)
- expect(getByPlaceholderText('搜索地点')).toBeTruthy()
- })
- it('应该显示自定义占位符', () => {
- const { getByPlaceholderText } = render(
- <LocationSearch placeholder="请输入地点名称" />
- )
- expect(getByPlaceholderText('请输入地点名称')).toBeTruthy()
- })
- it('应该处理输入变化并显示搜索结果', async () => {
- const { getByPlaceholderText, getByText } = render(<LocationSearch />)
- const input = getByPlaceholderText('搜索地点')
- fireEvent.input(input, { target: { value: '北京' } })
- await waitFor(() => {
- expect(getByText('北京首都国际机场')).toBeTruthy()
- expect(getByText('北京南站')).toBeTruthy()
- })
- })
- it('应该正确选择地点并触发onChange', async () => {
- const mockOnChange = jest.fn()
- const { getByPlaceholderText, getByText } = render(
- <LocationSearch onChange={mockOnChange} />
- )
- const input = getByPlaceholderText('搜索地点')
- fireEvent.input(input, { target: { value: '北京' } })
- await waitFor(() => {
- expect(getByText('北京首都国际机场')).toBeTruthy()
- })
- const locationItem = getByText('北京首都国际机场')
- fireEvent.click(locationItem)
- expect(mockOnChange).toHaveBeenCalledWith({
- id: 1,
- name: '北京首都国际机场',
- province: '北京市',
- city: '北京市',
- district: '朝阳区',
- address: '北京市朝阳区首都机场路'
- })
- })
- it('应该支持地区筛选', async () => {
- const { getByPlaceholderText } = render(
- <LocationSearch
- areaFilter={{
- provinceId: 1,
- cityId: 11,
- districtId: 111
- }}
- />
- )
- const input = getByPlaceholderText('搜索地点')
- fireEvent.input(input, { target: { value: '北京' } })
- await waitFor(() => {
- // 验证API调用时传递了地区筛选参数
- const locationClient = require('../../src/api').locationClient
- expect(locationClient.$get).toHaveBeenCalledWith({
- query: {
- keyword: '北京',
- provinceId: 1,
- cityId: 11,
- districtId: 111
- }
- })
- })
- })
- it('应该处理清除操作', async () => {
- const mockOnChange = jest.fn()
- const { getByPlaceholderText, getByText } = render(
- <LocationSearch onChange={mockOnChange} />
- )
- const input = getByPlaceholderText('搜索地点')
- fireEvent.input(input, { target: { value: '北京' } })
- await waitFor(() => {
- expect(getByText('北京首都国际机场')).toBeTruthy()
- })
- // 选择地点
- const locationItem = getByText('北京首都国际机场')
- fireEvent.click(locationItem)
- // 清除输入
- const clearButton = getByText('×')
- fireEvent.click(clearButton)
- expect(mockOnChange).toHaveBeenCalledWith(null)
- })
- it('应该显示当前选择的地点', () => {
- const selectedLocation = {
- id: 1,
- name: '北京首都国际机场',
- province: '北京市',
- city: '北京市',
- district: '朝阳区',
- address: '北京市朝阳区首都机场路'
- }
- const { getByText } = render(
- <LocationSearch value={selectedLocation} />
- )
- expect(getByText('已选择: 北京首都国际机场 · 朝阳区 · 北京市 · 北京市')).toBeTruthy()
- })
- it('应该处理空搜索结果', async () => {
- const { getByPlaceholderText, getByText } = render(<LocationSearch />)
- const input = getByPlaceholderText('搜索地点')
- fireEvent.input(input, { target: { value: '不存在的城市' } })
- await waitFor(() => {
- expect(getByText('未找到相关地点')).toBeTruthy()
- })
- })
- it('应该处理防抖搜索', async () => {
- jest.useFakeTimers()
- const { getByPlaceholderText } = render(<LocationSearch />)
- const input = getByPlaceholderText('搜索地点')
- // 快速输入多个字符
- fireEvent.input(input, { target: { value: '北' } })
- fireEvent.input(input, { target: { value: '北京' } })
- fireEvent.input(input, { target: { value: '北京市' } })
- // 验证API只被调用一次(防抖)
- const locationClient = require('../../src/api').locationClient
- expect(locationClient.$get).not.toHaveBeenCalled()
- // 快进防抖时间
- jest.advanceTimersByTime(300)
- await waitFor(() => {
- expect(locationClient.$get).toHaveBeenCalledTimes(1)
- expect(locationClient.$get).toHaveBeenCalledWith({
- query: {
- keyword: '北京市'
- }
- })
- })
- jest.useRealTimers()
- })
- })
|