import { renderHook, act } from '@testing-library/react-native' import { useRerunGeneration } from './use-rerun-generation' import { root } from '@repo/core' import { TemplateController } from '@repo/sdk' jest.mock('@repo/core', () => ({ root: { get: jest.fn(), }, })) jest.mock('./use-error', () => ({ handleError: jest.fn(async (cb) => { try { const data = await cb() return { data, error: null } } catch (e) { return { data: null, error: e } } }), })) describe('useRerunGeneration', () => { beforeEach(() => { jest.clearAllMocks() }) afterEach(() => { jest.restoreAllMocks() }) describe('initial state', () => { it('should return initial state', () => { const { result } = renderHook(() => useRerunGeneration()) expect(result.current.loading).toBe(false) expect(result.current.error).toBeNull() expect(typeof result.current.rerun).toBe('function') }) }) describe('rerun function', () => { it('should rerun generation successfully', async () => { const mockData = { generationId: 'new-gen-456' } const mockController = { rerun: jest.fn().mockResolvedValue(mockData), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useRerunGeneration()) let response await act(async () => { response = await result.current.rerun('old-gen-123') }) expect(root.get).toHaveBeenCalledWith(TemplateController) expect(mockController.rerun).toHaveBeenCalledWith({ generationId: 'old-gen-123', }) expect(response).toEqual({ generationId: 'new-gen-456' }) expect(result.current.error).toBeNull() }) it('should handle API errors', async () => { const mockError = { status: 500, statusText: 'Internal Server Error', message: 'Failed to rerun generation', } const mockController = { rerun: jest.fn().mockRejectedValue(mockError), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useRerunGeneration()) let response await act(async () => { response = await result.current.rerun('gen-123') }) expect(result.current.error).toEqual(mockError) expect(response).toEqual({ error: mockError }) }) it('should handle network errors', async () => { const mockError = { message: 'Network error', } const mockController = { rerun: jest.fn().mockRejectedValue(mockError), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useRerunGeneration()) let response await act(async () => { response = await result.current.rerun('gen-123') }) expect(result.current.error).toEqual(mockError) expect(response).toEqual({ error: mockError }) }) }) describe('loading state', () => { it('should set loading to true during execution', async () => { let resolveFetch: (value: any) => void const fetchPromise = new Promise((resolve) => { resolveFetch = resolve }) const mockController = { rerun: jest.fn().mockReturnValue(fetchPromise), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useRerunGeneration()) act(() => { result.current.rerun('gen-123') }) expect(result.current.loading).toBe(true) await act(async () => { resolveFetch!({ generationId: 'new-gen-456' }) await fetchPromise }) expect(result.current.loading).toBe(false) }) it('should set loading to false after error', async () => { const mockError = { status: 500, message: 'Error' } const mockController = { rerun: jest.fn().mockRejectedValue(mockError), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useRerunGeneration()) await act(async () => { await result.current.rerun('gen-123') }) expect(result.current.loading).toBe(false) }) }) describe('error handling', () => { it('should clear error on successful rerun', async () => { const mockError = { status: 500, message: 'Error' } const mockData = { generationId: 'new-gen-456' } const mockController = { rerun: jest.fn() .mockRejectedValueOnce(mockError) .mockResolvedValueOnce(mockData), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useRerunGeneration()) await act(async () => { await result.current.rerun('gen-123') }) expect(result.current.error).toEqual(mockError) await act(async () => { await result.current.rerun('gen-456') }) expect(result.current.error).toBeNull() }) it('should update error on consecutive failures', async () => { const mockError1 = { status: 500, message: 'First error' } const mockError2 = { status: 404, message: 'Second error' } const mockController = { rerun: jest.fn() .mockRejectedValueOnce(mockError1) .mockRejectedValueOnce(mockError2), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useRerunGeneration()) await act(async () => { await result.current.rerun('gen-123') }) expect(result.current.error).toEqual(mockError1) await act(async () => { await result.current.rerun('gen-456') }) expect(result.current.error).toEqual(mockError2) }) }) describe('multiple calls', () => { it('should handle multiple sequential calls', async () => { const mockController = { rerun: jest.fn() .mockResolvedValueOnce({ generationId: 'new-gen-1' }) .mockResolvedValueOnce({ generationId: 'new-gen-2' }), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useRerunGeneration()) let response1 await act(async () => { response1 = await result.current.rerun('gen-1') }) expect(response1).toEqual({ generationId: 'new-gen-1' }) let response2 await act(async () => { response2 = await result.current.rerun('gen-2') }) expect(response2).toEqual({ generationId: 'new-gen-2' }) expect(mockController.rerun).toHaveBeenCalledTimes(2) }) }) })