import React, { useContext } from 'react'; import { atom, useRecoilState, useRecoilValue } from 'recoil'; import { act, renderRecoilHook } from './react-recoil-hooks-testing-library'; const atomA = atom({ key: 'setMockRecoilState__a', default: 0, }); const atomB = atom({ key: 'setMockRecoilState__b', default: 'test', }); const useRecoilTestHook = (initialProps: string) => { const [valueA, setValueA] = useRecoilState(atomA); const [valueB, setValueB] = useRecoilState(atomB); const update = () => { setValueA(123); setValueB('Wow!'); }; return { update, valueA, valueB, initialProps }; }; describe('react-recoil-hooks-testing-library', () => { it('reads default values and updates values', () => { const { result } = renderRecoilHook(useRecoilTestHook); expect(result.current.valueA).toBe(0); expect(result.current.valueB).toBe('test'); act(() => { result.current.update(); }); expect(result.current.valueA).toBe(123); expect(result.current.valueB).toBe('Wow!'); }); it('gets state set from options', () => { const { result } = renderRecoilHook(useRecoilTestHook, { states: [ { recoilState: atomA, initialValue: 42 }, { recoilState: atomB, initialValue: 'Calculated' }, ], }); expect(result.current.valueA).toBe(42); expect(result.current.valueB).toBe('Calculated'); act(() => { result.current.update(); }); expect(result.current.valueA).toBe(123); expect(result.current.valueB).toBe('Wow!'); }); it('sets initialProps', () => { const { result } = renderRecoilHook(useRecoilTestHook, { initialProps: 'initialProps', }); expect(result.current.initialProps).toBe('initialProps'); }); it('sets wrapper', () => { const MockContext = React.createContext(''); const useRecoilTestHookWithContext = () => { const valueA = useRecoilValue(atomA); const contextValue = useContext(MockContext); return { valueA, contextValue }; }; const { result } = renderRecoilHook(useRecoilTestHookWithContext, { wrapper: ({ children }) => ( <MockContext.Provider value="context!">{children}</MockContext.Provider> ), states: [{ recoilState: atomA, initialValue: 9 }], }); expect(result.current.contextValue).toBe('context!'); expect(result.current.valueA).toBe(9); }); it('sets initialProps with wrapper', () => { const MockContext = React.createContext(''); const useRecoilTestHookWithContext = () => { const valueA = useRecoilValue(atomA); const contextValue = useContext(MockContext); return { valueA, contextValue }; }; const WrapperWithProviderValue: React.FC<{ providerValue: string; }> = ({ children, providerValue }) => ( <MockContext.Provider value={providerValue}> {children} </MockContext.Provider> ); const { result } = renderRecoilHook(useRecoilTestHookWithContext, { wrapper: WrapperWithProviderValue, states: [{ recoilState: atomA, initialValue: 123 }], initialProps: { providerValue: 'context!', }, }); expect(result.current.contextValue).toBe('context!'); expect(result.current.valueA).toBe(123); }); it('updates wrapper props on rerender', () => { const MockContext = React.createContext(''); const useRecoilTestHookWithContext = () => { const valueA = useRecoilValue(atomA); const contextValue = useContext(MockContext); return { valueA, contextValue }; }; const WrapperWithProviderValue: React.FC<{ providerValue: string; }> = ({ children, providerValue }) => ( <MockContext.Provider value={providerValue}> {children} </MockContext.Provider> ); const { result, rerender } = renderRecoilHook( useRecoilTestHookWithContext, { wrapper: WrapperWithProviderValue, states: [{ recoilState: atomA, initialValue: 123 }], initialProps: { providerValue: 'context 1', }, }, ); expect(result.current.contextValue).toBe('context 1'); expect(result.current.valueA).toBe(123); rerender({ providerValue: 'context 2', }); expect(result.current.contextValue).toBe('context 2'); expect(result.current.valueA).toBe(123); }); });