basic.test.tsx 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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 AddressManagePage from '@/pages/address-manage/index'
  5. // 导入Taro mock函数
  6. import { mockGetCurrentPages, mockNavigateTo, mockShowModal } from '~/__mocks__/taroMock'
  7. // Mock API client
  8. jest.mock('@/api', () => ({
  9. deliveryAddressClient: {
  10. $get: jest.fn(),
  11. $post: jest.fn(),
  12. ':id': {
  13. $put: jest.fn(),
  14. $delete: jest.fn(),
  15. 'set-default': {
  16. $post: jest.fn(),
  17. },
  18. },
  19. },
  20. }))
  21. // Mock auth hook
  22. jest.mock('@/utils/auth', () => ({
  23. useAuth: () => ({
  24. user: { id: 1 },
  25. }),
  26. }))
  27. // Mock components
  28. jest.mock('@/components/ui/navbar', () => ({
  29. Navbar: ({ title, onClickLeft }: { title: string; onClickLeft: () => void }) => (
  30. <div data-testid="navbar">
  31. <span>{title}</span>
  32. <button onClick={onClickLeft}>返回</button>
  33. </div>
  34. ),
  35. }))
  36. jest.mock('@/components/ui/button', () => ({
  37. Button: ({ children, onClick, disabled, className }: any) => (
  38. <button
  39. onClick={onClick}
  40. disabled={disabled}
  41. className={className}
  42. data-testid="button"
  43. >
  44. {children}
  45. </button>
  46. ),
  47. }))
  48. describe('AddressManagePage', () => {
  49. let queryClient: QueryClient
  50. beforeEach(() => {
  51. queryClient = new QueryClient({
  52. defaultOptions: {
  53. queries: { retry: false },
  54. mutations: { retry: false },
  55. },
  56. })
  57. // Reset all mocks
  58. jest.clearAllMocks()
  59. // 设置 getCurrentPages 的默认返回值
  60. mockGetCurrentPages.mockReturnValue([{ route: 'pages/address-manage/index' }])
  61. })
  62. const renderWithProviders = (component: React.ReactElement) => {
  63. return render(
  64. <QueryClientProvider client={queryClient}>
  65. {component}
  66. </QueryClientProvider>
  67. )
  68. }
  69. const mockAddresses = [
  70. {
  71. id: 1,
  72. name: '张三',
  73. phone: '13812345678',
  74. province: { name: '广东省' },
  75. city: { name: '深圳市' },
  76. district: { name: '南山区' },
  77. town: { name: '科技园' },
  78. address: '科技大厦A座',
  79. isDefault: 1,
  80. },
  81. {
  82. id: 2,
  83. name: '李四',
  84. phone: '13987654321',
  85. province: { name: '北京市' },
  86. city: { name: '北京市' },
  87. district: { name: '朝阳区' },
  88. town: { name: '' },
  89. address: '国贸中心',
  90. isDefault: 0,
  91. },
  92. ]
  93. it('渲染页面标题和布局', async () => {
  94. const { deliveryAddressClient } = await import('@/api')
  95. ;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
  96. status: 200,
  97. json: async () => ({ data: [] }),
  98. } as any)
  99. renderWithProviders(<AddressManagePage />)
  100. expect(screen.getByTestId('navbar')).toBeInTheDocument()
  101. expect(screen.getByText('收货地址')).toBeInTheDocument()
  102. })
  103. it('显示地址列表', async () => {
  104. const { deliveryAddressClient } = await import('@/api')
  105. ;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
  106. status: 200,
  107. json: async () => ({ data: mockAddresses }),
  108. } as any)
  109. renderWithProviders(<AddressManagePage />)
  110. await waitFor(() => {
  111. expect(screen.getByText('张三')).toBeInTheDocument()
  112. expect(screen.getByText('李四')).toBeInTheDocument()
  113. expect(screen.getByText('138****5678')).toBeInTheDocument()
  114. expect(screen.getByText('139****4321')).toBeInTheDocument()
  115. expect(screen.getByText('默认')).toBeInTheDocument()
  116. })
  117. })
  118. it('显示空状态', async () => {
  119. const { deliveryAddressClient } = await import('@/api')
  120. ;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
  121. status: 200,
  122. json: async () => ({ data: [] }),
  123. } as any)
  124. renderWithProviders(<AddressManagePage />)
  125. await waitFor(() => {
  126. expect(screen.getByText('暂无收货地址')).toBeInTheDocument()
  127. })
  128. })
  129. it('显示地址数量限制提示', async () => {
  130. const { deliveryAddressClient } = await import('@/api')
  131. const addresses = Array.from({ length: 20 }, (_, i) => ({
  132. id: i + 1,
  133. name: `用户${i + 1}`,
  134. phone: '13812345678',
  135. province: { name: '广东省' },
  136. city: { name: '深圳市' },
  137. district: { name: '南山区' },
  138. address: '测试地址',
  139. isDefault: i === 0 ? 1 : 0,
  140. }))
  141. ;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
  142. status: 200,
  143. json: async () => ({ data: addresses }),
  144. } as any)
  145. renderWithProviders(<AddressManagePage />)
  146. await waitFor(() => {
  147. expect(screen.getByText('最多可添加20个收货地址')).toBeInTheDocument()
  148. })
  149. })
  150. it('点击添加地址按钮', async () => {
  151. const { deliveryAddressClient } = await import('@/api')
  152. ;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
  153. status: 200,
  154. json: async () => ({ data: [] }),
  155. } as any)
  156. renderWithProviders(<AddressManagePage />)
  157. await waitFor(() => {
  158. const addButton = screen.getByText('添加新地址')
  159. fireEvent.click(addButton)
  160. expect(mockNavigateTo).toHaveBeenCalledWith({
  161. url: '/pages/address-edit/index',
  162. })
  163. })
  164. })
  165. it('点击编辑地址按钮', async () => {
  166. const { deliveryAddressClient } = await import('@/api')
  167. ;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
  168. status: 200,
  169. json: async () => ({ data: mockAddresses }),
  170. } as any)
  171. renderWithProviders(<AddressManagePage />)
  172. await waitFor(() => {
  173. const editButtons = screen.getAllByText('编辑')
  174. fireEvent.click(editButtons[0])
  175. expect(mockNavigateTo).toHaveBeenCalledWith({
  176. url: '/pages/address-edit/index?id=1',
  177. })
  178. })
  179. })
  180. it('点击设为默认按钮', async () => {
  181. const { deliveryAddressClient } = await import('@/api')
  182. ;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
  183. status: 200,
  184. json: async () => ({ data: mockAddresses }),
  185. } as any)
  186. ;(deliveryAddressClient[':id'].$put as jest.Mock).mockResolvedValue({
  187. status: 200,
  188. json: async () => ({}),
  189. } as any)
  190. renderWithProviders(<AddressManagePage />)
  191. await waitFor(() => {
  192. const setDefaultButtons = screen.getAllByText('设为默认')
  193. fireEvent.click(setDefaultButtons[0])
  194. expect(deliveryAddressClient[':id'].$put).toHaveBeenCalledWith({
  195. param: { id: 2 },
  196. json: { isDefault: 1 },
  197. })
  198. })
  199. })
  200. it('点击删除按钮', async () => {
  201. const { deliveryAddressClient } = await import('@/api')
  202. ;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
  203. status: 200,
  204. json: async () => ({ data: mockAddresses }),
  205. } as any)
  206. ;(deliveryAddressClient[':id'].$delete as jest.Mock).mockResolvedValue({
  207. status: 204,
  208. json: async () => ({}),
  209. } as any)
  210. renderWithProviders(<AddressManagePage />)
  211. await waitFor(() => {
  212. const deleteButtons = screen.getAllByText('删除')
  213. fireEvent.click(deleteButtons[0])
  214. expect(mockShowModal).toHaveBeenCalled()
  215. })
  216. })
  217. it('验证样式类名应用', async () => {
  218. const { deliveryAddressClient } = await import('@/api')
  219. ;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
  220. status: 200,
  221. json: async () => ({ data: mockAddresses }),
  222. } as any)
  223. renderWithProviders(<AddressManagePage />)
  224. await waitFor(() => {
  225. const container = document.querySelector('.address-container')
  226. expect(container).toBeInTheDocument()
  227. const addressList = document.querySelector('.address-list')
  228. expect(addressList).toBeInTheDocument()
  229. const addressItems = document.querySelectorAll('.address-item')
  230. expect(addressItems).toHaveLength(2)
  231. const bottomFixed = document.querySelector('.bottom-fixed')
  232. expect(bottomFixed).toBeInTheDocument()
  233. })
  234. })
  235. })