import React from 'react' import { render } from '@testing-library/react' import { CartProvider, useCart, CartItem } from '@/contexts/CartContext' import { mockShowToast, mockGetStorageSync, mockSetStorageSync } from '~/__mocks__/taroMock' // Mock Taro API jest.mock('@tarojs/taro', () => jest.requireActual('~/__mocks__/taroMock')) // 测试组件用于访问购物车hook const TestComponent = ({ action, item }: { action: string; item?: CartItem }) => { const cart = useCart() React.useEffect(() => { console.log('TestComponent useEffect called, action:', action, 'item:', item, 'isLoading:', cart.isLoading) // 等待购物车加载完成后再添加商品 if (!cart.isLoading && action === 'add' && item) { console.log('Calling addToCart with item:', item) cart.addToCart(item) } }, [action, item, cart.isLoading]) console.log('TestComponent rendering, cart items:', cart.cart.items, 'isLoading:', cart.isLoading) return (
{cart.cart.items.length}
{cart.cart.totalCount}
{cart.cart.totalAmount}
{cart.cart.items.map((item, index) => (
{item.id} {item.name} {/* spec字段已移除 */} {item.quantity} {item.stock}
))}
) } describe('CartContext - 规格支持', () => { beforeEach(() => { mockGetStorageSync.mockReturnValue(null) mockSetStorageSync.mockClear() mockShowToast.mockClear() }) it('应该支持添加父商品到购物车', () => { const parentGoods: CartItem = { id: 1001, parentGoodsId: 0, // 父商品,无父商品 name: '测试父商品', price: 99.9, image: 'parent.jpg', stock: 10, quantity: 2, } const { getByTestId } = render( ) expect(getByTestId('items-count').textContent).toBe('1') expect(getByTestId('item-0-id').textContent).toBe('1001') expect(getByTestId('item-0-name').textContent).toBe('测试父商品') expect(mockSetStorageSync).toHaveBeenCalled() }) it('应该支持添加子商品(带规格)到购物车', () => { const childGoods: CartItem = { id: 2001, // 子商品ID parentGoodsId: 2000, // 父商品ID name: '红色/M', // 规格名称 price: 109.9, image: 'child.jpg', stock: 5, quantity: 1, } const { getByTestId } = render( ) expect(getByTestId('items-count').textContent).toBe('1') expect(getByTestId('item-0-id').textContent).toBe('2001') expect(getByTestId('item-0-name').textContent).toBe('红色/M') expect(mockSetStorageSync).toHaveBeenCalled() }) it('应该支持添加同一子商品多次(数量累加)', () => { const childGoods1: CartItem = { id: 3001, parentGoodsId: 3000, // 父商品ID name: '蓝色/L', // 规格名称 price: 89.9, image: 'goods.jpg', stock: 10, quantity: 1, } const childGoods2: CartItem = { id: 3001, // 同一子商品ID parentGoodsId: 3000, // 父商品ID name: '蓝色/L', // 规格名称 price: 89.9, image: 'goods.jpg', stock: 10, quantity: 3, } const { getByTestId, rerender } = render( ) expect(getByTestId('items-count').textContent).toBe('1') console.log('Item 0 id:', getByTestId('item-0-id').textContent) console.log('Item 0 name:', getByTestId('item-0-name').textContent) const quantityElement = getByTestId('item-0-quantity') console.log('Quantity element text:', quantityElement.textContent) // 修复:检查数量是否正确,应该是1而不是库存值10 expect(parseInt(quantityElement.textContent || '0')).toBe(1) // 重新渲染添加更多数量 rerender( ) expect(getByTestId('item-0-quantity').textContent).toBe('4') // 1 + 3 }) it('应该限制数量不超过库存', () => { const childGoods: CartItem = { id: 4001, parentGoodsId: 4000, // 父商品ID name: '测试商品 - 黑色/XL', price: 129.9, image: 'goods.jpg', stock: 2, // 库存只有2 quantity: 3, // 尝试购买3个 } const { getByTestId } = render( ) // 应该显示库存不足提示 expect(mockShowToast).toHaveBeenCalledWith( expect.objectContaining({ title: '库存不足' }) ) // 商品不应被添加 expect(getByTestId('items-count').textContent).toBe('0') }) it('应该支持同时添加父商品和不同子商品', () => { const parentGoods: CartItem = { id: 5001, parentGoodsId: 0, // 父商品,无父商品 name: '测试父商品', price: 199.9, image: 'parent.jpg', stock: 20, quantity: 1, } const childGoods1: CartItem = { id: 5002, // 子商品ID1 parentGoodsId: 5001, // 父商品ID name: '测试父商品 - 规格A', price: 219.9, image: 'child1.jpg', stock: 5, quantity: 2, } const childGoods2: CartItem = { id: 5003, // 子商品ID2 parentGoodsId: 5001, // 父商品ID name: '测试父商品 - 规格B', price: 229.9, image: 'child2.jpg', stock: 3, quantity: 1, } const { getByTestId, rerender } = render( ) expect(getByTestId('items-count').textContent).toBe('1') // 添加第一个子商品 rerender( ) expect(getByTestId('items-count').textContent).toBe('2') // 添加第二个子商品 rerender( ) expect(getByTestId('items-count').textContent).toBe('3') expect(getByTestId('item-0-id').textContent).toBe('5001') expect(getByTestId('item-1-id').textContent).toBe('5002') expect(getByTestId('item-2-id').textContent).toBe('5003') }) it('应该支持切换购物车项规格', () => { // 首先添加一个子商品到购物车 const childGoods: CartItem = { id: 6001, parentGoodsId: 6000, // 父商品ID name: '测试父商品 - 规格A', price: 99.9, image: 'child1.jpg', stock: 10, quantity: 2, } // 创建一个新的测试组件来测试switchSpec const TestSwitchSpecComponent = ({ cartItemId, newChildGoods }: { cartItemId?: number, newChildGoods?: { id: number; name: string; price: number; stock: number; image?: string } }) => { const cart = useCart() React.useEffect(() => { if (!cart.isLoading && cartItemId && newChildGoods) { cart.switchSpec(cartItemId, newChildGoods) } }, [cart.isLoading, cartItemId, newChildGoods]) return (
{cart.cart.items.length}
{cart.cart.items.map((item, index) => (
{item.id} {item.name} {/* spec字段已移除 */} {item.quantity} {item.price}
))}
) } const { getByTestId, rerender } = render( ) expect(getByTestId('items-count').textContent).toBe('1') expect(getByTestId('item-0-id').textContent).toBe('6001') expect(getByTestId('item-0-name').textContent).toBe('测试父商品 - 规格A') // 切换到新规格 const newChildGoods = { id: 6002, name: '规格B', // 规格名称 price: 119.9, stock: 5, image: 'child2.jpg', } rerender( ) // 验证规格已切换 expect(getByTestId('items-count').textContent).toBe('1') expect(getByTestId('item-0-id').textContent).toBe('6002') // ID已更新 expect(getByTestId('item-0-name').textContent).toBe('规格B') // 规格名称 expect(getByTestId('item-0-price').textContent).toBe('119.9') expect(getByTestId('item-0-quantity').textContent).toBe('2') // 数量保持不变 }) it('切换规格时应该验证库存', () => { const childGoods: CartItem = { id: 7001, parentGoodsId: 7000, name: '测试商品 - 规格A', price: 50, image: 'test.jpg', stock: 10, quantity: 8, // 当前数量8 } const TestSwitchSpecComponent = ({ cartItemId, newChildGoods }: { cartItemId?: number, newChildGoods?: { id: number; name: string; price: number; stock: number; image?: string } }) => { const cart = useCart() React.useEffect(() => { if (!cart.isLoading && cartItemId && newChildGoods) { cart.switchSpec(cartItemId, newChildGoods) } }, [cart.isLoading, cartItemId, newChildGoods]) return
{mockShowToast.mock.calls.length}
} // 添加商品到购物车 const { getByTestId, rerender } = render( ) // 尝试切换到库存不足的规格(库存只有5,但当前数量是8) const newChildGoods = { id: 7002, name: '测试商品 - 规格B', price: 60, stock: 5, // 库存不足 image: 'test2.jpg', } rerender( ) // 应该显示库存不足提示 expect(mockShowToast).toHaveBeenCalledWith( expect.objectContaining({ title: expect.stringContaining('库存不足') }) ) }) it('单规格商品不应该支持切换规格', () => { const singleSpecGoods: CartItem = { id: 8001, parentGoodsId: 0, // 单规格商品 name: '单规格商品', price: 30, image: 'single.jpg', stock: 10, quantity: 1, } const TestSwitchSpecComponent = ({ cartItemId, newChildGoods }: { cartItemId?: number, newChildGoods?: { id: number; name: string; price: number; stock: number; image?: string } }) => { const cart = useCart() React.useEffect(() => { if (!cart.isLoading && cartItemId && newChildGoods) { cart.switchSpec(cartItemId, newChildGoods) } }, [cart.isLoading, cartItemId, newChildGoods]) return
Test
} // 添加单规格商品 const { rerender } = render( ) const newChildGoods = { id: 8002, name: '新规格', price: 40, stock: 5, } rerender( ) // 应该显示不支持切换的提示 expect(mockShowToast).toHaveBeenCalledWith( expect.objectContaining({ title: '该商品不支持切换规格' }) ) }) })