|
@@ -7,42 +7,32 @@ import { mockShowToast, mockShowModal, mockNavigateTo, mockSetStorageSync, mockR
|
|
|
// Mock Taro API
|
|
// Mock Taro API
|
|
|
jest.mock('@tarojs/taro', () => jest.requireActual('~/__mocks__/taroMock'))
|
|
jest.mock('@tarojs/taro', () => jest.requireActual('~/__mocks__/taroMock'))
|
|
|
|
|
|
|
|
-// Mock购物车hook
|
|
|
|
|
-jest.mock('@/contexts/CartContext', () => ({
|
|
|
|
|
- useCart: () => ({
|
|
|
|
|
- cart: {
|
|
|
|
|
- items: [
|
|
|
|
|
- {
|
|
|
|
|
- id: 1,
|
|
|
|
|
- parentGoodsId: 100, // 父商品ID
|
|
|
|
|
- name: '测试商品1',
|
|
|
|
|
- price: 29.9,
|
|
|
|
|
- image: 'test-image1.jpg',
|
|
|
|
|
- stock: 10,
|
|
|
|
|
- quantity: 2,
|
|
|
|
|
- spec: '红色/M',
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- id: 2,
|
|
|
|
|
- parentGoodsId: 200, // 父商品ID
|
|
|
|
|
- name: '测试商品2',
|
|
|
|
|
- price: 49.9,
|
|
|
|
|
- image: 'test-image2.jpg',
|
|
|
|
|
- stock: 5,
|
|
|
|
|
- quantity: 1,
|
|
|
|
|
- spec: '蓝色/L',
|
|
|
|
|
- },
|
|
|
|
|
- ],
|
|
|
|
|
- totalAmount: 109.7,
|
|
|
|
|
- totalCount: 3,
|
|
|
|
|
- },
|
|
|
|
|
- updateQuantity: jest.fn(),
|
|
|
|
|
- removeFromCart: jest.fn(),
|
|
|
|
|
- switchSpec: jest.fn(),
|
|
|
|
|
- clearCart: jest.fn(),
|
|
|
|
|
- isLoading: false,
|
|
|
|
|
- }),
|
|
|
|
|
-}))
|
|
|
|
|
|
|
+// 使用真实CartContext,通过mock存储控制初始状态
|
|
|
|
|
+import { CartProvider } from '@/contexts/CartContext'
|
|
|
|
|
+
|
|
|
|
|
+// 购物车测试数据
|
|
|
|
|
+const mockCartItems = [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 1,
|
|
|
|
|
+ parentGoodsId: 100, // 父商品ID
|
|
|
|
|
+ name: '测试商品1',
|
|
|
|
|
+ price: 29.9,
|
|
|
|
|
+ image: 'test-image1.jpg',
|
|
|
|
|
+ stock: 10,
|
|
|
|
|
+ quantity: 2,
|
|
|
|
|
+ spec: '红色/M',
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 2,
|
|
|
|
|
+ parentGoodsId: 200, // 父商品ID
|
|
|
|
|
+ name: '测试商品2',
|
|
|
|
|
+ price: 49.9,
|
|
|
|
|
+ image: 'test-image2.jpg',
|
|
|
|
|
+ stock: 5,
|
|
|
|
|
+ quantity: 1,
|
|
|
|
|
+ spec: '蓝色/L',
|
|
|
|
|
+ },
|
|
|
|
|
+]
|
|
|
|
|
|
|
|
// Mock API客户端
|
|
// Mock API客户端
|
|
|
const mockGoodsData = {
|
|
const mockGoodsData = {
|
|
@@ -66,7 +56,9 @@ const mockGoodsClient = {
|
|
|
':id': {
|
|
':id': {
|
|
|
$get: jest.fn(({ param }: any) => {
|
|
$get: jest.fn(({ param }: any) => {
|
|
|
const goodsId = param?.id
|
|
const goodsId = param?.id
|
|
|
|
|
+ console.log('mockGoodsClient called with id:', goodsId)
|
|
|
const goodsData = mockGoodsData[goodsId as keyof typeof mockGoodsData] || mockGoodsData[1]
|
|
const goodsData = mockGoodsData[goodsId as keyof typeof mockGoodsData] || mockGoodsData[1]
|
|
|
|
|
+ console.log('Returning goods data:', goodsData)
|
|
|
return Promise.resolve({
|
|
return Promise.resolve({
|
|
|
status: 200,
|
|
status: 200,
|
|
|
json: () => Promise.resolve(goodsData)
|
|
json: () => Promise.resolve(goodsData)
|
|
@@ -121,12 +113,14 @@ const createTestQueryClient = () => new QueryClient({
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
-// 包装组件提供QueryClientProvider
|
|
|
|
|
|
|
+// 包装组件提供QueryClientProvider和CartProvider
|
|
|
const renderWithProviders = (ui: React.ReactElement) => {
|
|
const renderWithProviders = (ui: React.ReactElement) => {
|
|
|
const testQueryClient = createTestQueryClient()
|
|
const testQueryClient = createTestQueryClient()
|
|
|
return render(
|
|
return render(
|
|
|
<QueryClientProvider client={testQueryClient}>
|
|
<QueryClientProvider client={testQueryClient}>
|
|
|
- {ui}
|
|
|
|
|
|
|
+ <CartProvider>
|
|
|
|
|
+ {ui}
|
|
|
|
|
+ </CartProvider>
|
|
|
</QueryClientProvider>
|
|
</QueryClientProvider>
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
@@ -134,7 +128,8 @@ const renderWithProviders = (ui: React.ReactElement) => {
|
|
|
describe('购物车页面', () => {
|
|
describe('购物车页面', () => {
|
|
|
beforeEach(() => {
|
|
beforeEach(() => {
|
|
|
jest.clearAllMocks()
|
|
jest.clearAllMocks()
|
|
|
- mockGetStorageSync.mockReturnValue(null)
|
|
|
|
|
|
|
+ // 设置默认购物车数据(包含2个商品)
|
|
|
|
|
+ mockGetStorageSync.mockReturnValue({ items: mockCartItems })
|
|
|
mockShowModal.mockImplementation(() => Promise.resolve({ confirm: true }))
|
|
mockShowModal.mockImplementation(() => Promise.resolve({ confirm: true }))
|
|
|
mockGoodsClient[':id'].$get.mockClear()
|
|
mockGoodsClient[':id'].$get.mockClear()
|
|
|
// 设置默认mock实现
|
|
// 设置默认mock实现
|
|
@@ -230,9 +225,18 @@ describe('购物车页面', () => {
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- it.skip('应该显示库存不足提示', () => {
|
|
|
|
|
- const { getByText } = renderWithProviders(<CartPage />)
|
|
|
|
|
- expect(getByText('仅剩3件')).toBeDefined() // 商品2的库存
|
|
|
|
|
|
|
+ it.skip('应该显示库存不足提示', async () => {
|
|
|
|
|
+ // 跳过:库存提示显示逻辑需要进一步调查
|
|
|
|
|
+ // 问题:goodsStock可能没有正确从查询获取,导致库存提示不显示
|
|
|
|
|
+ const { findByText, container } = renderWithProviders(<CartPage />)
|
|
|
|
|
+ // 先等待商品2加载完成
|
|
|
|
|
+ await findByText('测试商品2')
|
|
|
|
|
+ // 检查库存提示元素是否存在
|
|
|
|
|
+ const stockMaskElements = container.querySelectorAll('.stock-mask')
|
|
|
|
|
+ console.log('Stock mask elements count:', stockMaskElements.length)
|
|
|
|
|
+ stockMaskElements.forEach(el => console.log('Stock mask text:', el.textContent))
|
|
|
|
|
+ // 然后检查库存提示文本
|
|
|
|
|
+ expect(await findByText('仅剩2件')).toBeDefined() // 商品2的库存现在是2
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
it('应该显示广告区域', () => {
|
|
it('应该显示广告区域', () => {
|
|
@@ -241,32 +245,26 @@ describe('购物车页面', () => {
|
|
|
expect(adElement).toBeDefined()
|
|
expect(adElement).toBeDefined()
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- describe.skip('空购物车状态', () => {
|
|
|
|
|
|
|
+ describe('空购物车状态', () => {
|
|
|
beforeEach(() => {
|
|
beforeEach(() => {
|
|
|
- // Mock空购物车状态
|
|
|
|
|
- jest.doMock('@/contexts/CartContext', () => ({
|
|
|
|
|
- useCart: () => ({
|
|
|
|
|
- cart: {
|
|
|
|
|
- items: [],
|
|
|
|
|
- totalAmount: 0,
|
|
|
|
|
- totalCount: 0,
|
|
|
|
|
- },
|
|
|
|
|
- updateQuantity: jest.fn(),
|
|
|
|
|
- removeFromCart: jest.fn(),
|
|
|
|
|
- clearCart: jest.fn(),
|
|
|
|
|
- isLoading: false,
|
|
|
|
|
- }),
|
|
|
|
|
- }))
|
|
|
|
|
|
|
+ // 设置空购物车数据
|
|
|
|
|
+ mockGetStorageSync.mockReturnValue({ items: [] })
|
|
|
|
|
+ // 确保其他mock被清除
|
|
|
|
|
+ mockShowModal.mockImplementation(() => Promise.resolve({ confirm: true }))
|
|
|
|
|
+ mockGoodsClient[':id'].$get.mockClear()
|
|
|
|
|
+ mockRequest.mockClear()
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- it('应该显示空购物车状态', () => {
|
|
|
|
|
- const { getByText } = renderWithProviders(<CartPage />)
|
|
|
|
|
- expect(getByText('购物车是空的')).toBeDefined()
|
|
|
|
|
- expect(getByText('去首页逛逛')).toBeDefined()
|
|
|
|
|
|
|
+ it('应该显示空购物车状态', async () => {
|
|
|
|
|
+ const { findByText } = renderWithProviders(<CartPage />)
|
|
|
|
|
+ expect(await findByText('购物车是空的')).toBeDefined()
|
|
|
|
|
+ expect(await findByText('去首页逛逛')).toBeDefined()
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- it('应该隐藏底部结算栏', () => {
|
|
|
|
|
- const { queryByText } = renderWithProviders(<CartPage />)
|
|
|
|
|
|
|
+ it('应该隐藏底部结算栏', async () => {
|
|
|
|
|
+ const { queryByText, findByText } = renderWithProviders(<CartPage />)
|
|
|
|
|
+ // 等待空状态显示,确保骨架屏已消失
|
|
|
|
|
+ await findByText('购物车是空的')
|
|
|
expect(queryByText('去结算')).toBeNull()
|
|
expect(queryByText('去结算')).toBeNull()
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|