boxons/app/store/__tests__/TimerContext.test.tsx

206 lines
5.4 KiB
TypeScript

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(),
}
}));
const mockTimerState = {
reps: 5,
workTime: 30,
restTime: 10
};
describe('TimerContext', () => {
beforeEach(() => {
jest.clearAllMocks();
// Default configuration for getState
(timerStore.getState as jest.Mock<Promise<any>>).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<Promise<any>>).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<typeof console.error>).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<Promise<void>>).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<typeof console.error>).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 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
});
});
});