import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import sdk from '@farcaster/miniapp-sdk'; import { renderHook, waitFor } from '@testing-library/react'; import { type Mock, beforeEach, describe, expect, it, vi } from 'vitest'; import { useIsInMiniApp } from './useIsInMiniApp'; vi.mock('@farcaster/miniapp-sdk', () => ({ default: { isInMiniApp: vi.fn(), }, })); const createWrapper = () => { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, }, }, }); // eslint-disable-next-line react/display-name return ({ children }: { children: React.ReactNode }) => ( {children} ); }; describe('useIsInMiniApp', () => { beforeEach(() => { vi.clearAllMocks(); }); it('should return isInMiniApp as true when in mini app context', async () => { (sdk.isInMiniApp as Mock).mockResolvedValue(true); const { result } = renderHook(() => useIsInMiniApp(), { wrapper: createWrapper(), }); await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(sdk.isInMiniApp).toHaveBeenCalled(); expect(result.current.isInMiniApp).toBe(true); }); it('should return isInMiniApp as false when not in mini app context', async () => { (sdk.isInMiniApp as Mock).mockResolvedValue(false); const { result } = renderHook(() => useIsInMiniApp(), { wrapper: createWrapper(), }); await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(sdk.isInMiniApp).toHaveBeenCalled(); expect(result.current.isInMiniApp).toBe(false); }); it('should handle errors when sdk.isInMiniApp fails', async () => { const consoleSpy = vi.spyOn(console, 'error').mockImplementation(vi.fn()); (sdk.isInMiniApp as Mock).mockRejectedValue(new Error('SDK error')); const { result } = renderHook(() => useIsInMiniApp(), { wrapper: createWrapper(), }); await waitFor(() => expect(result.current.isError).toBe(true)); expect(sdk.isInMiniApp).toHaveBeenCalled(); expect(result.current.isInMiniApp).toBeUndefined(); consoleSpy.mockRestore(); }); it('should handle mutation states correctly', async () => { (sdk.isInMiniApp as Mock).mockResolvedValue(true); const { result } = renderHook(() => useIsInMiniApp(), { wrapper: createWrapper(), }); expect(result.current.isPending).toBe(true); expect(result.current.isError).toBe(false); expect(result.current.isSuccess).toBe(false); await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(result.current.isPending).toBe(false); expect(result.current.isError).toBe(false); }); it('should return all useQuery properties', async () => { (sdk.isInMiniApp as Mock).mockResolvedValue(true); const { result } = renderHook(() => useIsInMiniApp(), { wrapper: createWrapper(), }); await waitFor(() => expect(result.current.isSuccess).toBe(true)); // Check that it returns all the expected useQuery properties expect(result.current).toHaveProperty('isInMiniApp'); expect(result.current).toHaveProperty('isPending'); expect(result.current).toHaveProperty('isError'); expect(result.current).toHaveProperty('isSuccess'); expect(result.current).toHaveProperty('error'); expect(result.current).toHaveProperty('refetch'); }); it('should use correct query key', async () => { (sdk.isInMiniApp as Mock).mockResolvedValue(true); const { result } = renderHook(() => useIsInMiniApp(), { wrapper: createWrapper(), }); await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(sdk.isInMiniApp).toHaveBeenCalledWith( expect.objectContaining({ queryKey: ['useIsInMiniApp'], signal: expect.any(AbortSignal), }), ); }); it('should handle initial loading state', () => { (sdk.isInMiniApp as Mock).mockImplementation( () => new Promise((resolve) => setTimeout(() => resolve(true), 100)), ); const { result } = renderHook(() => useIsInMiniApp(), { wrapper: createWrapper(), }); expect(result.current.isPending).toBe(true); expect(result.current.isInMiniApp).toBeUndefined(); }); });