mirror of
https://github.com/streamich/react-use.git
synced 2025-12-08 18:02:14 +00:00
131 lines
4.0 KiB
TypeScript
131 lines
4.0 KiB
TypeScript
import { act, renderHook, RenderHookResult } from '@testing-library/react-hooks';
|
|
import { useState } from 'react';
|
|
import { MultiStateValidator, useMultiStateValidator } from '../src/useMultiStateValidator';
|
|
import { UseStateValidatorReturn, ValidityState } from '../src/useStateValidator';
|
|
|
|
interface Mock extends jest.Mock {}
|
|
|
|
describe('useMultiStateValidator', () => {
|
|
it('should be defined', () => {
|
|
expect(useMultiStateValidator).toBeDefined();
|
|
});
|
|
|
|
const defaultStatesValidator = (states: number[]) => [states.every((num) => !(num % 2))];
|
|
|
|
function getHook(
|
|
fn: MultiStateValidator<any, number[]> = jest.fn(defaultStatesValidator),
|
|
initialStates = [1, 2],
|
|
initialValidity = [false]
|
|
): [
|
|
MultiStateValidator<any, number[]>,
|
|
RenderHookResult<any, [Function, UseStateValidatorReturn<ValidityState>]>
|
|
] {
|
|
return [
|
|
fn,
|
|
renderHook(
|
|
({ initStates, validator, initValidity }) => {
|
|
const [states, setStates] = useState(initStates);
|
|
|
|
return [setStates, useMultiStateValidator(states, validator, initValidity)];
|
|
},
|
|
{
|
|
initialProps: {
|
|
initStates: initialStates,
|
|
initValidity: initialValidity,
|
|
validator: fn,
|
|
},
|
|
}
|
|
),
|
|
];
|
|
}
|
|
|
|
it('should return an array of two elements', () => {
|
|
const [, hook] = getHook();
|
|
const res = hook.result.current[1];
|
|
|
|
expect(Array.isArray(res)).toBe(true);
|
|
expect(res.length).toBe(2);
|
|
});
|
|
|
|
it('should call validator on init', () => {
|
|
const [spy] = getHook();
|
|
|
|
expect(spy).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('should call validator on any of states changed', () => {
|
|
const [spy, hook] = getHook();
|
|
|
|
expect(spy).toHaveBeenCalledTimes(1);
|
|
act(() => hook.result.current[0]([4, 2]));
|
|
expect(spy).toHaveBeenCalledTimes(2);
|
|
});
|
|
|
|
it("should NOT call validator on it's change", () => {
|
|
const [spy, hook] = getHook();
|
|
const newValidator: MultiStateValidator<any, number[]> = jest.fn((states) => [
|
|
states!.every((num) => !!(num % 2)),
|
|
]);
|
|
|
|
expect(spy).toHaveBeenCalledTimes(1);
|
|
hook.rerender({ validator: newValidator });
|
|
expect(spy).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('should throw if states is not an object', () => {
|
|
expect(() => {
|
|
// @ts-ignore
|
|
const [, hook] = getHook(defaultStatesValidator, 123);
|
|
|
|
if (hook.result.error) {
|
|
throw hook.result.error;
|
|
}
|
|
}).toThrowError('states expected to be an object or array, got number');
|
|
});
|
|
|
|
it('first returned element should represent current validity state', () => {
|
|
const [, hook] = getHook();
|
|
let [setState, [validity]] = hook.result.current;
|
|
expect(validity).toEqual([false]);
|
|
|
|
act(() => setState([4, 2]));
|
|
[setState, [validity]] = hook.result.current;
|
|
expect(validity).toEqual([true]);
|
|
|
|
act(() => setState([4, 5]));
|
|
[setState, [validity]] = hook.result.current;
|
|
expect(validity).toEqual([false]);
|
|
});
|
|
|
|
it('second returned element should re-call validation', () => {
|
|
const [spy, hook] = getHook();
|
|
const [, [, revalidate]] = hook.result.current;
|
|
|
|
expect(spy).toHaveBeenCalledTimes(1);
|
|
act(() => revalidate());
|
|
expect(spy).toHaveBeenCalledTimes(2);
|
|
});
|
|
|
|
it('validator should receive states as a firs argument', () => {
|
|
const [spy, hook] = getHook();
|
|
const [setState] = hook.result.current;
|
|
|
|
expect((spy as Mock).mock.calls[0].length).toBe(1);
|
|
expect((spy as Mock).mock.calls[0][0]).toEqual([1, 2]);
|
|
act(() => setState([4, 6]));
|
|
expect((spy as Mock).mock.calls[1][0]).toEqual([4, 6]);
|
|
});
|
|
|
|
it('if validator expects 2nd parameters it should pass a validity setter there', () => {
|
|
const spy = jest.fn((states: number[], done) => {
|
|
done([states.every((num) => !!(num % 2))]);
|
|
}) as unknown as MultiStateValidator<[boolean], number[]>;
|
|
const [, hook] = getHook(spy, [1, 3]);
|
|
const [, [validity]] = hook.result.current;
|
|
|
|
expect((spy as Mock).mock.calls[0].length).toBe(2);
|
|
expect((spy as Mock).mock.calls[0][0]).toEqual([1, 3]);
|
|
expect(validity).toEqual([true]);
|
|
});
|
|
});
|