import {renderHook} from '@testing-library/react' import {describe, expect, it, vi, beforeEach} from 'vitest' import {useShopIntent} from '../../internal/useShopIntent' import {useAddToCart} from './useAddToCart' vi.mock('../../internal/useShopIntent', () => ({ useShopIntent: vi.fn(), })) const mockUseShopIntent = useShopIntent as unknown as ReturnType const PRODUCT_ID = 'gid://shopify/Product/123' const VARIANT_ID = 'gid://shopify/ProductVariant/456' const VARIANT = { id: VARIANT_ID, title: 'Red / S', isFavorited: false, availableForSale: true, quantityAvailable: 5, selectedOptions: [ {name: 'Color', value: 'Red'}, {name: 'Size', value: 'S'}, ], image: {url: 'https://cdn/v.jpg'}, price: {amount: '10.00', currencyCode: 'USD'}, compareAtPrice: null, } describe('useAddToCart', () => { beforeEach(() => { vi.clearAllMocks() }) it('invokes the add_to_cart:shopify/ProductVariant intent with productId in data', async () => { const invokeQuery = vi.fn().mockResolvedValue({ code: 'ok', data: { outcome: 'added_to_cart', productVariantId: VARIANT_ID, variant: VARIANT, quantity: 1, source: 'auto', }, }) mockUseShopIntent.mockReturnValue({invokeQuery}) const {result} = renderHook(() => useAddToCart()) await result.current.addToCart({productId: PRODUCT_ID}) expect(invokeQuery).toHaveBeenCalledWith({ action: 'add_to_cart', type: 'shopify/ProductVariant', data: {productId: PRODUCT_ID}, }) }) it('passes optional params through as the intent data payload', async () => { const invokeQuery = vi.fn().mockResolvedValue({code: 'closed'}) mockUseShopIntent.mockReturnValue({invokeQuery}) const {result} = renderHook(() => useAddToCart()) await result.current.addToCart({ productId: PRODUCT_ID, productVariantId: VARIANT_ID, quantity: 2, discountCodes: ['SUMMER20'], includedProductVariantGIDs: [VARIANT_ID], initialVariantId: VARIANT_ID, initialQuantity: 2, maxQuantity: 10, showQuantity: false, forceShow: true, }) expect(invokeQuery).toHaveBeenCalledWith({ action: 'add_to_cart', type: 'shopify/ProductVariant', data: { productId: PRODUCT_ID, productVariantId: VARIANT_ID, quantity: 2, discountCodes: ['SUMMER20'], includedProductVariantGIDs: [VARIANT_ID], initialVariantId: VARIANT_ID, initialQuantity: 2, maxQuantity: 10, showQuantity: false, forceShow: true, }, }) }) it("returns the ok IntentResult with outcome 'added_to_cart' on direct ATC", async () => { const invokeQuery = vi.fn().mockResolvedValue({ code: 'ok', data: { outcome: 'added_to_cart', productVariantId: VARIANT_ID, variant: VARIANT, quantity: 2, source: 'auto', }, }) mockUseShopIntent.mockReturnValue({invokeQuery}) const {result} = renderHook(() => useAddToCart()) const response = await result.current.addToCart({ productId: PRODUCT_ID, productVariantId: VARIANT_ID, quantity: 2, }) expect(response).toEqual({ code: 'ok', data: { outcome: 'added_to_cart', productVariantId: VARIANT_ID, variant: VARIANT, quantity: 2, source: 'auto', }, }) }) it('returns the ok IntentResult with source user when sheet was shown', async () => { const invokeQuery = vi.fn().mockResolvedValue({ code: 'ok', data: { outcome: 'added_to_cart', productVariantId: VARIANT_ID, variant: VARIANT, quantity: 1, source: 'user', }, }) mockUseShopIntent.mockReturnValue({invokeQuery}) const {result} = renderHook(() => useAddToCart()) const response = await result.current.addToCart({productId: PRODUCT_ID}) if (response.code !== 'ok') throw new Error('expected ok') if (response.data.outcome !== 'added_to_cart') { throw new Error('expected added_to_cart outcome') } expect(response.data.source).toBe('user') }) it('returns the ok IntentResult with navigated_to_product outcome for referrals', async () => { const invokeQuery = vi.fn().mockResolvedValue({ code: 'ok', data: { outcome: 'navigated_to_product', productId: PRODUCT_ID, }, }) mockUseShopIntent.mockReturnValue({invokeQuery}) const {result} = renderHook(() => useAddToCart()) const response = await result.current.addToCart({productId: PRODUCT_ID}) if (response.code !== 'ok') throw new Error('expected ok') if (response.data.outcome !== 'navigated_to_product') { throw new Error('expected navigated_to_product outcome') } expect(response.data.productId).toBe(PRODUCT_ID) }) it('returns closed when the user dismisses the sheet', async () => { const invokeQuery = vi.fn().mockResolvedValue({code: 'closed'}) mockUseShopIntent.mockReturnValue({invokeQuery}) const {result} = renderHook(() => useAddToCart()) const response = await result.current.addToCart({productId: PRODUCT_ID}) expect(response).toEqual({code: 'closed'}) }) it('returns the error IntentResult when the host fails', async () => { const invokeQuery = vi.fn().mockResolvedValue({ code: 'error', message: 'sold out', }) mockUseShopIntent.mockReturnValue({invokeQuery}) const {result} = renderHook(() => useAddToCart()) const response = await result.current.addToCart({ productId: PRODUCT_ID, productVariantId: VARIANT_ID, }) expect(response).toEqual({code: 'error', message: 'sold out'}) }) })