HomePageCombinationQuery.test.tsx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. import React from 'react'
  2. import { render, screen, fireEvent, waitFor } from '@testing-library/react'
  3. import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
  4. import HomePage from '../../src/pages/home/index'
  5. // Mock Taro 导航
  6. const mockNavigateTo = jest.fn()
  7. jest.mock('@tarojs/taro', () => ({
  8. navigateTo: mockNavigateTo
  9. }))
  10. // Mock AreaPicker 组件
  11. jest.mock('../../src/components/AreaPicker', () => ({
  12. AreaPicker: jest.fn(({ visible, onClose, onConfirm, value, title }) => {
  13. if (!visible) return null
  14. return (
  15. <div data-testid="area-picker">
  16. <div data-testid="area-picker-title">{title}</div>
  17. <button data-testid="area-picker-confirm" onClick={() => onConfirm([1, 11, 101], [
  18. { id: 1, name: '北京市', type: 'province' },
  19. { id: 11, name: '北京市', type: 'city' },
  20. { id: 101, name: '朝阳区', type: 'district' }
  21. ])}>确认</button>
  22. <button data-testid="area-picker-cancel" onClick={onClose}>取消</button>
  23. </div>
  24. )
  25. })
  26. }))
  27. // Mock TabBarLayout 组件
  28. jest.mock('@/layouts/tab-bar-layout', () => ({
  29. TabBarLayout: jest.fn(({ children, activeKey, className }) => (
  30. <div data-testid="tab-bar-layout" data-active-key={activeKey} className={className}>
  31. {children}
  32. </div>
  33. ))
  34. }))
  35. // 创建测试用的 QueryClient
  36. const createTestQueryClient = () => new QueryClient({
  37. defaultOptions: {
  38. queries: {
  39. retry: false,
  40. },
  41. },
  42. })
  43. // 包装组件
  44. const Wrapper = ({ children }: { children: React.ReactNode }) => {
  45. const queryClient = createTestQueryClient()
  46. return (
  47. <QueryClientProvider client={queryClient}>
  48. {children}
  49. </QueryClientProvider>
  50. )
  51. }
  52. describe('首页组合查询逻辑测试', () => {
  53. beforeEach(() => {
  54. jest.clearAllMocks()
  55. })
  56. describe('组合查询映射逻辑', () => {
  57. test('应该正确映射大巴拼车组合查询参数', async () => {
  58. render(
  59. <Wrapper>
  60. <HomePage />
  61. </Wrapper>
  62. )
  63. // 设置出发地和目的地
  64. const startLocationButton = screen.getByText('出发地').closest('button')
  65. fireEvent.click(startLocationButton!)
  66. const confirmButton = screen.getByTestId('area-picker-confirm')
  67. fireEvent.click(confirmButton)
  68. const endLocationButton = screen.getByText('目的地').closest('button')
  69. fireEvent.click(endLocationButton!)
  70. fireEvent.click(confirmButton)
  71. // 等待状态更新
  72. await waitFor(() => {
  73. expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
  74. })
  75. // 默认选择大巴拼车,点击查询
  76. const searchButton = screen.getByText('查询路线')
  77. fireEvent.click(searchButton)
  78. // 验证导航参数
  79. expect(mockNavigateTo).toHaveBeenCalledWith({
  80. url: expect.stringContaining('vehicleType=bus')
  81. })
  82. expect(mockNavigateTo).toHaveBeenCalledWith({
  83. url: expect.stringContaining('travelMode=carpool')
  84. })
  85. })
  86. test('应该正确映射商务车组合查询参数', async () => {
  87. render(
  88. <Wrapper>
  89. <HomePage />
  90. </Wrapper>
  91. )
  92. // 设置出发地和目的地
  93. const startLocationButton = screen.getByText('出发地').closest('button')
  94. fireEvent.click(startLocationButton!)
  95. const confirmButton = screen.getByTestId('area-picker-confirm')
  96. fireEvent.click(confirmButton)
  97. const endLocationButton = screen.getByText('目的地').closest('button')
  98. fireEvent.click(endLocationButton!)
  99. fireEvent.click(confirmButton)
  100. // 等待状态更新
  101. await waitFor(() => {
  102. expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
  103. })
  104. // 选择商务车
  105. const businessOption = screen.getByText('商务车')
  106. fireEvent.click(businessOption)
  107. // 点击查询
  108. const searchButton = screen.getByText('查询路线')
  109. fireEvent.click(searchButton)
  110. // 验证导航参数 - 商务车支持拼车和包车两种出行方式
  111. expect(mockNavigateTo).toHaveBeenCalledWith({
  112. url: expect.stringContaining('vehicleType=business')
  113. })
  114. expect(mockNavigateTo).toHaveBeenCalledWith({
  115. url: expect.stringContaining('travelMode=carpool,charter')
  116. })
  117. })
  118. test('应该正确映射包车组合查询参数', async () => {
  119. render(
  120. <Wrapper>
  121. <HomePage />
  122. </Wrapper>
  123. )
  124. // 设置出发地和目的地
  125. const startLocationButton = screen.getByText('出发地').closest('button')
  126. fireEvent.click(startLocationButton!)
  127. const confirmButton = screen.getByTestId('area-picker-confirm')
  128. fireEvent.click(confirmButton)
  129. const endLocationButton = screen.getByText('目的地').closest('button')
  130. fireEvent.click(endLocationButton!)
  131. fireEvent.click(confirmButton)
  132. // 等待状态更新
  133. await waitFor(() => {
  134. expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
  135. })
  136. // 选择包车
  137. const charterOption = screen.getByText('包车')
  138. fireEvent.click(charterOption)
  139. // 点击查询
  140. const searchButton = screen.getByText('查询路线')
  141. fireEvent.click(searchButton)
  142. // 验证导航参数 - 包车支持大巴和商务车两种车型
  143. expect(mockNavigateTo).toHaveBeenCalledWith({
  144. url: expect.stringContaining('vehicleType=bus,business')
  145. })
  146. expect(mockNavigateTo).toHaveBeenCalledWith({
  147. url: expect.stringContaining('travelMode=charter')
  148. })
  149. })
  150. test('应该正确显示组合查询选项', () => {
  151. render(
  152. <Wrapper>
  153. <HomePage />
  154. </Wrapper>
  155. )
  156. // 验证三个组合查询选项都存在
  157. expect(screen.getByText('大巴拼车')).toBeInTheDocument()
  158. expect(screen.getByText('商务车')).toBeInTheDocument()
  159. expect(screen.getByText('包车')).toBeInTheDocument()
  160. })
  161. test('应该正确显示组合查询选项的选中状态', () => {
  162. render(
  163. <Wrapper>
  164. <HomePage />
  165. </Wrapper>
  166. )
  167. // 默认选中大巴拼车
  168. const busOption = screen.getByText('大巴拼车')
  169. expect(busOption.parentElement).toHaveClass('bg-gradient-to-r')
  170. expect(busOption.parentElement).toHaveClass('text-white')
  171. // 选择商务车
  172. const businessOption = screen.getByText('商务车')
  173. fireEvent.click(businessOption)
  174. // 验证商务车被选中,大巴拼车取消选中
  175. expect(businessOption.parentElement).toHaveClass('bg-gradient-to-r')
  176. expect(businessOption.parentElement).toHaveClass('text-white')
  177. expect(busOption.parentElement).not.toHaveClass('text-white')
  178. })
  179. })
  180. describe('组合查询参数传递', () => {
  181. test('应该正确传递完整的组合查询参数', async () => {
  182. render(
  183. <Wrapper>
  184. <HomePage />
  185. </Wrapper>
  186. )
  187. // 设置出发地和目的地
  188. const startLocationButton = screen.getByText('出发地').closest('button')
  189. fireEvent.click(startLocationButton!)
  190. const confirmButton = screen.getByTestId('area-picker-confirm')
  191. fireEvent.click(confirmButton)
  192. const endLocationButton = screen.getByText('目的地').closest('button')
  193. fireEvent.click(endLocationButton!)
  194. fireEvent.click(confirmButton)
  195. // 等待状态更新
  196. await waitFor(() => {
  197. expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
  198. })
  199. // 选择包车
  200. const charterOption = screen.getByText('包车')
  201. fireEvent.click(charterOption)
  202. // 点击查询
  203. const searchButton = screen.getByText('查询路线')
  204. fireEvent.click(searchButton)
  205. // 验证完整的导航参数
  206. const navigateCall = mockNavigateTo.mock.calls[0][0]
  207. const url = navigateCall.url
  208. expect(url).toContain('startAreaIds=[1,11,101]')
  209. expect(url).toContain('endAreaIds=[1,11,101]')
  210. expect(url).toContain('date=')
  211. expect(url).toContain('vehicleType=bus,business')
  212. expect(url).toContain('travelMode=charter')
  213. })
  214. test('应该正确传递商务车多值出行方式参数', async () => {
  215. render(
  216. <Wrapper>
  217. <HomePage />
  218. </Wrapper>
  219. )
  220. // 设置出发地和目的地
  221. const startLocationButton = screen.getByText('出发地').closest('button')
  222. fireEvent.click(startLocationButton!)
  223. const confirmButton = screen.getByTestId('area-picker-confirm')
  224. fireEvent.click(confirmButton)
  225. const endLocationButton = screen.getByText('目的地').closest('button')
  226. fireEvent.click(endLocationButton!)
  227. fireEvent.click(confirmButton)
  228. // 等待状态更新
  229. await waitFor(() => {
  230. expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
  231. })
  232. // 选择商务车
  233. const businessOption = screen.getByText('商务车')
  234. fireEvent.click(businessOption)
  235. // 点击查询
  236. const searchButton = screen.getByText('查询路线')
  237. fireEvent.click(searchButton)
  238. // 验证商务车支持多值出行方式参数
  239. const navigateCall = mockNavigateTo.mock.calls[0][0]
  240. const url = navigateCall.url
  241. expect(url).toContain('vehicleType=business')
  242. expect(url).toContain('travelMode=carpool,charter')
  243. })
  244. test('应该正确传递包车多值车型参数', async () => {
  245. render(
  246. <Wrapper>
  247. <HomePage />
  248. </Wrapper>
  249. )
  250. // 设置出发地和目的地
  251. const startLocationButton = screen.getByText('出发地').closest('button')
  252. fireEvent.click(startLocationButton!)
  253. const confirmButton = screen.getByTestId('area-picker-confirm')
  254. fireEvent.click(confirmButton)
  255. const endLocationButton = screen.getByText('目的地').closest('button')
  256. fireEvent.click(endLocationButton!)
  257. fireEvent.click(confirmButton)
  258. // 等待状态更新
  259. await waitFor(() => {
  260. expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
  261. })
  262. // 选择包车
  263. const charterOption = screen.getByText('包车')
  264. fireEvent.click(charterOption)
  265. // 点击查询
  266. const searchButton = screen.getByText('查询路线')
  267. fireEvent.click(searchButton)
  268. // 验证包车支持多值车型参数
  269. const navigateCall = mockNavigateTo.mock.calls[0][0]
  270. const url = navigateCall.url
  271. expect(url).toContain('vehicleType=bus,business')
  272. expect(url).toContain('travelMode=charter')
  273. })
  274. })
  275. describe('组合查询样式验证', () => {
  276. test('应该为不同组合查询选项应用正确的样式', () => {
  277. render(
  278. <Wrapper>
  279. <HomePage />
  280. </Wrapper>
  281. )
  282. const busOption = screen.getByText('大巴拼车')
  283. const businessOption = screen.getByText('商务车')
  284. const charterOption = screen.getByText('包车')
  285. // 默认选中大巴拼车
  286. expect(busOption.parentElement).toHaveClass('bg-gradient-to-r')
  287. expect(busOption.parentElement).toHaveClass('text-white')
  288. // 选择商务车
  289. fireEvent.click(businessOption)
  290. expect(businessOption.parentElement).toHaveClass('bg-gradient-to-r')
  291. expect(businessOption.parentElement).toHaveClass('text-white')
  292. // 选择包车
  293. fireEvent.click(charterOption)
  294. expect(charterOption.parentElement).toHaveClass('bg-gradient-to-r')
  295. expect(charterOption.parentElement).toHaveClass('text-white')
  296. })
  297. test('应该正确切换组合查询选项的选中状态', () => {
  298. render(
  299. <Wrapper>
  300. <HomePage />
  301. </Wrapper>
  302. )
  303. const busOption = screen.getByText('大巴拼车')
  304. const businessOption = screen.getByText('商务车')
  305. const charterOption = screen.getByText('包车')
  306. // 初始状态:大巴拼车选中
  307. expect(busOption.parentElement).toHaveClass('text-white')
  308. expect(businessOption.parentElement).not.toHaveClass('text-white')
  309. expect(charterOption.parentElement).not.toHaveClass('text-white')
  310. // 选择商务车
  311. fireEvent.click(businessOption)
  312. expect(busOption.parentElement).not.toHaveClass('text-white')
  313. expect(businessOption.parentElement).toHaveClass('text-white')
  314. expect(charterOption.parentElement).not.toHaveClass('text-white')
  315. // 选择包车
  316. fireEvent.click(charterOption)
  317. expect(busOption.parentElement).not.toHaveClass('text-white')
  318. expect(businessOption.parentElement).not.toHaveClass('text-white')
  319. expect(charterOption.parentElement).toHaveClass('text-white')
  320. })
  321. })
  322. describe('组合查询边界情况', () => {
  323. test('应该正确处理默认组合查询参数', () => {
  324. render(
  325. <Wrapper>
  326. <HomePage />
  327. </Wrapper>
  328. )
  329. // 验证默认参数
  330. const busOption = screen.getByText('大巴拼车')
  331. expect(busOption.parentElement).toHaveClass('text-white')
  332. // 验证默认参数设置
  333. expect(mockNavigateTo).not.toHaveBeenCalled()
  334. })
  335. test('应该正确处理组合查询参数变化', async () => {
  336. render(
  337. <Wrapper>
  338. <HomePage />
  339. </Wrapper>
  340. )
  341. // 设置出发地和目的地
  342. const startLocationButton = screen.getByText('出发地').closest('button')
  343. fireEvent.click(startLocationButton!)
  344. const confirmButton = screen.getByTestId('area-picker-confirm')
  345. fireEvent.click(confirmButton)
  346. const endLocationButton = screen.getByText('目的地').closest('button')
  347. fireEvent.click(endLocationButton!)
  348. fireEvent.click(confirmButton)
  349. // 等待状态更新
  350. await waitFor(() => {
  351. expect(screen.getAllByText('北京市 北京市 朝阳区')).toHaveLength(2)
  352. })
  353. // 测试从大巴拼车切换到商务车
  354. const busOption = screen.getByText('大巴拼车')
  355. const businessOption = screen.getByText('商务车')
  356. // 初始选择大巴拼车
  357. expect(busOption.parentElement).toHaveClass('text-white')
  358. // 切换到商务车
  359. fireEvent.click(businessOption)
  360. expect(businessOption.parentElement).toHaveClass('text-white')
  361. expect(busOption.parentElement).not.toHaveClass('text-white')
  362. // 点击查询
  363. const searchButton = screen.getByText('查询路线')
  364. fireEvent.click(searchButton)
  365. // 验证商务车参数
  366. const navigateCall = mockNavigateTo.mock.calls[0][0]
  367. const url = navigateCall.url
  368. expect(url).toContain('vehicleType=business')
  369. expect(url).toContain('travelMode=carpool,charter')
  370. expect(url).not.toContain('vehicleType=bus')
  371. expect(url).not.toContain('travelMode=carpool')
  372. })
  373. })
  374. })