import * as React from 'react'; import { render, screen, fireEvent } from '@testing-library/react'; import { renderHook } from '@testing-library/react-hooks'; import { useStore } from './useStore'; import { StoreContextProvider } from './StoreContextProvider'; import { memoryStore } from './memoryStore'; describe('useStore', () => { it('should return undefined values by default', () => { const { result } = renderHook(() => useStore('foo.bar')); expect(result.current[0]).toBeUndefined(); }); const StoreReader = ({ name, defaultValue, }: { name: string; defaultValue?: any; }) => { const [value] = useStore(name, defaultValue); return <>{value}; }; it('should return the value from the provider', () => { render( 'hello', setup: () => {}, teardown: () => {}, subscribe: () => () => {}, } as any } > ); screen.getByText('hello'); }); it('should subscribe to changes on the key on mount', () => { const unsubscribe = jest.fn(); const subscribe = jest.fn().mockImplementation(() => unsubscribe); const { unmount } = render( 'hello', setup: () => {}, teardown: () => {}, subscribe, } as any } > ); expect(subscribe).toHaveBeenCalledWith('foo.bar', expect.any(Function)); unmount(); expect(unsubscribe).toHaveBeenCalled(); }); it('should allow to set values', () => { const { result } = renderHook(() => useStore('foo.bar')); result.current[1]('hello'); expect(result.current[0]).toBe('hello'); }); it('should update all components using the same store key on update', () => { const UpdateStore = () => { const [, setValue] = useStore('foo.bar'); return ; }; render( ); screen.getByText('hello'); fireEvent.click(screen.getByText('update')); screen.getByText('world'); }); it('should not update components using other store key on update', () => { const UpdateStore = () => { const [, setValue] = useStore('other.key'); return ; }; render( ); screen.getByText('hello'); fireEvent.click(screen.getByText('update')); screen.getByText('hello'); }); it('should accept an updater function as parameter', () => { const { result } = renderHook(() => useStore('foo.bar')); result.current[1]('hello'); let innerValue; result.current[1](value => { innerValue = value; return 'world'; }); expect(innerValue).toBe('hello'); expect(result.current[0]).toBe('world'); }); it('should clear its value when the key changes', () => { const StoreConsumer = ({ storeKey }: { storeKey: string }) => { const [value, setValue] = useStore(storeKey); return ( <>

{value}

); }; const MyComponent = () => { const [storeKey, setStoreKey] = React.useState('list1'); return ( ); }; render(); expect(screen.queryByText('hello')).toBeNull(); fireEvent.click(screen.getByText('change value')); screen.getByText('hello'); fireEvent.click(screen.getByText('change key')); expect(screen.queryByText('hello')).toBeNull(); }); });