import React from 'react'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import AddressManagePage from '@/pages/address-manage/index'
// 导入Taro mock函数
import { mockGetCurrentPages, mockNavigateTo, mockShowModal } from '~/__mocks__/taroMock'
// Mock API client
jest.mock('@/api', () => ({
deliveryAddressClient: {
$get: jest.fn(),
$post: jest.fn(),
':id': {
$put: jest.fn(),
$delete: jest.fn(),
},
},
}))
// Mock auth hook
jest.mock('@/utils/auth', () => ({
useAuth: () => ({
user: { id: 1 },
}),
}))
// Mock components
jest.mock('@/components/ui/navbar', () => ({
Navbar: ({ title, onClickLeft }: { title: string; onClickLeft: () => void }) => (
{title}
),
}))
jest.mock('@/components/ui/button', () => ({
Button: ({ children, onClick, disabled, className }: any) => (
),
}))
describe('AddressManagePage', () => {
let queryClient: QueryClient
beforeEach(() => {
queryClient = new QueryClient({
defaultOptions: {
queries: { retry: false },
mutations: { retry: false },
},
})
// Reset all mocks
jest.clearAllMocks()
// 设置 getCurrentPages 的默认返回值
mockGetCurrentPages.mockReturnValue([{ route: 'pages/address-manage/index' }])
})
const renderWithProviders = (component: React.ReactElement) => {
return render(
{component}
)
}
const mockAddresses = [
{
id: 1,
name: '张三',
phone: '13812345678',
province: { name: '广东省' },
city: { name: '深圳市' },
district: { name: '南山区' },
town: { name: '科技园' },
address: '科技大厦A座',
isDefault: 1,
},
{
id: 2,
name: '李四',
phone: '13987654321',
province: { name: '北京市' },
city: { name: '北京市' },
district: { name: '朝阳区' },
town: { name: '' },
address: '国贸中心',
isDefault: 0,
},
]
it('渲染页面标题和布局', async () => {
const { deliveryAddressClient } = await import('@/api')
;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
status: 200,
json: async () => ({ data: [] }),
} as any)
renderWithProviders()
expect(screen.getByTestId('navbar')).toBeInTheDocument()
expect(screen.getByText('收货地址')).toBeInTheDocument()
})
it('显示地址列表', async () => {
const { deliveryAddressClient } = await import('@/api')
;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
status: 200,
json: async () => ({ data: mockAddresses }),
} as any)
renderWithProviders()
await waitFor(() => {
expect(screen.getByText('张三')).toBeInTheDocument()
expect(screen.getByText('李四')).toBeInTheDocument()
expect(screen.getByText('138****5678')).toBeInTheDocument()
expect(screen.getByText('139****4321')).toBeInTheDocument()
expect(screen.getByText('默认')).toBeInTheDocument()
})
})
it('显示空状态', async () => {
const { deliveryAddressClient } = await import('@/api')
;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
status: 200,
json: async () => ({ data: [] }),
} as any)
renderWithProviders()
await waitFor(() => {
expect(screen.getByText('暂无收货地址')).toBeInTheDocument()
})
})
it('显示地址数量限制提示', async () => {
const { deliveryAddressClient } = await import('@/api')
const addresses = Array.from({ length: 20 }, (_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
phone: '13812345678',
province: { name: '广东省' },
city: { name: '深圳市' },
district: { name: '南山区' },
address: '测试地址',
isDefault: i === 0 ? 1 : 0,
}))
;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
status: 200,
json: async () => ({ data: addresses }),
} as any)
renderWithProviders()
await waitFor(() => {
expect(screen.getByText('最多可添加20个收货地址')).toBeInTheDocument()
})
})
it('点击添加地址按钮', async () => {
const { deliveryAddressClient } = await import('@/api')
;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
status: 200,
json: async () => ({ data: [] }),
} as any)
renderWithProviders()
await waitFor(() => {
const addButton = screen.getByText('添加新地址')
fireEvent.click(addButton)
expect(mockNavigateTo).toHaveBeenCalledWith({
url: '/pages/address-edit/index',
})
})
})
it('点击编辑地址按钮', async () => {
const { deliveryAddressClient } = await import('@/api')
;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
status: 200,
json: async () => ({ data: mockAddresses }),
} as any)
renderWithProviders()
await waitFor(() => {
const editButtons = screen.getAllByText('编辑')
fireEvent.click(editButtons[0])
expect(mockNavigateTo).toHaveBeenCalledWith({
url: '/pages/address-edit/index?id=1',
})
})
})
it('点击设为默认按钮', async () => {
const { deliveryAddressClient } = await import('@/api')
;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
status: 200,
json: async () => ({ data: mockAddresses }),
} as any)
;(deliveryAddressClient[':id'].$put as jest.Mock).mockResolvedValue({
status: 200,
json: async () => ({}),
} as any)
renderWithProviders()
await waitFor(() => {
const setDefaultButtons = screen.getAllByText('设为默认')
fireEvent.click(setDefaultButtons[0])
expect(deliveryAddressClient[':id'].$put).toHaveBeenCalledWith({
param: { id: 2 },
json: { isDefault: 1 },
})
})
})
it('点击删除按钮', async () => {
const { deliveryAddressClient } = await import('@/api')
;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
status: 200,
json: async () => ({ data: mockAddresses }),
} as any)
;(deliveryAddressClient[':id'].$delete as jest.Mock).mockResolvedValue({
status: 204,
json: async () => ({}),
} as any)
renderWithProviders()
await waitFor(() => {
const deleteButtons = screen.getAllByText('删除')
fireEvent.click(deleteButtons[0])
expect(mockShowModal).toHaveBeenCalled()
})
})
it('验证样式类名应用', async () => {
const { deliveryAddressClient } = await import('@/api')
;(deliveryAddressClient.$get as jest.Mock).mockResolvedValue({
status: 200,
json: async () => ({ data: mockAddresses }),
} as any)
renderWithProviders()
await waitFor(() => {
const container = document.querySelector('.address-container')
expect(container).toBeInTheDocument()
const addressList = document.querySelector('.address-list')
expect(addressList).toBeInTheDocument()
const addressItems = document.querySelectorAll('.address-item')
expect(addressItems).toHaveLength(2)
const bottomFixed = document.querySelector('.bottom-fixed')
expect(bottomFixed).toBeInTheDocument()
})
})
})