/* eslint-disable */ import useLocalStorage from '../../hooks/useLocalStorage'; import { renderHook, act } from '@testing-library/react-hooks'; import { localStorageMock } from '../mock/localStorageMock'; describe(useLocalStorage, () => { beforeEach(() => { Object.defineProperty(window, 'localStorage', { value: localStorageMock, }); }); afterEach(() => { localStorage.clear(); jest.clearAllMocks(); }); it('retrieves an existing value from localStorage', () => { localStorage.setItem('foo', '"bar"'); const { result } = renderHook(() => useLocalStorage('foo')); const [state] = result.current; expect(state).toEqual('bar'); }); it('should return initialValue if localStorage empty and set that to localStorage', () => { const { result } = renderHook(() => useLocalStorage('foo', 'bar')); const [state] = result.current; expect(state).toEqual('bar'); expect(localStorage.getItem('foo')).toEqual('"bar"'); }); it('prefers existing value over initial state', () => { localStorage.setItem('foo', '"bar"'); const { result } = renderHook(() => useLocalStorage('foo', 'baz')); const [state] = result.current; expect(state).toEqual('bar'); }); it('does not clobber existing localStorage with initialState', () => { localStorage.setItem('foo', '"bar"'); const { result } = renderHook(() => useLocalStorage('foo', 'buzz')); result.current; // invoke current to make sure things are set expect(localStorage.getItem('foo')).toEqual('"bar"'); }); it('correctly updates localStorage', () => { const { result, rerender } = renderHook(() => useLocalStorage('foo', 'bar') ); const [, setFoo] = result.current; act(() => setFoo('baz')); rerender(); expect(localStorage.getItem('foo')).toEqual('"baz"'); }); it('should return undefined if no initialValue provided and localStorage empty', () => { const { result } = renderHook(() => useLocalStorage('some_key')); expect(result.current[0]).toBeUndefined(); }); it('returns and allows null setting', () => { localStorage.setItem('foo', 'null'); const { result, rerender } = renderHook(() => useLocalStorage('foo')); const [foo1, setFoo] = result.current; act(() => setFoo(null)); rerender(); const [foo2] = result.current; expect(foo1).toEqual(null); expect(foo2).toEqual(null); }); it('sets initialState if initialState is an object', () => { renderHook(() => useLocalStorage('foo', { bar: true })); expect(localStorage.getItem('foo')).toEqual('{"bar":true}'); }); it('correctly and promptly returns a new value', () => { const { result, rerender } = renderHook(() => useLocalStorage('foo', 'bar') ); const [, setFoo] = result.current; act(() => setFoo('baz')); rerender(); const [foo] = result.current; expect(foo).toEqual('baz'); }); it('parses out objects from localStorage', () => { localStorage.setItem('foo', JSON.stringify({ ok: true })); const { result } = renderHook(() => useLocalStorage<{ ok: boolean }>('foo') ); const [foo] = result.current; expect(foo!.ok).toEqual(true); }); it('safely initializes objects to localStorage', () => { const { result } = renderHook(() => useLocalStorage<{ ok: boolean }>('foo', { ok: true }) ); const [foo] = result.current; expect(foo!.ok).toEqual(true); }); it('safely sets objects to localStorage', () => { const { result, rerender } = renderHook(() => useLocalStorage<{ ok: any }>('foo', { ok: true }) ); const [, setFoo] = result.current; act(() => setFoo({ ok: 'bar' })); rerender(); const [foo] = result.current; expect(foo!.ok).toEqual('bar'); }); it('safely returns objects from updates', () => { const { result, rerender } = renderHook(() => useLocalStorage<{ ok: any }>('foo', { ok: true }) ); const [, setFoo] = result.current; act(() => setFoo({ ok: 'bar' })); rerender(); const [foo] = result.current; expect(foo).toBeInstanceOf(Object); expect(foo!.ok).toEqual('bar'); }); it('sets localStorage from the function updater', () => { const { result, rerender } = renderHook(() => useLocalStorage<{ foo: string; fizz?: string }>('foo', { foo: 'bar' }) ); const [, setFoo] = result.current; act(() => setFoo((state) => ({ ...state!, fizz: 'buzz' }))); rerender(); const [value] = result.current; expect(value!.foo).toEqual('bar'); expect(value!.fizz).toEqual('buzz'); }); /* Enforces proper eslint react-hooks/rules-of-hooks usage */ describe('eslint react-hooks/rules-of-hooks', () => { it('memoizes an object between rerenders', () => { const { result, rerender } = renderHook(() => useLocalStorage('foo', { ok: true }) ); result.current; // if localStorage isn't set then r1 and r2 will be different rerender(); const [r2] = result.current; rerender(); const [r3] = result.current; expect(r2).toBe(r3); }); it('memoizes an object immediately if localStorage is already set', () => { localStorage.setItem('foo', JSON.stringify({ ok: true })); const { result, rerender } = renderHook(() => useLocalStorage('foo', { ok: true }) ); const [r1] = result.current; // if localStorage isn't set then r1 and r2 will be different rerender(); const [r2] = result.current; expect(r1).toBe(r2); }); it('memoizes the setState function', () => { localStorage.setItem('foo', JSON.stringify({ ok: true })); const { result, rerender } = renderHook(() => useLocalStorage('foo', { ok: true }) ); const [, s1] = result.current; rerender(); const [, s2] = result.current; expect(s1).toBe(s2); }); }); describe('Options: raw', () => { it('returns a string when localStorage is a stringified object', () => { localStorage.setItem('foo', JSON.stringify({ fizz: 'buzz' })); const { result } = renderHook(() => useLocalStorage('foo', null, { raw: true }) ); const [foo] = result.current; expect(typeof foo).toBe('string'); }); }); });