import { renderHook, act } from '@testing-library/react-native' import { useGenerationDetail } from './use-generation-detail' import { root } from '@repo/core' import { TemplateGenerationController } 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('useGenerationDetail', () => { beforeEach(() => { jest.clearAllMocks() }) afterEach(() => { jest.restoreAllMocks() }) describe('initial state', () => { it('should return initial state with no data', () => { const { result } = renderHook(() => useGenerationDetail()) expect(result.current.data).toBeNull() expect(result.current.loading).toBe(false) expect(result.current.error).toBeNull() }) }) describe('execute function', () => { it('should load generation detail successfully', async () => { const mockData = { id: 'generation-1', userId: 'user-1', templateId: 'template-1', type: 'IMAGE', resultUrl: ['https://example.com/result.png'], originalUrl: null, status: 'COMPLETED', creditsCost: 10, data: null, webpPreviewUrl: 'https://example.com/preview.webp', webpHighPreviewUrl: 'https://example.com/preview-high.webp', createdAt: new Date(), updatedAt: new Date(), template: { id: 'template-1', title: 'Test Template', titleEn: 'Test Template', coverImageUrl: 'https://example.com/cover.png', }, } const mockController = { get: jest.fn().mockResolvedValue(mockData), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useGenerationDetail()) await act(async () => { await result.current.execute({ id: 'generation-1' }) }) expect(mockController.get).toHaveBeenCalledWith('generation-1') expect(result.current.data).toEqual(mockData) expect(result.current.error).toBeNull() }) it('should handle API errors', async () => { const mockError = { status: 404, statusText: 'Not Found', message: 'Generation not found', } const mockController = { get: jest.fn().mockRejectedValue(mockError), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useGenerationDetail()) await act(async () => { await result.current.execute({ id: 'invalid-id' }) }) expect(result.current.error).toEqual(mockError) expect(result.current.data).toBeNull() }) it('should return error in response when API fails', async () => { const mockError = { status: 500, statusText: 'Internal Server Error', message: 'Server error', } const mockController = { get: jest.fn().mockRejectedValue(mockError), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useGenerationDetail()) let response await act(async () => { response = await result.current.execute({ id: 'generation-1' }) }) expect(response).toEqual({ data: null, error: mockError }) }) it('should return data in response when API succeeds', async () => { const mockData = { id: 'generation-1', userId: 'user-1', templateId: 'template-1', type: 'IMAGE', resultUrl: ['https://example.com/result.png'], status: 'COMPLETED', } const mockController = { get: jest.fn().mockResolvedValue(mockData), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useGenerationDetail()) let response await act(async () => { response = await result.current.execute({ id: 'generation-1' }) }) expect(response).toEqual({ data: mockData, error: null }) }) }) describe('loading state', () => { it('should set loading to true during fetch', async () => { let resolveFetch: (value: any) => void const fetchPromise = new Promise((resolve) => { resolveFetch = resolve }) const mockController = { get: jest.fn().mockReturnValue(fetchPromise), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useGenerationDetail()) act(() => { result.current.execute({ id: 'generation-1' }) }) expect(result.current.loading).toBe(true) await act(async () => { resolveFetch!({ id: 'generation-1', status: 'COMPLETED' }) await fetchPromise }) expect(result.current.loading).toBe(false) }) it('should set loading to false after error', async () => { const mockError = { status: 500, statusText: 'Error', message: 'Error' } const mockController = { get: jest.fn().mockRejectedValue(mockError), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useGenerationDetail()) await act(async () => { await result.current.execute({ id: 'generation-1' }) }) expect(result.current.loading).toBe(false) }) }) describe('refetch function', () => { it('should reload generation data', async () => { const initialData = { id: 'generation-1', status: 'PROCESSING', } const refreshedData = { id: 'generation-1', status: 'COMPLETED', } const mockController = { get: jest.fn() .mockResolvedValueOnce(initialData) .mockResolvedValueOnce(refreshedData), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useGenerationDetail()) await act(async () => { await result.current.execute({ id: 'generation-1' }) }) expect(result.current.data).toEqual(initialData) await act(async () => { await result.current.refetch({ id: 'generation-1' }) }) expect(result.current.data).toEqual(refreshedData) expect(mockController.get).toHaveBeenCalledTimes(2) }) it('should call execute with same params', async () => { const mockData = { id: 'generation-1', status: 'COMPLETED' } const mockController = { get: jest.fn().mockResolvedValue(mockData), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useGenerationDetail()) await act(async () => { await result.current.refetch({ id: 'generation-1' }) }) expect(mockController.get).toHaveBeenCalledWith('generation-1') }) }) describe('error handling', () => { it('should clear error on successful execute', async () => { const mockError = { status: 500, statusText: 'Error', message: 'Error' } const mockData = { id: 'generation-1', status: 'COMPLETED' } const mockController = { get: jest.fn() .mockRejectedValueOnce(mockError) .mockResolvedValueOnce(mockData), } ;(root.get as jest.Mock).mockReturnValue(mockController) const { result } = renderHook(() => useGenerationDetail()) await act(async () => { await result.current.execute({ id: 'generation-1' }) }) expect(result.current.error).toEqual(mockError) await act(async () => { await result.current.execute({ id: 'generation-1' }) }) expect(result.current.error).toBeNull() }) }) })