basic.test.tsx 7.7 KB

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