import React from 'react'; import { render, fireEvent } from '@testing-library/react'; import { act, renderHook } from '@testing-library/react-hooks'; import createStateContext from '../src/factory/createStateContext'; it('should create a hook and a provider', () => { const [useSharedNumber, SharedNumberProvider] = createStateContext(0); expect(useSharedNumber).toBeInstanceOf(Function); expect(SharedNumberProvider).toBeInstanceOf(Function); }); describe('when using created hook', () => { it('should throw out of a provider', () => { const [useSharedText] = createStateContext('init'); const { result } = renderHook(() => useSharedText()); expect(result.error).toEqual(new Error('useStateContext must be used inside a StateProvider.')); }); const setUp = () => { const [useSharedText, SharedTextProvider] = createStateContext('init'); const wrapper: React.FC = ({ children }) => {children}; return renderHook(() => useSharedText(), { wrapper }); }; it('should init state and updater', () => { const { result } = setUp(); const [sharedText, setSharedText] = result.current; expect(sharedText).toEqual('init'); expect(setSharedText).toBeInstanceOf(Function); }); it('should update the state', () => { const { result } = setUp(); const [, setSharedText] = result.current; act(() => setSharedText('changed')); const [sharedText] = result.current; expect(sharedText).toEqual('changed'); }); }); describe('when using among multiple components', () => { const [useSharedText, SharedTextProvider] = createStateContext('init'); const DisplayComponent = () => { const [sharedText] = useSharedText(); return

{sharedText}

; }; const UpdateComponent = () => { const [, setSharedText] = useSharedText(); return ( ); }; it('should be in sync when under the same provider', () => { const { baseElement, getByText } = render( ); expect(baseElement.innerHTML).toBe( '

init

init

' ); fireEvent.click(getByText('UPDATE')); expect(baseElement.innerHTML).toBe( '

changed

changed

' ); }); it('should be in update independently when under different providers', () => { const { baseElement, getByText } = render( <> ); expect(baseElement.innerHTML).toBe( '

init

init

' ); fireEvent.click(getByText('UPDATE')); expect(baseElement.innerHTML).toBe( '

init

changed

' ); }); it('should not update component that do not use the state context', () => { let renderCount = 0; const StaticComponent = () => { renderCount++; return

static

; }; const { baseElement, getByText } = render( <> ); expect(baseElement.innerHTML).toBe( '

static

init

' ); fireEvent.click(getByText('UPDATE')); expect(baseElement.innerHTML).toBe( '

static

changed

' ); expect(renderCount).toBe(1); }); it('should override initialValue', () => { const { baseElement } = render( <> ); expect(baseElement.innerHTML).toBe('

init

other

'); }); });