react-use/tests/useSpring.test.ts
xobotyi b6993a6f95
feat(prettier): make prettier a part of eslint.
Also reduce max line width to 100. And remove `lint:types` step for
commit sequence, it bothers when committing incomplete (wip) changes.
2021-02-01 18:58:55 +03:00

120 lines
3.3 KiB
TypeScript

import { act, renderHook } from '@testing-library/react-hooks';
import { Spring } from 'rebound';
import useSpring from '../src/useSpring';
// simulate Spring for testing
const mockSetCurrentValue = jest.fn();
const mockAddListener = jest.fn();
const mockSetEndValue = jest.fn();
const mockRemoveListener = jest.fn();
let triggerSpringUpdate = () => {};
let springListener: Listener = { onSpringUpdate: () => {} };
interface Listener {
onSpringUpdate: (currentSpring: Spring) => void;
}
const mockCreateSpring: Spring = jest.fn().mockImplementation(() => {
let currentValue = 0;
let endValue = 0;
const getCloserValue = (a, b) => Math.round((a + b) / 2);
const getCurrentValue = () => {
currentValue = getCloserValue(currentValue, endValue);
return currentValue;
};
triggerSpringUpdate = () => {
if (currentValue !== endValue) {
springListener.onSpringUpdate({ getCurrentValue } as any);
}
};
return {
setCurrentValue: (val) => {
currentValue = val;
mockSetCurrentValue(val);
},
addListener: (newListener) => {
springListener = newListener;
mockAddListener(newListener);
},
setEndValue: (val) => {
endValue = val;
mockSetEndValue(val);
},
removeListener: mockRemoveListener,
};
}) as any;
jest.mock('rebound', () => {
return {
Sprint: {},
SpringSystem: jest.fn().mockImplementation(() => {
return { createSpring: mockCreateSpring };
}),
};
});
it('should init value to provided target', () => {
const { result } = renderHook(() => useSpring(70));
expect(result.current).toBe(70);
expect(mockSetCurrentValue).toHaveBeenCalledTimes(1);
expect(mockSetCurrentValue).toHaveBeenCalledWith(70);
expect(mockCreateSpring).toHaveBeenCalledTimes(1);
expect(mockCreateSpring).toHaveBeenCalledWith(50, 3);
});
it('should create spring with custom tension and friction args provided', () => {
renderHook(() => useSpring(500, 20, 7));
expect(mockCreateSpring).toHaveBeenCalledTimes(1);
expect(mockCreateSpring).toHaveBeenCalledWith(20, 7);
});
it('should subscribe only once', () => {
const { rerender } = renderHook(() => useSpring());
expect(mockAddListener).toHaveBeenCalledTimes(1);
expect(mockAddListener).toHaveBeenCalledWith(springListener);
rerender();
expect(mockAddListener).toHaveBeenCalledTimes(1);
});
it('should handle spring update', () => {
let targetValue = 70;
let lastSpringValue = targetValue;
const { result, rerender } = renderHook(() => useSpring(targetValue));
targetValue = 100;
rerender();
expect(result.current).toBe(lastSpringValue);
act(() => {
triggerSpringUpdate(); // simulate new spring value
});
expect(result.current).toBeGreaterThan(lastSpringValue);
expect(result.current).toBeLessThanOrEqual(targetValue);
lastSpringValue = result.current;
act(() => {
triggerSpringUpdate(); // simulate another new spring value
});
expect(result.current).toBeGreaterThan(lastSpringValue);
expect(result.current).toBeLessThanOrEqual(targetValue);
});
it('should remove listener on unmount', () => {
const { unmount } = renderHook(() => useSpring());
expect(mockRemoveListener).not.toHaveBeenCalled();
unmount();
expect(mockRemoveListener).toHaveBeenCalledTimes(1);
expect(mockRemoveListener).toHaveBeenCalledWith(springListener);
});