1import React, { PropsWithChildren } from 'react'; 2import { renderHook } from '@testing-library/react-hooks'; 3import { useStatelessReducer, useDispatch, DispatchContext, combineReducers } from './useStatelessReducer'; 4 5describe('useStatelessReducer Hook', () => { 6 it('When dispatch is called, it should call the provided reducer with the correct action and state', () => { 7 const action = { type: 'SOME ACTION' }; 8 const reducer = jest.fn(); 9 const state = { someProp: 'some state' }; 10 11 const { result } = renderHook(() => useStatelessReducer(() => {}, state, reducer)); 12 13 result.current(action); 14 15 expect(reducer).toHaveBeenCalledWith(state, action); 16 }); 17 18 it('When an action is dispatched, it should call the provided onChange callback with the result from the reducer', () => { 19 const action = { type: 'SOME ACTION' }; 20 const state = { propA: 'A', propB: 'B' }; 21 const expectedState = { ...state, propB: 'Changed' }; 22 const reducer = () => expectedState; 23 const onChange = jest.fn(); 24 25 const { result } = renderHook(() => useStatelessReducer(onChange, state, reducer)); 26 27 result.current(action); 28 29 expect(onChange).toHaveBeenLastCalledWith(expectedState); 30 }); 31}); 32 33describe('useDispatch Hook', () => { 34 it('Should throw when used outside of DispatchContext', () => { 35 const { result } = renderHook(() => useDispatch()); 36 37 expect(result.error).toBeTruthy(); 38 }); 39 40 it('Should return a dispatch function', () => { 41 const dispatch = jest.fn(); 42 const wrapper = ({ children }: PropsWithChildren<{}>) => ( 43 <DispatchContext.Provider value={dispatch}>{children}</DispatchContext.Provider> 44 ); 45 46 const { result } = renderHook(() => useDispatch(), { 47 wrapper, 48 }); 49 50 expect(result.current).toBe(dispatch); 51 }); 52}); 53 54describe('combineReducers', () => { 55 it('Should correctly combine reducers', () => { 56 const reducerA = jest.fn(); 57 const reducerB = jest.fn(); 58 59 const combinedReducer = combineReducers({ reducerA, reducerB }); 60 61 const action = { type: 'SOME ACTION' }; 62 const initialState = { reducerA: 'A', reducerB: 'B' }; 63 64 combinedReducer(initialState, action); 65 66 expect(reducerA).toHaveBeenCalledWith(initialState.reducerA, action); 67 expect(reducerB).toHaveBeenCalledWith(initialState.reducerB, action); 68 }); 69}); 70