import React from 'react' import { render, fireEvent, waitFor } from '@testing-library/react-native' import { View } from 'react-native' import GenerationRecordScreen from './generationRecord' jest.mock('expo-router', () => ({ useRouter: jest.fn(() => ({ back: jest.fn(), push: jest.fn(), })), })) jest.mock('react-i18next', () => ({ useTranslation: jest.fn(() => ({ t: (key: string) => key, })), })) jest.mock('expo-status-bar', () => ({ StatusBar: 'StatusBar', })) jest.mock('react-native-safe-area-context', () => ({ SafeAreaView: ({ children }: { children: React.ReactNode }) => ( {children} ), })) jest.mock('expo-image', () => ({ Image: 'Image', })) jest.mock('@/components/icon', () => ({ LeftArrowIcon: () => null, DeleteIcon: () => null, EditIcon: () => null, ChangeIcon: () => null, WhiteStarIcon: () => null, })) jest.mock('@/components/ui/delete-confirm-dialog', () => ({ DeleteConfirmDialog: () => null, })) jest.mock('@/components/LoadingState', () => ({ __esModule: true, default: ({ testID }: any) => , })) jest.mock('@/components/ErrorState', () => ({ __esModule: true, default: ({ testID }: any) => , })) jest.mock('@/components/PaginationLoader', () => ({ __esModule: true, default: ({ testID }: any) => , })) // Mock react-native RefreshControl (directly from react-native) jest.mock('react-native', () => Object.assign({}, jest.requireActual('react-native'), { RefreshControl: ({ children }: { children: React.ReactNode }) => <>{children}, }) ) jest.mock('@/hooks', () => ({ useTemplateGenerations: jest.fn(), })) import { useTemplateGenerations } from '@/hooks' const mockUseTemplateGenerations = useTemplateGenerations as jest.MockedFunction describe('GenerationRecordScreen', () => { const mockExecute = jest.fn() const mockRefetch = jest.fn() const mockLoadMore = jest.fn() beforeEach(() => { jest.clearAllMocks() }) it('shows loading state on initial load', () => { mockUseTemplateGenerations.mockReturnValue({ generations: [], loading: true, loadingMore: false, error: null, execute: mockExecute, refetch: mockRefetch, loadMore: mockLoadMore, hasMore: true, data: undefined, }) const { getByTestId } = render() expect(getByTestId('loading-state')).toBeTruthy() }) it('shows error state when error occurs', () => { mockUseTemplateGenerations.mockReturnValue({ generations: [], loading: false, loadingMore: false, error: { message: 'Failed to load' } as any, execute: mockExecute, refetch: mockRefetch, loadMore: mockLoadMore, hasMore: false, data: undefined, }) const { getByTestId } = render() expect(getByTestId('error-state')).toBeTruthy() }) it('renders generation list when data is loaded', () => { const mockGenerations = [ { id: '1', template: { title: 'Test Template' }, resultUrl: ['https://example.com/result.jpg'], originalUrl: 'https://example.com/original.jpg', }, ] mockUseTemplateGenerations.mockReturnValue({ generations: mockGenerations as any, loading: false, loadingMore: false, error: null, execute: mockExecute, refetch: mockRefetch, loadMore: mockLoadMore, hasMore: true, data: { data: mockGenerations } as any, }) const { getByText } = render() expect(getByText('Test Template')).toBeTruthy() }) it('shows pagination loader when loading more', () => { const mockGenerations = [ { id: '1', template: { title: 'Test Template' }, resultUrl: ['https://example.com/result.jpg'], }, ] mockUseTemplateGenerations.mockReturnValue({ generations: mockGenerations as any, loading: false, loadingMore: true, error: null, execute: mockExecute, refetch: mockRefetch, loadMore: mockLoadMore, hasMore: true, data: { data: mockGenerations } as any, }) const { getByTestId } = render() expect(getByTestId('pagination-loader')).toBeTruthy() }) it('calls execute on mount', () => { mockUseTemplateGenerations.mockReturnValue({ generations: [], loading: false, loadingMore: false, error: null, execute: mockExecute, refetch: mockRefetch, loadMore: mockLoadMore, hasMore: false, data: undefined, }) render() expect(mockExecute).toHaveBeenCalledWith({ page: 1, limit: 20 }) }) it('calls refetch on pull to refresh', async () => { const mockGenerations = [ { id: '1', template: { title: 'Test Template' }, resultUrl: ['https://example.com/result.jpg'], }, ] mockUseTemplateGenerations.mockReturnValue({ generations: mockGenerations as any, loading: false, loadingMore: false, error: null, execute: mockExecute, refetch: mockRefetch, loadMore: mockLoadMore, hasMore: true, data: { data: mockGenerations } as any, }) const { getByTestId } = render() const flatList = getByTestId('generation-list') fireEvent(flatList, 'refresh') await waitFor(() => { expect(mockRefetch).toHaveBeenCalledWith({ page: 1, limit: 20 }) }) }) it('calls loadMore when reaching end of list', async () => { const mockGenerations = [ { id: '1', template: { title: 'Test Template' }, resultUrl: ['https://example.com/result.jpg'], }, ] mockUseTemplateGenerations.mockReturnValue({ generations: mockGenerations as any, loading: false, loadingMore: false, error: null, execute: mockExecute, refetch: mockRefetch, loadMore: mockLoadMore, hasMore: true, data: { data: mockGenerations } as any, }) const { getByTestId } = render() const flatList = getByTestId('generation-list') fireEvent(flatList, 'endReached') await waitFor(() => { expect(mockLoadMore).toHaveBeenCalledWith({ limit: 20 }) }) }) it('does not call loadMore when hasMore is false', async () => { const mockGenerations = [ { id: '1', template: { title: 'Test Template' }, resultUrl: ['https://example.com/result.jpg'], }, ] mockUseTemplateGenerations.mockReturnValue({ generations: mockGenerations as any, loading: false, loadingMore: false, error: null, execute: mockExecute, refetch: mockRefetch, loadMore: mockLoadMore, hasMore: false, data: { data: mockGenerations } as any, }) const { getByTestId } = render() const flatList = getByTestId('generation-list') fireEvent(flatList, 'endReached') await waitFor(() => { expect(mockLoadMore).not.toHaveBeenCalled() }) }) })