Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
chore(useUpdate): improve useUpdate test suite
  • Loading branch information
xobotyi committed Jan 31, 2021
commit 0636cd87f47bf8b9a16ef4461a3d47a526e7f10d
1 change: 1 addition & 0 deletions src/misc/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export function off<T extends Window | Document | HTMLElement | EventTarget>(
}

export const isBrowser = typeof window !== 'undefined';

export const isNavigator = typeof navigator !== 'undefined';
7 changes: 3 additions & 4 deletions src/useUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import { useReducer } from 'react';

const updateReducer = (num: number): number => (num + 1) % 1_000_000;

const useUpdate = () => {
export default function useUpdate(): () => void {
const [, update] = useReducer(updateReducer, 0);
return update as () => void;
};

export default useUpdate;
return update;
}
81 changes: 58 additions & 23 deletions tests/useUpdate.test.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,70 @@
import { act, renderHook } from '@testing-library/react-hooks';
import useUpdate from '../src/useUpdate';

it('should init update function', () => {
const { result } = renderHook(() => useUpdate());
const update = result.current;
describe('useUpdate', () => {
it('should be defined', () => {
expect(useUpdate).toBeDefined();
});

expect(update).toBeInstanceOf(Function);
});
it('should return a function', () => {
const { result } = renderHook(() => useUpdate());

it('should forces a re-render every time update function is called', () => {
let renderCount = 0;
const { result } = renderHook(() => {
renderCount++;
return useUpdate();
});
const update = result.current;
expect(typeof result.current).toBe('function');
})

expect(renderCount).toBe(1);
it('should re-render component each time returned function is called', () => {
let renders = 0;
const { result: { current: update } } = renderHook(() => {
renders++;
return useUpdate();
});

act(() => update());
expect(renderCount).toBe(2);
expect(renders).toBe(1);

act(() => update());
expect(renderCount).toBe(3);
});
act(() => update());
expect(renders).toBe(2);

act(() => update());
expect(renders).toBe(3);
})

it('should return exact same function in between renders', () => {
let renders = 0;
const { result } = renderHook(() => {
renders++;
return useUpdate();
});
let initialUpdateFn = result.current;

expect(renders).toBe(1);

act(() => result.current());
expect(renders).toBe(2);
expect(initialUpdateFn).toBe(result.current);

act(() => result.current());
expect(renders).toBe(3);
expect(initialUpdateFn).toBe(result.current);
})

it('passing the argument to returned function should not affect the use', () => {
let renders = 0;
const { result } = renderHook(() => {
renders++;
return useUpdate();
});
let initialUpdateFn = result.current;

it('should return same update function instance on each update', () => {
const { result, rerender } = renderHook(() => useUpdate());
const { current: updateCb } = result;
expect(renders).toBe(1);

rerender();
/* @ts-expect-error */
act(() => result.current(1));
expect(renders).toBe(2);
expect(initialUpdateFn).toBe(result.current);

expect(Object.is(result.current, updateCb)).toBe(true);
/* @ts-expect-error */
act(() => result.current(1));
expect(renders).toBe(3);
expect(initialUpdateFn).toBe(result.current);
})
});