import React from 'react' import {renderHook, waitFor} from '@testing-library/react' import {describe, expect, it, vi} from 'vitest' import {MinisQueryProvider} from './MinisQueryProvider' import {useShopActionQuery} from './useShopActionQuery' describe('useShopActionQuery', () => { const wrapper = ({children}: {children: React.ReactNode}) => ( {children} ) describe('Successful Data Fetching', () => { it('fetches and returns data', async () => { const mockAction = vi.fn().mockResolvedValue({ ok: true, data: {data: {id: '1', name: 'Test Product'}}, }) const {result} = renderHook( () => useShopActionQuery(['test-1'], mockAction, {}), {wrapper} ) await waitFor(() => { expect(result.current.loading).toBe(false) }) expect(result.current.data).toEqual({id: '1', name: 'Test Product'}) expect(result.current.error).toBeNull() expect(mockAction).toHaveBeenCalledWith({}) }) it('returns null when data is undefined', async () => { const mockAction = vi.fn().mockResolvedValue({ ok: true, data: {data: undefined}, }) const {result} = renderHook( () => useShopActionQuery(['test-undefined'], mockAction, {}), {wrapper} ) await waitFor(() => { expect(result.current.loading).toBe(false) }) expect(result.current.data).toBeNull() }) }) describe('Error Handling', () => { it('handles action errors (ok: false)', async () => { const mockAction = vi.fn().mockRejectedValue(new Error('API Error')) const {result} = renderHook( () => useShopActionQuery(['test-action-error'], mockAction, {}), {wrapper} ) // Wait for loading to complete (after retries) await waitFor( () => { expect(result.current.loading).toBe(false) }, {timeout: 3000} ) expect(result.current.data).toBeNull() expect(result.current.error).toBeInstanceOf(Error) expect(result.current.error?.message).toBe('API Error') }) }) describe('Skip Parameter', () => { it('does not fetch when skip is true', async () => { const mockAction = vi.fn() renderHook( () => useShopActionQuery(['test-skip'], mockAction, {}, {skip: true}), {wrapper} ) // Wait a bit to ensure no fetch happens await new Promise(resolve => setTimeout(resolve, 100)) expect(mockAction).not.toHaveBeenCalled() }) it('fetches when skip is false', async () => { const mockAction = vi.fn().mockResolvedValue({ ok: true, data: {data: 'skip-false-data'}, }) const {result} = renderHook( () => useShopActionQuery( ['test-noskip-query'], mockAction, {}, {skip: false} ), {wrapper} ) await waitFor(() => { expect(result.current.data).toBe('skip-false-data') }) expect(mockAction).toHaveBeenCalled() }) }) describe('API Contract', () => { it('returns expected shape', async () => { const mockAction = vi.fn().mockResolvedValue({ ok: true, data: {data: 'contract-test'}, }) const {result} = renderHook( () => useShopActionQuery(['test-contract'], mockAction, {}), {wrapper} ) await waitFor(() => { expect(result.current.loading).toBe(false) }) // Verify all expected properties exist expect(result.current).toHaveProperty('data') expect(result.current).toHaveProperty('loading') expect(result.current).toHaveProperty('error') expect(result.current).toHaveProperty('refetch') // Verify types expect(typeof result.current.loading).toBe('boolean') expect(typeof result.current.refetch).toBe('function') }) }) describe('fetchPolicy Parameter', () => { it('passes fetchPolicy to action', async () => { const mockAction = vi.fn().mockResolvedValue({ ok: true, data: {data: 'test'}, }) renderHook( () => useShopActionQuery(['test-network-only'], mockAction, { fetchPolicy: 'network-only', }), {wrapper} ) await waitFor(() => { expect(mockAction).toHaveBeenCalledWith({fetchPolicy: 'network-only'}) }) }) it('passes cache-first fetchPolicy to action', async () => { const mockAction = vi.fn().mockResolvedValue({ ok: true, data: {data: 'test'}, }) renderHook( () => useShopActionQuery(['test-cache-first'], mockAction, { fetchPolicy: 'cache-first', }), {wrapper} ) await waitFor(() => { expect(mockAction).toHaveBeenCalledWith({fetchPolicy: 'cache-first'}) }) }) }) })