From 7d080bac67903a5d5b45f15016de20d34deb3482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Beltra=CC=81n=20Alarco=CC=81n?= Date: Mon, 22 Jul 2019 00:17:25 +0200 Subject: [PATCH] Add useGetSetState tests --- src/__tests__/useGetSet.test.ts | 16 ++-- src/__tests__/useGetSetState.test.ts | 127 +++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 8 deletions(-) create mode 100644 src/__tests__/useGetSetState.test.ts diff --git a/src/__tests__/useGetSet.test.ts b/src/__tests__/useGetSet.test.ts index f0925d01..9e838f95 100644 --- a/src/__tests__/useGetSet.test.ts +++ b/src/__tests__/useGetSet.test.ts @@ -16,23 +16,23 @@ describe('useGetSet hook', () => { expect(set).toBeInstanceOf(Function); }); - it('should get current state', () => { + it('should get current value', () => { const { result } = setUp('foo'); const [get] = result.current; - const currentState = get(); + const currentValue = get(); - expect(currentState).toBe('foo'); + expect(currentValue).toBe('foo'); }); - it('should set new state', () => { + it('should set new value', () => { const { result } = setUp('foo'); const [get, set] = result.current; act(() => set('bar')); - const currentState = get(); - expect(currentState).toBe('bar'); + const currentValue = get(); + expect(currentValue).toBe('bar'); }); /** @@ -59,8 +59,8 @@ describe('useGetSet hook', () => { jest.runAllTimers(); }); - const currentState = get(); - expect(currentState).toBe(3); + const currentValue = get(); + expect(currentValue).toBe(3); expect(onClick).toHaveBeenCalledTimes(3); }); }); diff --git a/src/__tests__/useGetSetState.test.ts b/src/__tests__/useGetSetState.test.ts new file mode 100644 index 00000000..f3ea5fa7 --- /dev/null +++ b/src/__tests__/useGetSetState.test.ts @@ -0,0 +1,127 @@ +import { act, renderHook } from '@testing-library/react-hooks'; +import useGetSetState from '../useGetSetState'; + +const originalConsoleError = console.error; +const mockConsoleError = jest.fn(); + +describe('useGetSetState hook', () => { + const setUp = (initialState: any) => renderHook(() => useGetSetState(initialState)); + + beforeAll(() => { + console.error = mockConsoleError; + }); + + afterAll(() => { + console.error = originalConsoleError; + }); + + beforeEach(() => { + jest.useFakeTimers(); + }); + + it('should init getter and setter', () => { + const { result } = setUp({ foo: 'initialValue' }); + const [get, set] = result.current; + + expect(get).toBeInstanceOf(Function); + expect(set).toBeInstanceOf(Function); + }); + + it('should log an error if init with something different than an object', () => { + expect(mockConsoleError).not.toHaveBeenCalled(); + + setUp('not an object'); + + expect(mockConsoleError).toHaveBeenCalledTimes(1); + expect(mockConsoleError).toHaveBeenCalledWith('useGetSetState initial state must be an object.'); + }); + + it('should get current state', () => { + const { result } = setUp({ foo: 'a', bar: 'z' }); + const [get] = result.current; + + const currentState = get(); + + expect(currentState).toEqual({ foo: 'a', bar: 'z' }); + }); + + it('should set new state by applying partial patch with existing keys', () => { + const { result } = setUp({ foo: 'a', bar: 'z' }); + const [get, set] = result.current; + + act(() => set({ bar: 'y' })); + + const currentState = get(); + expect(currentState).toEqual({ foo: 'a', bar: 'y' }); + }); + + it('should set new state by applying partial patch with new keys', () => { + const { result } = setUp({ foo: 'a', bar: 'z' }); + const [get, set] = result.current; + + act(() => set({ qux: 'f' })); + + const currentState = get(); + expect(currentState).toEqual({ foo: 'a', bar: 'z', qux: 'f' }); + }); + + it('should set new state by applying partial patch with both new and old keys', () => { + const { result } = setUp({ foo: 'a', bar: 'z' }); + const [get, set] = result.current; + + act(() => set({ bar: 'y', qux: 'f' })); + + const currentState = get(); + expect(currentState).toEqual({ foo: 'a', bar: 'y', qux: 'f' }); + }); + + it('should NOT set new state if empty partial patch received', () => { + const { result } = setUp({ foo: 'a', bar: 'z' }); + const [get, set] = result.current; + + act(() => set({})); + + const currentState = get(); + expect(currentState).toEqual({ foo: 'a', bar: 'z' }); + }); + + it('should log an error if set with a patch different than an object', () => { + const { result } = setUp({ foo: 'a', bar: 'z' }); + const [, set] = result.current; + expect(mockConsoleError).not.toHaveBeenCalled(); + + // @ts-ignore + act(() => set('not an object')); + + expect(mockConsoleError).toHaveBeenCalledTimes(1); + expect(mockConsoleError).toHaveBeenCalledWith('useGetSetState setter patch must be an object.'); + }); + + /** + * This test is equivalent to demo one for `useGetSet` hook. + */ + it('should get and set expected state when used in nested functions', () => { + const onClick = jest.fn(() => { + setTimeout(() => { + set({ counter: get().counter + 1 }); + }, 1000); + }); + + const { result } = setUp({ counter: 0 }); + const [get, set] = result.current; + + // simulate 3 clicks + onClick(); + onClick(); + onClick(); + + // fast-forward until all timers have been executed + act(() => { + jest.runAllTimers(); + }); + + const currentState = get(); + expect(currentState).toEqual({ counter: 3 }); + expect(onClick).toHaveBeenCalledTimes(3); + }); +});