import '@testing-library/jest-dom'; import { useNFTContext } from '@/nft/components/NFTProvider'; import { useMintAnalytics } from '@/nft/hooks/useMintAnalytics'; import { fireEvent, render } from '@testing-library/react'; import { act } from 'react'; import { type Mock, afterEach, beforeEach, describe, expect, it, vi, } from 'vitest'; import { NFTQuantitySelector } from './NFTQuantitySelector'; vi.mock('@/nft/components/NFTProvider'); vi.mock('@/nft/hooks/useMintAnalytics'); vi.mock('@/internal/components/QuantitySelector', () => ({ QuantitySelector: ({ onChange, minQuantity, maxQuantity, }: { onChange: (s: string) => void; minQuantity: string; maxQuantity: string; }) => ( onChange(e.target.value)} data-minquantity={minQuantity} data-maxquantity={maxQuantity} /> ), })); describe('NFTQuantitySelector', () => { const setQuantityMock = vi.fn(); const handleQuantityChangeMock = vi.fn(); const useNFTContextMock = useNFTContext as Mock; beforeEach(() => { useNFTContextMock.mockReturnValue({ maxMintsPerWallet: 5, setQuantity: setQuantityMock, }); (useMintAnalytics as Mock).mockReturnValue({ handleQuantityChange: handleQuantityChangeMock, }); }); afterEach(() => { vi.clearAllMocks(); }); it('should render quantity selector', () => { const { getByRole } = render(); expect(getByRole('textbox')).toBeInTheDocument(); }); it('should not render when maxMintsPerWallet is 1', () => { useNFTContextMock.mockReturnValueOnce({ maxMintsPerWallet: 1 }); const { container } = render(); expect(container.firstChild).toBeNull(); }); it('should update quantity and trigger analytics on valid numeric input', () => { const { getByRole } = render(); const input = getByRole('textbox') as HTMLInputElement; act(() => { input.focus(); fireEvent.change(input, { target: { value: '3' } }); input.blur(); }); expect(setQuantityMock).toHaveBeenCalledWith('3'); expect(handleQuantityChangeMock).toHaveBeenCalledWith(3); }); it('should update quantity but not trigger analytics on invalid input', () => { const { getByRole } = render(); const input = getByRole('textbox') as HTMLInputElement; act(() => { input.focus(); fireEvent.change(input, { target: { value: 'abc' } }); input.blur(); }); expect(setQuantityMock).toHaveBeenCalledWith('abc'); expect(handleQuantityChangeMock).not.toHaveBeenCalled(); }); it('should apply the provided className to container and input', () => { const className = 'custom-class'; const { container } = render(); expect(container.firstChild).toHaveClass('custom-class'); }); it('should set correct min and max quantity constraints', () => { const { getByRole } = render(); const input = getByRole('textbox') as HTMLInputElement; expect(input).toHaveAttribute('data-minquantity', '1'); expect(input).toHaveAttribute('data-maxquantity', '5'); }); it('should not set maxQuantity when maxMintsPerWallet is undefined', () => { useNFTContextMock.mockReturnValueOnce({ maxMintsPerWallet: undefined }); const { getByRole } = render(); const input = getByRole('textbox') as HTMLInputElement; expect(input).not.toHaveAttribute('data-maxquantity'); }); });