mirror of
https://github.com/streamich/react-use.git
synced 2025-12-08 18:02:14 +00:00
chore: move all the tests to the separate directory outside of sources; chore: remove jest.config.js (config moved to the package.json); test: unused import in test; test: 💍 fix tests add back x and y to useMeasure chore: 🤖 add linter to /tests folder ci: 🎡 limit Jest worker count for CircleCI
374 lines
11 KiB
TypeScript
374 lines
11 KiB
TypeScript
import { act, renderHook } from '@testing-library/react-hooks';
|
|
import { useRef } from 'react';
|
|
import useList, { ListActions } from '../src/useList';
|
|
|
|
describe('useList', () => {
|
|
it('should be defined', () => {
|
|
expect(useList).toBeDefined();
|
|
});
|
|
|
|
function getHook<T>(initialArray?: T[]) {
|
|
return renderHook(
|
|
(props): [number, [T[], ListActions<T>]] => {
|
|
const counter = useRef(0);
|
|
|
|
return [++counter.current, useList(props)];
|
|
},
|
|
{ initialProps: initialArray }
|
|
);
|
|
}
|
|
|
|
it('should init with 1st parameter and actions', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [list, actions]] = hook.result.current;
|
|
|
|
expect(list).toEqual([1, 2, 3]);
|
|
expect(actions).toStrictEqual({
|
|
set: expect.any(Function),
|
|
push: expect.any(Function),
|
|
updateAt: expect.any(Function),
|
|
insertAt: expect.any(Function),
|
|
update: expect.any(Function),
|
|
updateFirst: expect.any(Function),
|
|
upsert: expect.any(Function),
|
|
sort: expect.any(Function),
|
|
filter: expect.any(Function),
|
|
removeAt: expect.any(Function),
|
|
remove: expect.any(Function),
|
|
clear: expect.any(Function),
|
|
reset: expect.any(Function),
|
|
});
|
|
});
|
|
|
|
it('should return the same actions object each render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, actions]] = hook.result.current;
|
|
|
|
act(() => {
|
|
actions.set([1, 2, 3, 4]);
|
|
});
|
|
|
|
expect(actions).toBe(hook.result.current[1][1]);
|
|
});
|
|
|
|
it('should default with empty array', () => {
|
|
expect(getHook().result.current[1][0]).toEqual([]);
|
|
});
|
|
|
|
describe('set()', () => {
|
|
it('should reset list with given array and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { set }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
set([1, 2, 3, 4]);
|
|
});
|
|
expect(hook.result.current[1][0]).toEqual([1, 2, 3, 4]);
|
|
expect(hook.result.current[0]).toBe(2);
|
|
|
|
act(() => {
|
|
set([1, 2, 3, 4, 5]);
|
|
});
|
|
expect(hook.result.current[1][0]).toEqual([1, 2, 3, 4, 5]);
|
|
expect(hook.result.current[0]).toBe(3);
|
|
});
|
|
});
|
|
|
|
describe('push()', () => {
|
|
it('should add arbitrary amount of items to the end and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { push }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
push(1, 2, 3, 4);
|
|
});
|
|
expect(hook.result.current[1][0]).toEqual([1, 2, 3, 1, 2, 3, 4]);
|
|
expect(hook.result.current[0]).toBe(2);
|
|
});
|
|
|
|
it('should not do anything if called with no parameters', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [list, { push }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
push();
|
|
});
|
|
expect(hook.result.current[0]).toBe(1);
|
|
expect(list).toBe(hook.result.current[1][0]);
|
|
});
|
|
});
|
|
|
|
describe('updateAt()', () => {
|
|
it('should replace item at given index with given value and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { updateAt }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
updateAt(1, 5);
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([1, 5, 3]);
|
|
});
|
|
|
|
it('should work fine if target index is out of array length', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { updateAt }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
updateAt(5, 6);
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([1, 2, 3, undefined, undefined, 6]);
|
|
});
|
|
});
|
|
|
|
describe('insertAt()', () => {
|
|
it('should insert item at given index shifting all the right elements and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { insertAt }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
insertAt(1, 5);
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([1, 5, 2, 3]);
|
|
});
|
|
|
|
it('should work if index is out of array length', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { insertAt }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
insertAt(5, 6);
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([1, 2, 3, undefined, undefined, 6]);
|
|
});
|
|
});
|
|
|
|
describe('update()', () => {
|
|
it('should replace all items that matches the predicate and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { update }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
update((a, _) => a % 2 === 1, 0);
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([0, 2, 0]);
|
|
});
|
|
|
|
it('should pass two parameters to the predicate, iterated element and new one', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { update }]] = hook.result.current;
|
|
const spy = jest.fn();
|
|
|
|
act(() => {
|
|
update(spy, 0);
|
|
});
|
|
|
|
expect(spy.mock.calls[0][0]).toBe(1);
|
|
expect(spy.mock.calls[0][1]).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe('updateFirst()', () => {
|
|
it('should replace first items that matches the predicate and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { updateFirst }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
updateFirst((a, _) => a % 2 === 1, 0);
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([0, 2, 3]);
|
|
});
|
|
|
|
it('should pass two parameters to the predicate, iterated element and new one', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { updateFirst }]] = hook.result.current;
|
|
const spy = jest.fn();
|
|
|
|
act(() => {
|
|
updateFirst(spy, 0);
|
|
});
|
|
|
|
expect(spy.mock.calls[0].length).toBe(2);
|
|
expect(spy.mock.calls[0][0]).toBe(1);
|
|
expect(spy.mock.calls[0][1]).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe('upsert()', () => {
|
|
it('should replace first item that matches the predicate and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { upsert }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
upsert((a, _) => a === 1, 0);
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([0, 2, 3]);
|
|
});
|
|
|
|
it('otherwise should push it to the list and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { upsert }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
upsert((a, _) => a === 5, 0);
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([1, 2, 3, 0]);
|
|
});
|
|
|
|
it('should pass two parameters to the predicate, iterated element and new one', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { upsert }]] = hook.result.current;
|
|
const spy = jest.fn();
|
|
|
|
act(() => {
|
|
upsert(spy, 0);
|
|
});
|
|
|
|
expect(spy.mock.calls[0].length).toBe(2);
|
|
expect(spy.mock.calls[0][0]).toBe(1);
|
|
expect(spy.mock.calls[0][1]).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe('sort()', () => {
|
|
it('should sort the list with given comparator and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { sort }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
sort((a, b) => (a === b ? 0 : a < b ? 1 : -1));
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([3, 2, 1]);
|
|
});
|
|
|
|
it('should use default array`s sorting function of called without parameters', () => {
|
|
const hook = getHook([2, 3, 1]);
|
|
const [, [, { sort }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
sort();
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([1, 2, 3]);
|
|
});
|
|
});
|
|
|
|
describe('filter()', () => {
|
|
it('should filter the list with given predicate and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { filter }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
filter(val => val % 2 === 1);
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([1, 3]);
|
|
});
|
|
|
|
it('should pass three parameters to the predicate, iterated element, it`s index and filtered array', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [list, { filter }]] = hook.result.current;
|
|
const spy = jest.fn((_, _2, _3) => false);
|
|
|
|
act(() => {
|
|
filter(spy);
|
|
});
|
|
|
|
expect(spy.mock.calls[0].length).toBe(3);
|
|
expect(spy.mock.calls[0][0]).toBe(1);
|
|
expect(spy.mock.calls[0][1]).toBe(0);
|
|
expect(spy.mock.calls[0][2]).toEqual(list);
|
|
});
|
|
});
|
|
|
|
describe('removeAt()', () => {
|
|
it('should remove item at given index and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { removeAt }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
removeAt(1);
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([1, 3]);
|
|
});
|
|
|
|
it('should do nothing if index is out of array length, although it should cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { removeAt }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
removeAt(5);
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([1, 2, 3]);
|
|
});
|
|
});
|
|
|
|
describe('remove()', () => {
|
|
it('should be a ref to removeAt', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { remove, removeAt }]] = hook.result.current;
|
|
|
|
expect(remove).toBe(removeAt);
|
|
});
|
|
});
|
|
|
|
describe('clear()', () => {
|
|
it('should clear the list and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { clear }]] = hook.result.current;
|
|
|
|
expect(hook.result.current[0]).toBe(1);
|
|
act(() => {
|
|
clear();
|
|
});
|
|
expect(hook.result.current[0]).toBe(2);
|
|
expect(hook.result.current[1][0]).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('reset()', () => {
|
|
it('should reset list to initial values and cause re-render', () => {
|
|
const hook = getHook([1, 2, 3]);
|
|
const [, [, { set, reset }]] = hook.result.current;
|
|
|
|
act(() => {
|
|
set([1, 2, 3, 4, 6, 7, 8]);
|
|
});
|
|
expect(hook.result.current[1][0]).toEqual([1, 2, 3, 4, 6, 7, 8]);
|
|
|
|
expect(hook.result.current[0]).toBe(2);
|
|
act(() => {
|
|
reset();
|
|
});
|
|
expect(hook.result.current[0]).toBe(3);
|
|
expect(hook.result.current[1][0]).toEqual([1, 2, 3]);
|
|
});
|
|
});
|
|
});
|