import { renderHook, act, waitFor } from '@testing-library/react-native'; import { TimerProvider, useTimerContext } from '../TimerContext'; import { timerStore } from '../TimerStore'; import '@testing-library/jest-native/extend-expect'; jest.mock('../TimerStore', () => ({ timerStore: { getState: jest.fn(), saveReps: jest.fn(), saveWorkTime: jest.fn(), saveRestTime: jest.fn(), saveState: jest.fn(), savePreparationTime: jest.fn(), } })); const mockTimerState = { reps: 5, workTime: 30, restTime: 10, preparationTime: 3 }; describe('TimerContext', () => { beforeEach(() => { jest.clearAllMocks(); // Default configuration for getState (timerStore.getState as jest.Mock>).mockResolvedValue(mockTimerState); }); it('should load initial data', async () => { const { result } = renderHook(() => useTimerContext(), { wrapper: TimerProvider }); // Check initial loading state expect(result.current.isLoading).toBe(true); // Wait for loading to complete await waitFor(() => { expect(result.current.isLoading).toBe(false); }); // Verify getState was called expect(timerStore.getState).toHaveBeenCalledTimes(1); // Verify data is correctly loaded expect(result.current.timerState).toEqual(mockTimerState); }); it('should handle errors when loading data', async () => { // Simulate an error (timerStore.getState as jest.Mock>).mockRejectedValueOnce(new Error('Loading error')); // Spy on console.error jest.spyOn(console, 'error').mockImplementation(() => {}); const { result } = renderHook(() => useTimerContext(), { wrapper: TimerProvider }); // Wait for loading to complete despite error await waitFor(() => { expect(result.current.isLoading).toBe(false); }); // Verify error was logged expect(console.error).toHaveBeenCalledWith( 'Error loading data:', expect.any(Error) ); // Restore console.error (console.error as jest.MockedFunction).mockRestore(); }); it('should update repetitions', async () => { const { result } = renderHook(() => useTimerContext(), { wrapper: TimerProvider }); // Wait for initial loading to complete await waitFor(() => { expect(result.current.isLoading).toBe(false); }); // Update repetitions await act(async () => { await result.current.updateReps(10); }); // Verify saveReps was called with the correct value expect(timerStore.saveReps).toHaveBeenCalledWith(10); // Verify state was updated expect(result.current.timerState.reps).toBe(10); }); it('should handle errors when updating repetitions', async () => { // Simulate an error (timerStore.saveReps as jest.Mock>).mockRejectedValueOnce(new Error('Saving error')); // Spy on console.error jest.spyOn(console, 'error').mockImplementation(() => {}); const { result } = renderHook(() => useTimerContext(), { wrapper: TimerProvider }); // Wait for initial loading to complete await waitFor(() => { expect(result.current.isLoading).toBe(false); }); // Attempt to update repetitions await act(async () => { await result.current.updateReps(10); }); // Verify error was logged expect(console.error).toHaveBeenCalledWith( 'Error updating repetitions:', expect.any(Error) ); // Restore console.error (console.error as jest.MockedFunction).mockRestore(); }); it('should update work time', async () => { const { result } = renderHook(() => useTimerContext(), { wrapper: TimerProvider }); // Wait for initial loading to complete await waitFor(() => { expect(result.current.isLoading).toBe(false); }); // Update work time await act(async () => { await result.current.updateWorkTime(45); }); // Verify saveWorkTime was called with the correct value expect(timerStore.saveWorkTime).toHaveBeenCalledWith(45); // Verify state was updated expect(result.current.timerState.workTime).toBe(45); }); it('should update rest time', async () => { const { result } = renderHook(() => useTimerContext(), { wrapper: TimerProvider }); // Wait for initial loading to complete await waitFor(() => { expect(result.current.isLoading).toBe(false); }); // Update rest time await act(async () => { await result.current.updateRestTime(15); }); // Verify saveRestTime was called with the correct value expect(timerStore.saveRestTime).toHaveBeenCalledWith(15); // Verify state was updated expect(result.current.timerState.restTime).toBe(15); }); it('should handle errors when updating rest time', async () => { // Simulate an error (timerStore.saveRestTime as jest.Mock>).mockRejectedValueOnce(new Error('Saving error')); // Spy on console.error jest.spyOn(console, 'error').mockImplementation(() => {}); const { result } = renderHook(() => useTimerContext(), { wrapper: TimerProvider }); // Wait for initial loading to complete await waitFor(() => { expect(result.current.isLoading).toBe(false); }); // Attempt to update rest time await act(async () => { await result.current.updateRestTime(15); }); // Verify error was logged expect(console.error).toHaveBeenCalledWith( 'Error updating rest time:', expect.any(Error) ); // Restore console.error (console.error as jest.MockedFunction).mockRestore(); }); it('should handle errors when updating work time', async () => { // Simulate an error (timerStore.saveWorkTime as jest.Mock>).mockRejectedValueOnce(new Error('Saving error')); // Spy on console.error jest.spyOn(console, 'error').mockImplementation(() => {}); const { result } = renderHook(() => useTimerContext(), { wrapper: TimerProvider }); // Wait for initial loading to complete await waitFor(() => { expect(result.current.isLoading).toBe(false); }); // Attempt to update work time await act(async () => { await result.current.updateWorkTime(45); }); // Verify error was logged expect(console.error).toHaveBeenCalledWith( 'Error updating work time:', expect.any(Error) ); // Restore console.error (console.error as jest.MockedFunction).mockRestore(); }); it('should update preparation time', async () => { const { result } = renderHook(() => useTimerContext(), { wrapper: TimerProvider }); // Wait for initial loading to complete await waitFor(() => { expect(result.current.isLoading).toBe(false); }); // Update preparation time await act(async () => { await result.current.updatePreparationTime(5); }); // Verify savePreparationTime was called with the correct value expect(timerStore.savePreparationTime).toHaveBeenCalledWith(5); // Verify state was updated expect(result.current.timerState.preparationTime).toBe(5); }); it('should handle errors when updating preparation time', async () => { // Simulate an error (timerStore.savePreparationTime as jest.Mock>).mockRejectedValueOnce(new Error('Saving error')); // Spy on console.error jest.spyOn(console, 'error').mockImplementation(() => {}); const { result } = renderHook(() => useTimerContext(), { wrapper: TimerProvider }); // Wait for initial loading to complete await waitFor(() => { expect(result.current.isLoading).toBe(false); }); // Attempt to update preparation time await act(async () => { await result.current.updatePreparationTime(5); }); // Verify error was logged expect(console.error).toHaveBeenCalledWith( 'Error updating preparation time:', expect.any(Error) ); // Restore console.error (console.error as jest.MockedFunction).mockRestore(); }); it('should handle errors when updating multiple values at once', async () => { // Simulate an error (timerStore.saveState as jest.Mock>).mockRejectedValueOnce(new Error('Saving error')); // Spy on console.error jest.spyOn(console, 'error').mockImplementation(() => {}); const { result } = renderHook(() => useTimerContext(), { wrapper: TimerProvider }); // Wait for initial loading to complete await waitFor(() => { expect(result.current.isLoading).toBe(false); }); const newState = { reps: 8, workTime: 60, restTime: 20 }; // Attempt to update complete state await act(async () => { await result.current.updateState(newState); }); // Verify error was logged expect(console.error).toHaveBeenCalledWith( 'Error updating state:', expect.any(Error) ); // Restore console.error (console.error as jest.MockedFunction).mockRestore(); }); it('should update multiple values at once', async () => { const { result } = renderHook(() => useTimerContext(), { wrapper: TimerProvider }); // Wait for initial loading to complete await waitFor(() => { expect(result.current.isLoading).toBe(false); }); const newState = { reps: 8, workTime: 60, restTime: 20 }; // Update complete state await act(async () => { await result.current.updateState(newState); }); // Verify saveState was called with the correct state expect(timerStore.saveState).toHaveBeenCalledWith({ ...mockTimerState, ...newState }); // Verify state was updated expect(result.current.timerState).toEqual({ ...mockTimerState, ...newState }); }); });