ActivitySelectPage.test.tsx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. import React from 'react'
  2. import { render, fireEvent, waitFor } from '@testing-library/react'
  3. import { ActivitySelectPage } from '../../src/pages/select-activity/ActivitySelectPage'
  4. // Mock Taro路由和导航
  5. jest.mock('@tarojs/taro', () => ({
  6. useRouter: jest.fn(() => ({
  7. params: {
  8. startLocationId: '1',
  9. endLocationId: '2',
  10. date: '2025-10-18',
  11. vehicleType: 'bus'
  12. }
  13. })),
  14. navigateTo: jest.fn()
  15. }))
  16. // Mock API调用
  17. jest.mock('../../src/api', () => ({
  18. routeClient: {
  19. search: {
  20. $get: jest.fn().mockResolvedValue({
  21. status: 200,
  22. json: jest.fn().mockResolvedValue([
  23. {
  24. id: 1,
  25. startLocation: { name: '北京市' },
  26. endLocation: { name: '上海市' },
  27. activities: [
  28. {
  29. id: 101,
  30. name: '上海音乐节',
  31. venueLocation: {
  32. name: '上海大舞台',
  33. province: '上海市',
  34. city: '上海市',
  35. district: '徐汇区',
  36. address: '上海市徐汇区漕溪北路1111号'
  37. },
  38. startDate: '2025-10-20T19:00:00Z',
  39. endDate: '2025-10-20T22:00:00Z',
  40. imageUrl: 'https://example.com/concert.jpg'
  41. }
  42. ],
  43. routeType: 'departure'
  44. },
  45. {
  46. id: 2,
  47. startLocation: { name: '北京市' },
  48. endLocation: { name: '上海市' },
  49. activities: [
  50. {
  51. id: 102,
  52. name: '北京艺术展',
  53. venueLocation: {
  54. name: '北京美术馆',
  55. province: '北京市',
  56. city: '北京市',
  57. district: '东城区',
  58. address: '北京市东城区美术馆后街'
  59. },
  60. startDate: '2025-10-19T10:00:00Z',
  61. endDate: '2025-10-19T18:00:00Z',
  62. imageUrl: 'https://example.com/exhibition.jpg'
  63. }
  64. ],
  65. routeType: 'return'
  66. }
  67. ])
  68. })
  69. }
  70. }
  71. }))
  72. describe('ActivitySelectPage', () => {
  73. beforeEach(() => {
  74. jest.clearAllMocks()
  75. })
  76. it('应该正确渲染页面头部信息', async () => {
  77. const { getByText } = render(<ActivitySelectPage />)
  78. await waitFor(() => {
  79. expect(getByText('北京市 → 上海市')).toBeTruthy()
  80. expect(getByText('2025-10-18')).toBeTruthy()
  81. expect(getByText('选择观看活动')).toBeTruthy()
  82. })
  83. })
  84. it('应该加载并显示活动列表', async () => {
  85. const { getByText } = render(<ActivitySelectPage />)
  86. await waitFor(() => {
  87. expect(getByText('去程活动')).toBeTruthy()
  88. expect(getByText('返程活动')).toBeTruthy()
  89. expect(getByText('上海音乐节')).toBeTruthy()
  90. expect(getByText('北京艺术展')).toBeTruthy()
  91. })
  92. })
  93. it('应该正确显示活动信息', async () => {
  94. const { getByText } = render(<ActivitySelectPage />)
  95. await waitFor(() => {
  96. // 验证去程活动信息
  97. expect(getByText('上海音乐节')).toBeTruthy()
  98. expect(getByText('徐汇区 · 上海市 · 上海市')).toBeTruthy()
  99. expect(getByText('到达:上海市')).toBeTruthy()
  100. // 验证返程活动信息
  101. expect(getByText('北京艺术展')).toBeTruthy()
  102. expect(getByText('东城区 · 北京市 · 北京市')).toBeTruthy()
  103. expect(getByText('出发:北京市')).toBeTruthy()
  104. })
  105. })
  106. it('应该处理活动选择并导航', async () => {
  107. const mockNavigateTo = require('@tarojs/taro').navigateTo
  108. const { getByText } = render(<ActivitySelectPage />)
  109. await waitFor(() => {
  110. expect(getByText('上海音乐节')).toBeTruthy()
  111. })
  112. const activityItem = getByText('上海音乐节')
  113. fireEvent.click(activityItem)
  114. expect(mockNavigateTo).toHaveBeenCalledWith({
  115. url: '/pages/schedule-list/ScheduleListPage?startLocationId=1&endLocationId=2&date=2025-10-18&vehicleType=bus&activityId=101&routeType=departure'
  116. })
  117. })
  118. it('应该处理空活动列表', async () => {
  119. // Mock 空数据
  120. const routeClient = require('../../src/api').routeClient
  121. routeClient.search.$get.mockResolvedValueOnce({
  122. status: 200,
  123. json: jest.fn().mockResolvedValue([])
  124. })
  125. const { getByText } = render(<ActivitySelectPage />)
  126. await waitFor(() => {
  127. expect(getByText('暂无相关活动')).toBeTruthy()
  128. expect(getByText('北京市和上海市当前都没有热门活动')).toBeTruthy()
  129. })
  130. })
  131. it('应该处理加载状态', () => {
  132. // Mock 延迟加载
  133. const routeClient = require('../../src/api').routeClient
  134. routeClient.search.$get.mockImplementationOnce(
  135. () => new Promise(resolve => setTimeout(resolve, 100))
  136. )
  137. const { getByText } = render(<ActivitySelectPage />)
  138. expect(getByText('加载中...')).toBeTruthy()
  139. })
  140. it('应该正确格式化日期', async () => {
  141. const { getByText } = render(<ActivitySelectPage />)
  142. await waitFor(() => {
  143. // 验证日期格式化
  144. expect(getByText('2025/10/20')).toBeTruthy()
  145. expect(getByText('2025/10/19')).toBeTruthy()
  146. })
  147. })
  148. it('应该显示活动地址信息', async () => {
  149. const { getByText } = render(<ActivitySelectPage />)
  150. await waitFor(() => {
  151. expect(getByText('上海市徐汇区漕溪北路1111号')).toBeTruthy()
  152. expect(getByText('北京市东城区美术馆后街')).toBeTruthy()
  153. })
  154. })
  155. it('应该处理路由参数缺失的情况', () => {
  156. // Mock 缺失参数
  157. const useRouter = require('@tarojs/taro').useRouter
  158. useRouter.mockReturnValueOnce({
  159. params: {}
  160. })
  161. const { getByText } = render(<ActivitySelectPage />)
  162. // 验证页面仍然渲染,但可能显示错误或空状态
  163. expect(getByText('选择观看活动')).toBeTruthy()
  164. })
  165. it('应该去重活动列表', async () => {
  166. // Mock 包含重复活动的数据
  167. const routeClient = require('../../src/api').routeClient
  168. routeClient.search.$get.mockResolvedValueOnce({
  169. status: 200,
  170. json: jest.fn().mockResolvedValue([
  171. {
  172. id: 1,
  173. startLocation: { name: '北京市' },
  174. endLocation: { name: '上海市' },
  175. activities: [
  176. {
  177. id: 101,
  178. name: '上海音乐节',
  179. venueLocation: { name: '上海大舞台' },
  180. startDate: '2025-10-20T19:00:00Z',
  181. endDate: '2025-10-20T22:00:00Z'
  182. }
  183. ],
  184. routeType: 'departure'
  185. },
  186. {
  187. id: 2,
  188. startLocation: { name: '北京市' },
  189. endLocation: { name: '上海市' },
  190. activities: [
  191. {
  192. id: 101,
  193. name: '上海音乐节',
  194. venueLocation: { name: '上海大舞台' },
  195. startDate: '2025-10-20T19:00:00Z',
  196. endDate: '2025-10-20T22:00:00Z'
  197. }
  198. ],
  199. routeType: 'departure'
  200. }
  201. ])
  202. })
  203. const { getAllByText } = render(<ActivitySelectPage />)
  204. await waitFor(() => {
  205. // 验证重复活动只显示一次
  206. const activityItems = getAllByText('上海音乐节')
  207. expect(activityItems.length).toBe(1)
  208. })
  209. })
  210. })