diff --git a/CHANGELOG.md b/CHANGELOG.md
index f490b989..15b1a3b1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+# [10.4.0](https://github.com/streamich/react-use/compare/v10.3.1...v10.4.0) (2019-08-02)
+
+
+### Features
+
+* add useMountedState hook ([9081b99](https://github.com/streamich/react-use/commit/9081b99))
+
+## [10.3.1](https://github.com/streamich/react-use/compare/v10.3.0...v10.3.1) (2019-08-02)
+
+
+### Bug Fixes
+
+* **storybook:** fix useKeyboardJs import path ([b7481f6](https://github.com/streamich/react-use/commit/b7481f6))
+* **useKeyboardJs:** fix argument type error ([8c820ce](https://github.com/streamich/react-use/commit/8c820ce))
+* allow string list in useKeyboardJs hook ([aecbd0b](https://github.com/streamich/react-use/commit/aecbd0b))
+
# [10.3.0](https://github.com/streamich/react-use/compare/v10.2.0...v10.3.0) (2019-07-26)
diff --git a/README.md b/README.md
index 0a36269d..9e97e95b 100644
--- a/README.md
+++ b/README.md
@@ -102,12 +102,12 @@
- [`useTitle`](./docs/useTitle.md) — sets title of the page.
- [`usePermission`](./docs/usePermission.md) — query permission status for browser APIs.
-
+
- [**Lifecycles**](./docs/Lifecycles.md)
- [`useEffectOnce`](./docs/useEffectOnce.md) — a modified [`useEffect`](https://reactjs.org/docs/hooks-reference.html#useeffect) hook that only runs once.
- [`useEvent`](./docs/useEvent.md) — subscribe to events.
- [`useLifecycles`](./docs/useLifecycles.md) — calls `mount` and `unmount` callbacks.
- - [`useRefMounted`](./docs/useRefMounted.md) — tracks if component is mounted.
+ - [`useMountedState`](./docs/useMountedState.md) and [`useRefMounted`](./docs/useRefMounted.md) — track if component is mounted.
- [`usePromise`](./docs/usePromise.md) — resolves promise only while component is mounted.
- [`useLogger`](./docs/useLogger.md) — logs in console as component goes through life-cycles.
- [`useMount`](./docs/useMount.md) — calls `mount` callbacks.
diff --git a/docs/useKeyboardJs.md b/docs/useKeyboardJs.md
index 6dc09ef9..3df9d49d 100644
--- a/docs/useKeyboardJs.md
+++ b/docs/useKeyboardJs.md
@@ -37,5 +37,5 @@ yarn add keyboardjs
## Reference
```js
-useKeyboardJs(combination: string): [isPressed: boolean, event?: KeyboardEvent]
+useKeyboardJs(combination: string | string[]): [isPressed: boolean, event?: KeyboardEvent]
```
diff --git a/docs/useMountedState.md b/docs/useMountedState.md
new file mode 100644
index 00000000..ae6ecace
--- /dev/null
+++ b/docs/useMountedState.md
@@ -0,0 +1,25 @@
+# `useMountedState`
+
+Lifecycle hook providing ability to check component's mount state.
+Gives a function that will return `true` if component mounted and `false` otherwise.
+
+## Usage
+
+```jsx
+import * as React from 'react';
+import {useMountedState} from 'react-use';
+
+const Demo = () => {
+ const isMounted = useMountedState();
+
+ React.useEffect(() => {
+ setTimeout(() => {
+ if (isMounted()) {
+ // ...
+ } else {
+ // ...
+ }
+ }, 1000);
+ });
+};
+```
diff --git a/package.json b/package.json
index a3604150..b0473dfd 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-use",
- "version": "10.3.0",
+ "version": "10.4.0",
"description": "Collection of React Hooks",
"main": "lib/index.js",
"module": "esm/index.js",
@@ -24,7 +24,7 @@
"clean": "rimraf lib storybook-static esm",
"storybook": "start-storybook -p 6008",
"storybook:build": "build-storybook",
- "storybook:upload": "gh-pages -d storybook-static",
+ "storybook:upload": "gh-pages -d storybook-static --git \"$(which git)\"",
"storybook:clean": "rimraf storybook-static",
"release": "semantic-release"
},
@@ -67,34 +67,35 @@
"@semantic-release/changelog": "3.0.4",
"@semantic-release/git": "7.0.16",
"@semantic-release/npm": "5.1.13",
- "@storybook/addon-actions": "5.1.9",
- "@storybook/addon-knobs": "5.1.9",
- "@storybook/addon-notes": "5.1.9",
- "@storybook/addon-options": "5.1.9",
- "@storybook/react": "5.1.9",
- "@types/jest": "24.0.15",
+ "@storybook/addon-actions": "5.1.10",
+ "@storybook/addon-knobs": "5.1.10",
+ "@storybook/addon-notes": "5.1.10",
+ "@storybook/addon-options": "5.1.10",
+ "@storybook/react": "5.1.10",
+ "@testing-library/react-hooks": "^1.1.0",
+ "@types/jest": "24.0.16",
"@types/react": "16.8.23",
"babel-core": "6.26.3",
"babel-loader": "8.0.6",
"babel-plugin-dynamic-import-node": "2.3.0",
"fork-ts-checker-webpack-plugin": "1.4.3",
- "gh-pages": "2.0.1",
- "husky": "3.0.1",
+ "gh-pages": "2.1.0",
+ "husky": "3.0.2",
"jest": "24.8.0",
"keyboardjs": "2.5.1",
"lint-staged": "9.2.1",
- "markdown-loader": "5.0.0",
+ "markdown-loader": "5.1.0",
"prettier": "1.17.1",
"react": "16.8.6",
"react-dom": "16.8.6",
- "react-hooks-testing-library": "0.4.1",
"react-spring": "8.0.27",
+ "react-test-renderer": "^16.8.6",
"rebound": "0.1.0",
"redux-logger": "3.0.6",
"redux-thunk": "2.3.0",
"rimraf": "2.6.3",
"rxjs": "6.5.2",
- "semantic-release": "15.13.18",
+ "semantic-release": "15.13.19",
"ts-loader": "6.0.4",
"ts-node": "8.3.0",
"tslint": "5.18.0",
diff --git a/src/__stories__/useKeyboardJs.story.tsx b/src/__stories__/useKeyboardJs.story.tsx
index f9e83e9b..fd2f16cd 100644
--- a/src/__stories__/useKeyboardJs.story.tsx
+++ b/src/__stories__/useKeyboardJs.story.tsx
@@ -1,7 +1,7 @@
import { text, withKnobs } from '@storybook/addon-knobs';
import { storiesOf } from '@storybook/react';
import * as React from 'react';
-import { useKeyboardJs } from '..';
+import useKeyboardJs from '../useKeyboardJs';
import { CenterStory } from './util/CenterStory';
import ShowDocs from './util/ShowDocs';
diff --git a/src/__stories__/useMountedState.story.tsx b/src/__stories__/useMountedState.story.tsx
new file mode 100644
index 00000000..a4bcac43
--- /dev/null
+++ b/src/__stories__/useMountedState.story.tsx
@@ -0,0 +1,17 @@
+import { storiesOf } from '@storybook/react';
+import * as React from 'react';
+import { useMountedState } from '..';
+import ShowDocs from './util/ShowDocs';
+
+const Demo = () => {
+ const isMounted = useMountedState();
+ const [, updateState] = React.useState();
+
+ requestAnimationFrame(updateState);
+
+ return
This component is {isMounted() ? 'MOUNTED' : 'NOT MOUNTED'}
;
+};
+
+storiesOf('Lifecycle|useMountedState', module)
+ .add('Docs', () => )
+ .add('Demo', () => );
diff --git a/src/__tests__/createMemo.test.ts b/src/__tests__/createMemo.test.ts
new file mode 100644
index 00000000..2acb5d94
--- /dev/null
+++ b/src/__tests__/createMemo.test.ts
@@ -0,0 +1,45 @@
+import { renderHook } from '@testing-library/react-hooks';
+import createMemo from '../createMemo';
+
+const getDouble = jest.fn((n: number): number => n * 2);
+
+it('should init memo hook', () => {
+ const useMemoGetDouble = createMemo(getDouble);
+
+ expect(useMemoGetDouble).toBeInstanceOf(Function);
+});
+
+describe('when using created memo hook', () => {
+ let useMemoGetDouble;
+
+ beforeEach(() => {
+ useMemoGetDouble = createMemo(getDouble);
+ });
+
+ it.each([[1], [3], [5]])('should return same result as original function for argument %d', (val: number) => {
+ const { result } = renderHook(() => useMemoGetDouble(val));
+ expect(result.current).toBe(getDouble(val));
+ });
+
+ it('should NOT call original function for same arguments', () => {
+ let initialValue = 5;
+ expect(getDouble).not.toHaveBeenCalled();
+
+ // it's called first time calculating for argument 5
+ const { rerender } = renderHook(() => useMemoGetDouble(initialValue));
+ expect(getDouble).toHaveBeenCalled();
+
+ getDouble.mockClear();
+
+ // it's NOT called second time calculating for argument 5
+ rerender();
+ expect(getDouble).not.toHaveBeenCalled();
+
+ getDouble.mockClear();
+
+ // it's called again calculating for different argument
+ initialValue = 7;
+ rerender();
+ expect(getDouble).toHaveBeenCalled();
+ });
+});
diff --git a/src/__tests__/createReducer.test.ts b/src/__tests__/createReducer.test.ts
new file mode 100644
index 00000000..42ae47c6
--- /dev/null
+++ b/src/__tests__/createReducer.test.ts
@@ -0,0 +1,112 @@
+import { act, renderHook } from '@testing-library/react-hooks';
+import createReducer from '../createReducer';
+import logger from 'redux-logger';
+import thunk from 'redux-thunk';
+
+it('should init reducer hook function', () => {
+ const useSomeReducer = createReducer();
+ expect(useSomeReducer).toBeInstanceOf(Function);
+});
+
+/**
+ * This test suite implements the special demo in storybook that creates a
+ * reducer with thunk and logger for using a simple counter
+ */
+describe('when using created reducer hook', () => {
+ const initialCount = 1;
+ let originalLog;
+ let originalGroup;
+ const mockLog = jest.fn();
+ const mockGroup = jest.fn();
+
+ function reducer(state, action) {
+ switch (action.type) {
+ case 'increment':
+ return { count: state.count + 1 };
+ case 'decrement':
+ return { count: state.count - 1 };
+ case 'reset':
+ return { count: action.payload };
+ default:
+ throw new Error();
+ }
+ }
+
+ // Action creator to increment count, wait a second and then reset
+ const addAndReset = () => {
+ return dispatch => {
+ dispatch({ type: 'increment' });
+
+ setTimeout(() => {
+ dispatch({ type: 'reset', payload: initialCount });
+ }, 1000);
+ };
+ };
+
+ const setUp = () => {
+ const useThunkReducer = createReducer(thunk, logger);
+ return renderHook(() => useThunkReducer(reducer, { count: initialCount }));
+ };
+
+ beforeAll(() => {
+ originalLog = console.log;
+ originalGroup = console.group;
+ console.log = mockLog;
+ console.group = mockGroup;
+ });
+
+ beforeEach(() => {
+ jest.useFakeTimers();
+ });
+
+ afterAll(() => {
+ console.log = originalLog;
+ console.group = originalGroup;
+ });
+
+ it('should init state and dispatcher', () => {
+ const { result } = setUp();
+ const [state, dispatch] = result.current;
+
+ expect(state).toEqual({ count: 1 });
+ expect(dispatch).toBeInstanceOf(Function);
+ });
+
+ it.each`
+ actionType | expectedCount | payload
+ ${'increment'} | ${2} | ${undefined}
+ ${'decrement'} | ${0} | ${undefined}
+ ${'reset'} | ${1} | ${1}
+ `('should handle "$actionType" action', ({ actionType, expectedCount, payload }) => {
+ const { result } = setUp();
+ const [, dispatch] = result.current;
+ expect(mockLog).not.toHaveBeenCalled();
+
+ act(() => {
+ dispatch({ type: actionType, payload });
+ });
+
+ expect(result.current[0]).toEqual({ count: expectedCount });
+ expect(mockLog).toHaveBeenCalled();
+ });
+
+ it('should handle async action with several middlewares', () => {
+ const { result } = setUp();
+ const [, dispatch] = result.current;
+ expect(mockLog).not.toHaveBeenCalled();
+
+ act(() => {
+ dispatch(addAndReset());
+ });
+
+ expect(result.current[0]).toEqual({ count: 2 });
+ expect(mockLog).toHaveBeenCalled();
+
+ // fast-forward until all timers have been executed
+ act(() => {
+ jest.runAllTimers();
+ });
+
+ expect(result.current[0]).toEqual({ count: 1 });
+ });
+});
diff --git a/src/__tests__/useAsync.test.tsx b/src/__tests__/useAsync.test.tsx
index 3764e42a..4e5ca61f 100644
--- a/src/__tests__/useAsync.test.tsx
+++ b/src/__tests__/useAsync.test.tsx
@@ -1,9 +1,7 @@
+import { renderHook } from '@testing-library/react-hooks';
import { useCallback } from 'react';
-import { cleanup, renderHook } from 'react-hooks-testing-library';
import useAsync from '../useAsync';
-afterEach(cleanup);
-
// NOTE: these tests cause console errors.
// maybe we should test in a real environment instead
// of a fake one?
@@ -17,7 +15,7 @@ describe('useAsync', () => {
let callCount = 0;
const resolver = async () => {
- return new Promise((resolve, reject) => {
+ return new Promise(resolve => {
callCount++;
const wait = setTimeout(() => {
@@ -58,7 +56,7 @@ describe('useAsync', () => {
let callCount = 0;
const rejection = async () => {
- return new Promise((resolve, reject) => {
+ return new Promise((_, reject) => {
callCount++;
const wait = setTimeout(() => {
diff --git a/src/__tests__/useAsyncFn.test.tsx b/src/__tests__/useAsyncFn.test.tsx
index 8e3826b5..f9c7d238 100644
--- a/src/__tests__/useAsyncFn.test.tsx
+++ b/src/__tests__/useAsyncFn.test.tsx
@@ -5,11 +5,9 @@
// does not automatically invoke the function
// and it can take arguments.
-import { cleanup, renderHook } from 'react-hooks-testing-library';
+import { renderHook } from '@testing-library/react-hooks';
import useAsyncFn, { AsyncState } from '../useAsyncFn';
-afterEach(cleanup);
-
type AdderFn = (a: number, b: number) => Promise;
describe('useAsyncFn', () => {
diff --git a/src/__tests__/useBoolean.test.ts b/src/__tests__/useBoolean.test.ts
new file mode 100644
index 00000000..8f633e9e
--- /dev/null
+++ b/src/__tests__/useBoolean.test.ts
@@ -0,0 +1,6 @@
+import useBoolean from '../useBoolean';
+import useToggle from '../useToggle';
+
+it('should be an alias for useToggle ', () => {
+ expect(useBoolean).toBe(useToggle);
+});
diff --git a/src/__tests__/useCounter.test.ts b/src/__tests__/useCounter.test.ts
new file mode 100644
index 00000000..41cc1e22
--- /dev/null
+++ b/src/__tests__/useCounter.test.ts
@@ -0,0 +1,128 @@
+import { act, renderHook } from '@testing-library/react-hooks';
+import useCounter from '../useCounter';
+
+const setUp = (initialValue?: number) => renderHook(() => useCounter(initialValue));
+
+it('should init counter and utils', () => {
+ const { result } = setUp(5);
+
+ expect(result.current[0]).toBe(5);
+ expect(result.current[1]).toStrictEqual({
+ inc: expect.any(Function),
+ dec: expect.any(Function),
+ get: expect.any(Function),
+ set: expect.any(Function),
+ reset: expect.any(Function),
+ });
+});
+
+it('should init counter to 0 if not initial value received', () => {
+ const { result } = setUp();
+
+ expect(result.current[0]).toBe(0);
+});
+
+it('should init counter to negative number', () => {
+ const { result } = setUp(-2);
+
+ expect(result.current[0]).toBe(-2);
+});
+
+it('should get current counter', () => {
+ const { result } = setUp(5);
+ const { get } = result.current[1];
+
+ expect(get()).toBe(5);
+});
+
+it('should increment by 1 if not value received', () => {
+ const { result } = setUp(5);
+ const { get, inc } = result.current[1];
+
+ act(() => inc());
+
+ expect(result.current[0]).toBe(6);
+ expect(get()).toBe(6);
+});
+
+it('should increment by value received', () => {
+ const { result } = setUp(5);
+ const { get, inc } = result.current[1];
+
+ act(() => inc(9));
+
+ expect(result.current[0]).toBe(14);
+ expect(get()).toBe(14);
+});
+
+it('should decrement by 1 if not value received', () => {
+ const { result } = setUp(5);
+ const { get, dec } = result.current[1];
+
+ act(() => dec());
+
+ expect(result.current[0]).toBe(4);
+ expect(get()).toBe(4);
+});
+
+it('should decrement by value received', () => {
+ const { result } = setUp(5);
+ const { get, dec } = result.current[1];
+
+ act(() => dec(9));
+
+ expect(result.current[0]).toBe(-4);
+ expect(get()).toBe(-4);
+});
+
+it('should set to value received', () => {
+ const { result } = setUp(5);
+ const { get, set } = result.current[1];
+
+ act(() => set(17));
+
+ expect(result.current[0]).toBe(17);
+ expect(get()).toBe(17);
+});
+
+it('should reset to original value', () => {
+ const { result } = setUp(5);
+ const { get, set, reset } = result.current[1];
+
+ // set different value than initial one...
+ act(() => set(17));
+ expect(result.current[0]).toBe(17);
+
+ // ... and reset it to initial one
+ act(() => reset());
+ expect(result.current[0]).toBe(5);
+ expect(get()).toBe(5);
+});
+
+it('should reset and set new original value', () => {
+ const { result } = setUp(5);
+ const { get, set, reset } = result.current[1];
+
+ // set different value than initial one...
+ act(() => set(17));
+ expect(result.current[0]).toBe(17);
+
+ // ... now reset and set it to different than initial one...
+ act(() => reset(8));
+ expect(result.current[0]).toBe(8);
+
+ // ... and set different value than initial one again...
+ act(() => set(32));
+ expect(result.current[0]).toBe(32);
+
+ // ... and reset it to new initial value
+ act(() => reset());
+ expect(result.current[0]).toBe(8);
+ expect(get()).toBe(8);
+});
+
+it.todo('should log an error if initial value is other than a number');
+it.todo('should log an error if increment value is other than a number');
+it.todo('should log an error if increment value is a negative number');
+it.todo('should log an error if decrement value is other than a number');
+it.todo('should log an error if decrement value is a negative number');
diff --git a/src/__tests__/useDefault.test.ts b/src/__tests__/useDefault.test.ts
new file mode 100644
index 00000000..3e1fbd5a
--- /dev/null
+++ b/src/__tests__/useDefault.test.ts
@@ -0,0 +1,61 @@
+import { act, renderHook } from '@testing-library/react-hooks';
+import useDefault from '../useDefault';
+
+const setUp = (defaultValue: any, initialValue: any) => renderHook(() => useDefault(defaultValue, initialValue));
+
+describe.each`
+ valueType | defaultValue | initialValue | anotherValue
+ ${'number'} | ${0} | ${5} | ${77}
+ ${'object'} | ${{}} | ${{ name: 'John Doe' }} | ${{ name: 'Solid Snake' }}
+ ${'boolean'} | ${false} | ${false} | ${true}
+ ${'string'} | ${''} | ${'foo'} | ${'bar'}
+`('when value type is $valueType', ({ defaultValue, initialValue, anotherValue }) => {
+ it('should init state with initial value', () => {
+ const { result } = setUp(defaultValue, initialValue);
+ const [value, setValue] = result.current;
+
+ expect(value).toBe(initialValue);
+ expect(setValue).toBeInstanceOf(Function);
+ });
+
+ it('should set state to another value', () => {
+ const { result } = setUp(defaultValue, initialValue);
+ const [, setValue] = result.current;
+
+ act(() => setValue(anotherValue));
+
+ expect(result.current[0]).toBe(anotherValue);
+ });
+
+ it('should return default value if state set to null', () => {
+ const { result } = setUp(defaultValue, initialValue);
+ const [, setValue] = result.current;
+
+ act(() => setValue(null));
+
+ expect(result.current[0]).toBe(defaultValue);
+ });
+
+ it('should return default value if state set to undefined', () => {
+ const { result } = setUp(defaultValue, initialValue);
+ const [, setValue] = result.current;
+
+ act(() => setValue(undefined));
+
+ expect(result.current[0]).toBe(defaultValue);
+ });
+
+ it('should handle state properly after being set to nil and then to another value', () => {
+ const { result } = setUp(defaultValue, initialValue);
+ const [, setValue] = result.current;
+
+ act(() => setValue(undefined));
+ expect(result.current[0]).toBe(defaultValue);
+
+ act(() => setValue(null));
+ expect(result.current[0]).toBe(defaultValue);
+
+ act(() => setValue(anotherValue));
+ expect(result.current[0]).toBe(anotherValue);
+ });
+});
diff --git a/src/__tests__/useDefault.test.tsx b/src/__tests__/useDefault.test.tsx
deleted file mode 100644
index 97de7d4b..00000000
--- a/src/__tests__/useDefault.test.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import { act, cleanup, renderHook } from 'react-hooks-testing-library';
-import useDefault from '../useDefault';
-
-afterEach(cleanup);
-
-describe('useDefault', () => {
- test('should be defined', () => {
- expect(useDefault).toBeDefined();
- });
-
- const hook = renderHook(() => useDefault({ name: 'Marshall' }, { name: '' }));
-
- test('should return initial state on initial render', () => {
- expect(hook.result.current[0].name).toBe('');
- });
-
- test('should update state with correct value', () => {
- hook.rerender();
- act(() => {
- hook.result.current[1]({ name: 'Mathers' });
- });
-
- expect(hook.result.current[0].name).toBe('Mathers');
- });
-
- test('should return the default value when updated state is nil', () => {
- hook.rerender();
- act(() => {
- hook.result.current[1](null);
- });
-
- expect(hook.result.current[0].name).toBe('Marshall');
-
- act(() => {
- hook.result.current[1](undefined);
- });
-
- expect(hook.result.current[0].name).toBe('Marshall');
- });
-});
diff --git a/src/__tests__/useGetSet.test.ts b/src/__tests__/useGetSet.test.ts
new file mode 100644
index 00000000..1f971e09
--- /dev/null
+++ b/src/__tests__/useGetSet.test.ts
@@ -0,0 +1,64 @@
+import { act, renderHook } from '@testing-library/react-hooks';
+import useGetSet from '../useGetSet';
+
+const setUp = (initialValue: any) => renderHook(() => useGetSet(initialValue));
+
+beforeEach(() => {
+ jest.useFakeTimers();
+});
+
+it('should init getter and setter', () => {
+ const { result } = setUp('foo');
+ const [get, set] = result.current;
+
+ expect(get).toBeInstanceOf(Function);
+ expect(set).toBeInstanceOf(Function);
+});
+
+it('should get current value', () => {
+ const { result } = setUp('foo');
+ const [get] = result.current;
+
+ const currentValue = get();
+
+ expect(currentValue).toBe('foo');
+});
+
+it('should set new value', () => {
+ const { result } = setUp('foo');
+ const [get, set] = result.current;
+
+ act(() => set('bar'));
+
+ const currentValue = get();
+ expect(currentValue).toBe('bar');
+});
+
+/**
+ * This test implements the special demo in storybook that increments a number
+ * after 1 second on each click.
+ */
+it('should get and set expected values when used in nested functions', () => {
+ const onClick = jest.fn(() => {
+ setTimeout(() => {
+ set(get() + 1);
+ }, 1000);
+ });
+
+ const { result } = setUp(0);
+ const [get, set] = result.current;
+
+ // simulate 3 clicks
+ onClick();
+ onClick();
+ onClick();
+
+ // fast-forward until all timers have been executed
+ act(() => {
+ jest.runAllTimers();
+ });
+
+ 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..e9eb6aef
--- /dev/null
+++ b/src/__tests__/useGetSetState.test.ts
@@ -0,0 +1,136 @@
+import { act, renderHook } from '@testing-library/react-hooks';
+import useGetSetState from '../useGetSetState';
+
+const originalConsoleError = console.error;
+const mockConsoleError = jest.fn();
+
+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 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 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 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 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 NOT set new state if no patch received', () => {
+ const { result } = setUp({ foo: 'a', bar: 'z' });
+ const [get, set] = result.current;
+
+ // @ts-ignore
+ 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);
+});
diff --git a/src/__tests__/useList.test.ts b/src/__tests__/useList.test.ts
new file mode 100644
index 00000000..047e6e68
--- /dev/null
+++ b/src/__tests__/useList.test.ts
@@ -0,0 +1,152 @@
+import { act, renderHook } from '@testing-library/react-hooks';
+import useList from '../useList';
+
+const setUp = (initialList?: any[]) => renderHook(() => useList(initialList));
+
+it('should init list and utils', () => {
+ const { result } = setUp([1, 2, 3]);
+ const [list, utils] = result.current;
+
+ expect(list).toEqual([1, 2, 3]);
+ expect(utils).toStrictEqual({
+ set: expect.any(Function),
+ clear: expect.any(Function),
+ updateAt: expect.any(Function),
+ remove: expect.any(Function),
+ push: expect.any(Function),
+ filter: expect.any(Function),
+ sort: expect.any(Function),
+ });
+});
+
+it('should init empty list if not initial list provided', () => {
+ const { result } = setUp();
+
+ expect(result.current[0]).toEqual([]);
+});
+
+it('should set new list', () => {
+ const initList = [1, 2, 3];
+ const { result } = setUp(initList);
+ const [, utils] = result.current;
+
+ act(() => {
+ utils.set([4, 5, 6]);
+ });
+
+ expect(result.current[0]).toEqual([4, 5, 6]);
+ expect(result.current[0]).not.toBe(initList); // checking immutability
+});
+
+it('should clear current list', () => {
+ const initList = [1, 2, 3];
+ const { result } = setUp(initList);
+ const [, utils] = result.current;
+
+ act(() => {
+ utils.clear();
+ });
+
+ expect(result.current[0]).toEqual([]);
+ expect(result.current[0]).not.toBe(initList); // checking immutability
+});
+
+it('should update element at specific position', () => {
+ const initList = [1, 2, 3];
+ const { result } = setUp(initList);
+ const [, utils] = result.current;
+
+ act(() => {
+ utils.updateAt(1, 'foo');
+ });
+
+ expect(result.current[0]).toEqual([1, 'foo', 3]);
+ expect(result.current[0]).not.toBe(initList); // checking immutability
+});
+
+it('should remove element at specific position', () => {
+ const initList = [1, 2, 3];
+ const { result } = setUp(initList);
+ const [, utils] = result.current;
+
+ act(() => {
+ utils.remove(1);
+ });
+
+ expect(result.current[0]).toEqual([1, 3]);
+ expect(result.current[0]).not.toBe(initList); // checking immutability
+});
+
+it('should push new element at the end of the list', () => {
+ const initList = [1, 2, 3];
+ const { result } = setUp(initList);
+ const [, utils] = result.current;
+
+ act(() => {
+ utils.push(0);
+ });
+
+ expect(result.current[0]).toEqual([1, 2, 3, 0]);
+ expect(result.current[0]).not.toBe(initList); // checking immutability
+});
+
+it('should push duplicated element at the end of the list', () => {
+ const initList = [1, 2, 3];
+ const { result } = setUp(initList);
+ const [, utils] = result.current;
+
+ act(() => {
+ utils.push(2);
+ });
+
+ expect(result.current[0]).toEqual([1, 2, 3, 2]);
+ expect(result.current[0]).not.toBe(initList); // checking immutability
+});
+
+it('should filter current list by provided function', () => {
+ const initList = [1, -1, 2, -2, 3, -3];
+ const { result } = setUp(initList);
+ const [, utils] = result.current;
+
+ act(() => {
+ utils.filter(n => n < 0);
+ });
+
+ expect(result.current[0]).toEqual([-1, -2, -3]);
+ expect(result.current[0]).not.toBe(initList); // checking immutability
+});
+
+it('should sort current list by default order', () => {
+ const initList = ['March', 'Jan', 'Feb', 'Dec'];
+ const { result } = setUp(initList);
+ const [, utils] = result.current;
+
+ act(() => {
+ utils.sort();
+ });
+
+ expect(result.current[0]).toEqual(['Dec', 'Feb', 'Jan', 'March']);
+ expect(result.current[0]).not.toBe(initList); // checking immutability
+});
+
+it('should sort current list by provided function', () => {
+ const initList = ['March', 'Jan', 'Feb', 'Dec'];
+ const { result } = setUp(initList);
+ const [, utils] = result.current;
+
+ act(() => {
+ utils.sort((a, b) => {
+ if (a < b) {
+ return 1;
+ }
+ if (a > b) {
+ return -1;
+ }
+
+ return 0;
+ });
+ });
+
+ expect(result.current[0]).toEqual(['March', 'Jan', 'Feb', 'Dec']);
+ expect(result.current[0]).not.toBe(initList); // checking immutability
+});
diff --git a/src/__tests__/useMap.test.ts b/src/__tests__/useMap.test.ts
new file mode 100644
index 00000000..242df55f
--- /dev/null
+++ b/src/__tests__/useMap.test.ts
@@ -0,0 +1,115 @@
+import { act, renderHook } from '@testing-library/react-hooks';
+import useMap from '../useMap';
+
+const setUp = (initialMap?: object) => renderHook(() => useMap(initialMap));
+
+it('should init map and utils', () => {
+ const { result } = setUp({ foo: 'bar', a: 1 });
+ const [map, utils] = result.current;
+
+ expect(map).toEqual({ foo: 'bar', a: 1 });
+ expect(utils).toStrictEqual({
+ get: expect.any(Function),
+ set: expect.any(Function),
+ remove: expect.any(Function),
+ reset: expect.any(Function),
+ });
+});
+
+it('should init empty map if not initial object provided', () => {
+ const { result } = setUp();
+
+ expect(result.current[0]).toEqual({});
+});
+
+it('should get corresponding value for existing provided key', () => {
+ const { result } = setUp({ foo: 'bar', a: 1 });
+ const [, utils] = result.current;
+
+ let value;
+ act(() => {
+ // @ts-ignore
+ value = utils.get('a');
+ });
+
+ expect(value).toBe(1);
+});
+
+it('should get undefined for non-existing provided key', () => {
+ const { result } = setUp({ foo: 'bar', a: 1 });
+ const [, utils] = result.current;
+
+ let value;
+ act(() => {
+ // @ts-ignore
+ value = utils.get('nonExisting');
+ });
+
+ expect(value).toBeUndefined();
+});
+
+it('should set new key-value pair', () => {
+ const { result } = setUp({ foo: 'bar', a: 1 });
+ const [, utils] = result.current;
+
+ act(() => {
+ // @ts-ignore
+ utils.set('newKey', 99);
+ });
+
+ expect(result.current[0]).toEqual({ foo: 'bar', a: 1, newKey: 99 });
+});
+
+it('should override current value if setting existing key', () => {
+ const { result } = setUp({ foo: 'bar', a: 1 });
+ const [, utils] = result.current;
+
+ act(() => {
+ // @ts-ignore
+ utils.set('foo', 99);
+ });
+
+ expect(result.current[0]).toEqual({ foo: 99, a: 1 });
+});
+
+it('should remove corresponding key-value pair for existing provided key', () => {
+ const { result } = setUp({ foo: 'bar', a: 1 });
+ const [, utils] = result.current;
+
+ act(() => {
+ // @ts-ignore
+ utils.remove('foo');
+ });
+
+ expect(result.current[0]).toEqual({ a: 1 });
+});
+
+it('should do nothing if removing non-existing provided key', () => {
+ const { result } = setUp({ foo: 'bar', a: 1 });
+ const [, utils] = result.current;
+
+ act(() => {
+ // @ts-ignore
+ utils.remove('nonExisting');
+ });
+
+ expect(result.current[0]).toEqual({ foo: 'bar', a: 1 });
+});
+
+it('should reset map to initial object provided', () => {
+ const { result } = setUp({ foo: 'bar', a: 1 });
+ const [, utils] = result.current;
+
+ act(() => {
+ // @ts-ignore
+ utils.set('z', 99);
+ });
+
+ expect(result.current[0]).toEqual({ foo: 'bar', a: 1, z: 99 });
+
+ act(() => {
+ utils.reset();
+ });
+
+ expect(result.current[0]).toEqual({ foo: 'bar', a: 1 });
+});
diff --git a/src/__tests__/useMountedState.test.tsx b/src/__tests__/useMountedState.test.tsx
new file mode 100644
index 00000000..ea3d8af9
--- /dev/null
+++ b/src/__tests__/useMountedState.test.tsx
@@ -0,0 +1,28 @@
+import { renderHook } from '@testing-library/react-hooks';
+import useMountedState from '../useMountedState';
+
+describe('useMountedState', () => {
+ it('should be defined', () => {
+ expect(useMountedState).toBeDefined();
+ });
+
+ it('should return a function', () => {
+ const hook = renderHook(() => useMountedState(), { initialProps: false });
+
+ expect(typeof hook.result.current).toEqual('function');
+ });
+
+ it('should return true if component is mounted', () => {
+ const hook = renderHook(() => useMountedState(), { initialProps: false });
+
+ expect(hook.result.current()).toBeTruthy();
+ });
+
+ it('should return false if component is unmounted', () => {
+ const hook = renderHook(() => useMountedState(), { initialProps: false });
+
+ hook.unmount();
+
+ expect(hook.result.current()).toBeFalsy();
+ });
+});
diff --git a/src/__tests__/useNumber.test.ts b/src/__tests__/useNumber.test.ts
new file mode 100644
index 00000000..f646f931
--- /dev/null
+++ b/src/__tests__/useNumber.test.ts
@@ -0,0 +1,6 @@
+import useNumber from '../useNumber';
+import useCounter from '../useCounter';
+
+it('should be an alias for useCounter', () => {
+ expect(useNumber).toBe(useCounter);
+});
diff --git a/src/__tests__/useObservable-layout.spec.ts b/src/__tests__/useObservable-layout.spec.ts
deleted file mode 100644
index 3701401f..00000000
--- a/src/__tests__/useObservable-layout.spec.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import * as React from 'react';
-import * as ReactDOM from 'react-dom';
-import { Subject } from 'rxjs';
-import { useObservable } from '..';
-import useIsomorphicLayoutEffect from '../useIsomorphicLayoutEffect';
-
-jest.mock('../useIsomorphicLayoutEffect');
-
-test('uses layout effect (to subscribe synchronously)', async () => {
- const subject = new Subject();
- const container = document.createElement('div');
-
- const Demo = ({ obs }) => {
- const value = useObservable(obs);
- return React.createElement(React.Fragment, {}, value);
- };
-
- expect(useIsomorphicLayoutEffect).toHaveBeenCalledTimes(0);
- ReactDOM.render(React.createElement(Demo, { obs: subject }), container);
- expect(useIsomorphicLayoutEffect).toHaveBeenCalledTimes(1);
-});
diff --git a/src/__tests__/useObservable.test.ts b/src/__tests__/useObservable.test.ts
new file mode 100644
index 00000000..7a4c2128
--- /dev/null
+++ b/src/__tests__/useObservable.test.ts
@@ -0,0 +1,108 @@
+import { act, renderHook } from '@testing-library/react-hooks';
+import { Subject } from 'rxjs';
+import useObservable, { Observable } from '../useObservable';
+import * as useIsomorphicLayoutEffect from '../useIsomorphicLayoutEffect';
+
+const setUp = (observable: Observable, initialValue?: any) =>
+ renderHook(() => useObservable(observable, initialValue));
+
+it('should init to initial value provided', () => {
+ const subject$ = new Subject();
+ const { result } = setUp(subject$, 123);
+
+ expect(result.current).toBe(123);
+});
+
+it('should init to undefined if not initial value provided', () => {
+ const subject$ = new Subject();
+ const { result } = setUp(subject$);
+
+ expect(result.current).toBeUndefined();
+});
+
+it('should return latest value of observables', () => {
+ const subject$ = new Subject();
+ const { result } = setUp(subject$, 123);
+
+ act(() => {
+ subject$.next(125);
+ });
+ expect(result.current).toBe(125);
+
+ act(() => {
+ subject$.next(300);
+ subject$.next(400);
+ });
+ expect(result.current).toBe(400);
+});
+
+it('should use layout effect to subscribe synchronously', async () => {
+ const subject$ = new Subject();
+ const spy = jest.spyOn(useIsomorphicLayoutEffect, 'default');
+
+ expect(spy).toHaveBeenCalledTimes(0);
+
+ setUp(subject$, 123);
+
+ expect(spy).toHaveBeenCalledTimes(1);
+});
+
+it('should subscribe to observable only once', () => {
+ const subject$ = new Subject();
+ const spy = jest.spyOn(subject$, 'subscribe');
+ expect(spy).not.toHaveBeenCalled();
+
+ setUp(subject$, 123);
+
+ expect(spy).toHaveBeenCalledTimes(1);
+
+ act(() => {
+ subject$.next('a');
+ });
+
+ act(() => {
+ subject$.next('b');
+ });
+
+ expect(spy).toHaveBeenCalledTimes(1);
+});
+
+it('should return updated value when observable changes', () => {
+ const subject$ = new Subject();
+ const { result } = setUp(subject$);
+ expect(result.current).toBeUndefined();
+
+ act(() => {
+ subject$.next('foo');
+ });
+ expect(result.current).toBe('foo');
+
+ act(() => {
+ subject$.next('bar');
+ });
+ expect(result.current).toBe('bar');
+});
+
+it('should unsubscribe from observable', () => {
+ const subject$ = new Subject();
+ const unsubscribeMock = jest.fn();
+ subject$.subscribe = jest.fn().mockReturnValue({
+ unsubscribe: unsubscribeMock,
+ });
+
+ const { unmount } = setUp(subject$);
+ expect(unsubscribeMock).not.toHaveBeenCalled();
+
+ act(() => {
+ subject$.next('foo');
+ });
+ expect(unsubscribeMock).not.toHaveBeenCalled();
+
+ act(() => {
+ subject$.next('bar');
+ });
+ expect(unsubscribeMock).not.toHaveBeenCalled();
+
+ unmount();
+ expect(unsubscribeMock).toHaveBeenCalledTimes(1);
+});
diff --git a/src/__tests__/useObservable.test.tsx b/src/__tests__/useObservable.test.tsx
deleted file mode 100644
index 4166c986..00000000
--- a/src/__tests__/useObservable.test.tsx
+++ /dev/null
@@ -1,107 +0,0 @@
-import * as React from 'react';
-import * as ReactDOM from 'react-dom';
-import { act, renderHook } from 'react-hooks-testing-library';
-import { Subject } from 'rxjs';
-import { useObservable } from '..';
-
-let container: HTMLDivElement | null;
-
-beforeEach(() => {
- container = document.createElement('div');
- document.body.appendChild(container);
-});
-
-afterEach(() => {
- document.body.removeChild(container!);
- container = null;
-});
-
-test('default initial value is undefined', () => {
- const subject$ = new Subject();
- const { result } = renderHook(() => useObservable(subject$));
-
- expect(result.current).toBe(undefined);
-});
-
-test('can specify initial value', () => {
- const subject$ = new Subject();
- const { result } = renderHook(() => useObservable(subject$, 123));
-
- expect(result.current).toBe(123);
-});
-
-test('returns the latest value of observables', () => {
- const subject$ = new Subject();
- const { result } = renderHook(() => useObservable(subject$, 123));
-
- act(() => {
- subject$.next(125);
- });
- expect(result.current).toBe(125);
-
- act(() => {
- subject$.next(300);
- subject$.next(400);
- });
- expect(result.current).toBe(400);
-});
-
-test('subscribes to observable only once', async () => {
- const subject = new Subject();
- const spy = jest.spyOn(subject, 'subscribe');
-
- expect(spy).toHaveBeenCalledTimes(0);
-
- const Demo = ({ obs }) => {
- const value = useObservable(obs);
- return <>{value}>;
- };
-
- ReactDOM.render(, container);
-
- expect(spy).toHaveBeenCalledTimes(1);
-
- await new Promise(r => setTimeout(r, 1));
- act(() => {
- subject.next('a');
- });
- await new Promise(r => setTimeout(r, 1));
- act(() => {
- subject.next('b');
- });
-
- expect(spy).toHaveBeenCalledTimes(1);
-});
-
-test('re-renders component as obsevable changes', async () => {
- const subject = new Subject();
-
- let cnt = 0;
- const Demo = ({ obs }) => {
- cnt++;
- const value = useObservable(obs);
- return <>{value}>;
- };
-
- ReactDOM.render(, container);
-
- await new Promise(r => setTimeout(r, 1));
- expect(cnt).toBe(1);
- expect(container.innerHTML).toBe('');
-
- act(() => {
- subject.next('a');
- });
-
- await new Promise(r => setTimeout(r, 1));
- expect(cnt).toBe(2);
- expect(container.innerHTML).toBe('a');
-
- act(() => {
- subject.next('b');
- });
-
- await new Promise(r => setTimeout(r, 1));
- expect(cnt).toBe(3);
- expect(container.innerHTML).toBe('b');
-});
diff --git a/src/__tests__/usePrevious.test.ts b/src/__tests__/usePrevious.test.ts
new file mode 100644
index 00000000..f6d63797
--- /dev/null
+++ b/src/__tests__/usePrevious.test.ts
@@ -0,0 +1,23 @@
+import { renderHook } from '@testing-library/react-hooks';
+import usePrevious from '../usePrevious';
+
+const setUp = () => renderHook(({ state }) => usePrevious(state), { initialProps: { state: 0 } });
+
+it('should return undefined on initial render', () => {
+ const { result } = setUp();
+
+ expect(result.current).toBeUndefined();
+});
+
+it('should always return previous state after each update', () => {
+ const { result, rerender } = setUp();
+
+ rerender({ state: 2 });
+ expect(result.current).toBe(0);
+
+ rerender({ state: 4 });
+ expect(result.current).toBe(2);
+
+ rerender({ state: 6 });
+ expect(result.current).toBe(4);
+});
diff --git a/src/__tests__/usePrevious.test.tsx b/src/__tests__/usePrevious.test.tsx
deleted file mode 100644
index 70713653..00000000
--- a/src/__tests__/usePrevious.test.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { cleanup, renderHook } from 'react-hooks-testing-library';
-import usePrevious from '../usePrevious';
-
-afterEach(cleanup);
-
-describe('usePrevious', () => {
- it('should be defined', () => {
- expect(usePrevious).toBeDefined();
- });
-
- const hook = renderHook(props => usePrevious(props), { initialProps: 0 });
-
- it('should return undefined on initial render', () => {
- expect(hook.result.current).toBe(undefined);
- });
-
- it('should return previous state after update', () => {
- hook.rerender(1);
- hook.rerender(2);
- expect(hook.result.current).toBe(1);
- });
-});
diff --git a/src/__tests__/useSetState.test.ts b/src/__tests__/useSetState.test.ts
new file mode 100644
index 00000000..684ba30b
--- /dev/null
+++ b/src/__tests__/useSetState.test.ts
@@ -0,0 +1,42 @@
+import { act, renderHook } from '@testing-library/react-hooks';
+import useSetState from '../useSetState';
+
+const setUp = (initialState?: object) => renderHook(() => useSetState(initialState));
+
+it('should init state and setter', () => {
+ const { result } = setUp({ foo: 'bar' });
+ const [state, setState] = result.current;
+
+ expect(state).toEqual({ foo: 'bar' });
+ expect(setState).toBeInstanceOf(Function);
+});
+
+it('should init empty state if not initial state provided', () => {
+ const { result } = setUp();
+
+ expect(result.current[0]).toEqual({});
+});
+
+it('should merge changes into current state when providing object', () => {
+ const { result } = setUp({ foo: 'bar', count: 1 });
+ const [state, setState] = result.current;
+
+ act(() => {
+ // @ts-ignore
+ setState({ count: state.count + 1, someBool: true });
+ });
+
+ expect(result.current[0]).toEqual({ foo: 'bar', count: 2, someBool: true });
+});
+
+it('should merge changes into current state when providing function', () => {
+ const { result } = setUp({ foo: 'bar', count: 1 });
+ const [, setState] = result.current;
+
+ act(() => {
+ // @ts-ignore
+ setState(prevState => ({ count: prevState.count + 1, someBool: true }));
+ });
+
+ expect(result.current[0]).toEqual({ foo: 'bar', count: 2, someBool: true });
+});
diff --git a/src/__tests__/useTitle.test.tsx b/src/__tests__/useTitle.test.tsx
index a98c5a13..b8cb626e 100644
--- a/src/__tests__/useTitle.test.tsx
+++ b/src/__tests__/useTitle.test.tsx
@@ -1,8 +1,6 @@
-import { cleanup, renderHook } from 'react-hooks-testing-library';
+import { renderHook } from '@testing-library/react-hooks';
import useTitle from '../useTitle';
-afterEach(cleanup);
-
describe('useTitle', () => {
it('should be defined', () => {
expect(useTitle).toBeDefined();
diff --git a/src/__tests__/useToggle.test.ts b/src/__tests__/useToggle.test.ts
new file mode 100644
index 00000000..adafdc3b
--- /dev/null
+++ b/src/__tests__/useToggle.test.ts
@@ -0,0 +1,83 @@
+import { act, renderHook } from '@testing-library/react-hooks';
+import useToggle from '../useToggle';
+
+const setUp = (initialValue: boolean) => renderHook(() => useToggle(initialValue));
+
+it('should init state to true', () => {
+ const { result } = setUp(true);
+
+ expect(result.current[0]).toBe(true);
+ expect(typeof result.current[1]).toBe('function');
+});
+
+it('should init state to false', () => {
+ const { result } = setUp(false);
+
+ expect(result.current[0]).toBe(false);
+ expect(result.current[1]).toBeInstanceOf(Function);
+});
+
+it('should set state to true', () => {
+ const { result } = setUp(false);
+ const [, toggle] = result.current;
+
+ expect(result.current[0]).toBe(false);
+
+ act(() => {
+ toggle(true);
+ });
+
+ expect(result.current[0]).toBe(true);
+});
+
+it('should set state to false', () => {
+ const { result } = setUp(true);
+ const [, toggle] = result.current;
+
+ expect(result.current[0]).toBe(true);
+
+ act(() => {
+ toggle(false);
+ });
+
+ expect(result.current[0]).toBe(false);
+});
+
+it('should toggle state from true', () => {
+ const { result } = setUp(true);
+ const [, toggle] = result.current;
+
+ act(() => {
+ toggle();
+ });
+
+ expect(result.current[0]).toBe(false);
+});
+
+it('should toggle state from false', () => {
+ const { result } = setUp(false);
+ const [, toggle] = result.current;
+
+ act(() => {
+ toggle();
+ });
+
+ expect(result.current[0]).toBe(true);
+});
+
+it('should ignore non-boolean parameters and toggle state', () => {
+ const { result } = setUp(true);
+ const [, toggle] = result.current;
+
+ act(() => {
+ toggle('string');
+ });
+
+ expect(result.current[0]).toBe(false);
+
+ act(() => {
+ toggle({});
+ });
+
+ expect(result.current[0]).toBe(true);
+});
diff --git a/src/__tests__/useToggle.test.tsx b/src/__tests__/useToggle.test.tsx
deleted file mode 100644
index bcf1d78f..00000000
--- a/src/__tests__/useToggle.test.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import { act, cleanup, renderHook } from 'react-hooks-testing-library';
-import useToggle from '../useToggle';
-
-afterEach(cleanup);
-
-describe('useToggle', () => {
- it('should be defined', () => {
- expect(useToggle).toBeDefined();
- });
-
- const hook = renderHook(props => useToggle(props), { initialProps: false });
-
- it('should return initial state on initial render', () => {
- expect(hook.result.current[0]).toBe(false);
- });
-
- it('should update state with correct value', () => {
- hook.rerender(true);
- expect(hook.result.current[0]).toBe(true);
-
- act(() => {
- hook.result.current[1](false);
- });
-
- expect(hook.result.current[0]).toBe(false);
- });
-
- // it('should toggle state without a value parameter', () => {
- // act(() => {
- // hook.result.current[1]();
- // });
-
- // expect(hook.result.current[0]).toBe(true);
- // });
-
- // it('should ignore non-boolean parameters', () => {
- // act(() => {
- // hook.result.current[1]('string');
- // });
-
- // expect(hook.result.current[0]).toBe(true);
-
- // act(() => {
- // hook.result.current[1]({});
- // });
-
- // expect(hook.result.current[0]).toBe(false);
- // });
-});
diff --git a/src/__tests__/useWindowSize.test.tsx b/src/__tests__/useWindowSize.test.tsx
index 9cc4be50..b3cb7fe5 100644
--- a/src/__tests__/useWindowSize.test.tsx
+++ b/src/__tests__/useWindowSize.test.tsx
@@ -1,4 +1,4 @@
-import { act, cleanup, renderHook } from 'react-hooks-testing-library';
+import { act, renderHook } from '@testing-library/react-hooks';
import useWindowSize from '../useWindowSize';
// simulate window resize
@@ -17,8 +17,6 @@ function fireResize(type, value) {
window.dispatchEvent(new Event('resize'));
}
-afterEach(cleanup);
-
describe('useWindowSize', () => {
it('should be defined', () => {
expect(useWindowSize).toBeDefined();
diff --git a/src/index.ts b/src/index.ts
index 3c4e7bc3..f196b68a 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -44,6 +44,7 @@ export { default as useMedia } from './useMedia';
export { default as useMediaDevices } from './useMediaDevices';
export { default as useMotion } from './useMotion';
export { default as useMount } from './useMount';
+export { default as useMountedState } from './useMountedState';
export { default as useMouse } from './useMouse';
export { default as useMouseHovered } from './useMouseHovered';
export { default as useNetwork } from './useNetwork';
diff --git a/src/useKeyboardJs.ts b/src/useKeyboardJs.ts
index c67d9f2f..3ae5cc46 100644
--- a/src/useKeyboardJs.ts
+++ b/src/useKeyboardJs.ts
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import useMount from './useMount';
-const useKeyboardJs = (combination: string) => {
+const useKeyboardJs = (combination: string | string[]) => {
const [state, set] = useState<[boolean, null | KeyboardEvent]>([false, null]);
const [keyboardJs, setKeyboardJs] = useState(null);
diff --git a/src/useMountedState.ts b/src/useMountedState.ts
new file mode 100644
index 00000000..6236d415
--- /dev/null
+++ b/src/useMountedState.ts
@@ -0,0 +1,15 @@
+import { useEffect, useRef } from 'react';
+
+export default function useMountedState(): () => boolean {
+ const mountedRef = useRef(false);
+
+ useEffect(() => {
+ mountedRef.current = true;
+
+ return () => {
+ mountedRef.current = false;
+ };
+ });
+
+ return () => mountedRef.current;
+}
diff --git a/yarn.lock b/yarn.lock
index d2de2751..e867b975 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1528,7 +1528,7 @@
dependencies:
regenerator-runtime "^0.13.2"
-"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5":
+"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5":
version "7.4.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.5.tgz#582bb531f5f9dc67d2fcb682979894f75e253f12"
integrity sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==
@@ -1986,14 +1986,6 @@
source-map "^0.6.1"
write-file-atomic "2.4.1"
-"@jest/types@^24.7.0":
- version "24.7.0"
- resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.7.0.tgz#c4ec8d1828cdf23234d9b4ee31f5482a3f04f48b"
- integrity sha512-ipJUa2rFWiKoBqMKP63Myb6h9+iT3FHRTF2M8OR6irxWzItisa8i4dcSg14IbvmXUnBlHBlUQPYUHWyX3UPpYA==
- dependencies:
- "@types/istanbul-lib-coverage" "^2.0.0"
- "@types/yargs" "^12.0.9"
-
"@jest/types@^24.8.0":
version "24.8.0"
resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.8.0.tgz#f31e25948c58f0abd8c845ae26fcea1491dea7ad"
@@ -2188,21 +2180,16 @@
into-stream "^4.0.0"
lodash "^4.17.4"
-"@sheerun/mutationobserver-shim@^0.3.2":
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#8013f2af54a2b7d735f71560ff360d3a8176a87b"
- integrity sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q==
-
-"@storybook/addon-actions@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.1.9.tgz#a515b62b109cb886ccd75ef2f5b12f8c27b43dd3"
- integrity sha512-h/csHPotBESyEUYlML3yyF2jUlDChB+u3TUNC3Ztzh/x7HzLqy88SL0INSIdY0dCBGx4TK5Gh+rMI7z28Hfdyw==
+"@storybook/addon-actions@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.1.10.tgz#8ed4272a6afc68f4a30372da2eeff414f0fe6ecd"
+ integrity sha512-njl2AHBGi27NvisOB8LFnWH/3RcyJT/CW7tl1cvV2j5FH2oBjq5MsjxKyJIcKwC677k1Wr8G8fw/zSEHrPpmgA==
dependencies:
- "@storybook/addons" "5.1.9"
- "@storybook/api" "5.1.9"
- "@storybook/components" "5.1.9"
- "@storybook/core-events" "5.1.9"
- "@storybook/theming" "5.1.9"
+ "@storybook/addons" "5.1.10"
+ "@storybook/api" "5.1.10"
+ "@storybook/components" "5.1.10"
+ "@storybook/core-events" "5.1.10"
+ "@storybook/theming" "5.1.10"
core-js "^3.0.1"
fast-deep-equal "^2.0.1"
global "^4.3.2"
@@ -2213,16 +2200,16 @@
react-inspector "^3.0.2"
uuid "^3.3.2"
-"@storybook/addon-knobs@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-5.1.9.tgz#74db07fd644b41e63274f8754fbfb18f43d4cf01"
- integrity sha512-7/bICMYtR9CaTqfZX1kT2pBOTLZo3HxeslyQKWWsWlNElV33Ym2d0PPL5eS36eFxG/ZOp6lQWIFhunNnlmP5xg==
+"@storybook/addon-knobs@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-5.1.10.tgz#f5d9f21090e28046169a0aa0418de59bd92c21fd"
+ integrity sha512-j5wXBIPGQxK+guFDAi8xNBdUnyQglhDplVoC9SswkSMarqtWq02TT+OLN2VSBgpvzHmhLUW3autjJGfmwP4ltQ==
dependencies:
- "@storybook/addons" "5.1.9"
- "@storybook/client-api" "5.1.9"
- "@storybook/components" "5.1.9"
- "@storybook/core-events" "5.1.9"
- "@storybook/theming" "5.1.9"
+ "@storybook/addons" "5.1.10"
+ "@storybook/client-api" "5.1.10"
+ "@storybook/components" "5.1.10"
+ "@storybook/core-events" "5.1.10"
+ "@storybook/theming" "5.1.10"
copy-to-clipboard "^3.0.8"
core-js "^3.0.1"
escape-html "^1.0.3"
@@ -2235,18 +2222,18 @@
react-lifecycles-compat "^3.0.4"
react-select "^2.2.0"
-"@storybook/addon-notes@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/addon-notes/-/addon-notes-5.1.9.tgz#7a19373589b4280b9a10a107a0357e63d2d56f5c"
- integrity sha512-UE+/RNysKRo2ZqCaqllwwV59x2S1laZjF4Netcm0nf9dKNcnqOoSHlTs0t4m8WpmfBQKAde4p+8fJGP2bCM+8A==
+"@storybook/addon-notes@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/addon-notes/-/addon-notes-5.1.10.tgz#92609d64401b962c5eaea0b5235474daa59a0d3f"
+ integrity sha512-S2I9W7n8xQKuJFxk3dF1RO1o648L+yX/JHR9j9rMHbre+5LuZ/Bev5WOIhHHthKllPqy1/Wxe9ECsGR7L4W2CQ==
dependencies:
- "@storybook/addons" "5.1.9"
- "@storybook/api" "5.1.9"
- "@storybook/client-logger" "5.1.9"
- "@storybook/components" "5.1.9"
- "@storybook/core-events" "5.1.9"
- "@storybook/router" "5.1.9"
- "@storybook/theming" "5.1.9"
+ "@storybook/addons" "5.1.10"
+ "@storybook/api" "5.1.10"
+ "@storybook/client-logger" "5.1.10"
+ "@storybook/components" "5.1.10"
+ "@storybook/core-events" "5.1.10"
+ "@storybook/router" "5.1.10"
+ "@storybook/theming" "5.1.10"
core-js "^3.0.1"
global "^4.3.2"
markdown-to-jsx "^6.9.3"
@@ -2254,37 +2241,37 @@
prop-types "^15.7.2"
util-deprecate "^1.0.2"
-"@storybook/addon-options@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/addon-options/-/addon-options-5.1.9.tgz#dc326b94c52a7ee27bf948fb7ca63a6ea3c9736d"
- integrity sha512-wQIUw5Uc/5iREtI9eh2wPMlNG0O7jxaTaxGS8Bs6zDzkwiLHcLJCrfk1lPXU6O8ExEzWHpaCmxth8GyfKj8Qtw==
+"@storybook/addon-options@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/addon-options/-/addon-options-5.1.10.tgz#ae6cf58744cee4ed161ffc537bc7e29a7c7337d0"
+ integrity sha512-DA6r84JYMJ5zACGdPQ7utpig8pUU1wywMMZt43k2IhxKBFcamw0Nmc80vvlTMM4mUu+mevH1ZiuzWxTZU7IcxA==
dependencies:
- "@storybook/addons" "5.1.9"
+ "@storybook/addons" "5.1.10"
core-js "^3.0.1"
util-deprecate "^1.0.2"
-"@storybook/addons@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.1.9.tgz#ecf218d08508b97ca5e6e0f1ed361081385bd3ff"
- integrity sha512-1bavbcS/NiE65DwyKj8c0DmWmz9VekOinB+has2Pqt2bOffZoZwVnbmepcz9hH3GUyvp5fQBYbxTEmTDvF2lLA==
+"@storybook/addons@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.1.10.tgz#2d8d8ca20b6d9b4652744f5fc00ead483f705435"
+ integrity sha512-M9b2PCp9RZxDC6wL7vVt2SCKCGXrrEAOsdpMvU569yB1zoUPEiiqElVDwb91O2eAGPnmd2yjImp90kOpKUW0EA==
dependencies:
- "@storybook/api" "5.1.9"
- "@storybook/channels" "5.1.9"
- "@storybook/client-logger" "5.1.9"
+ "@storybook/api" "5.1.10"
+ "@storybook/channels" "5.1.10"
+ "@storybook/client-logger" "5.1.10"
core-js "^3.0.1"
global "^4.3.2"
util-deprecate "^1.0.2"
-"@storybook/api@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.1.9.tgz#eec5b2f775392ce0803930104c6ce14fa4931e8b"
- integrity sha512-d1HhpOkW+706/WJ9lP5nCqOrp/icvbm0o+6jFFOGJ35AW5O9D8vDBxzvgMEO45jjN4I+rtbcNHQCxshSbPvP9w==
+"@storybook/api@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.1.10.tgz#5eeb5d9a7c268e5c89bd40c9a80293a7c72343b8"
+ integrity sha512-YeZe/71zLMmgT95IMAEZOc9AwL6Y23mWvkZMwFbkokxS9+bU/qmVlQ0B9c3JBzO3OSs7sXaRqyP1o3QkQgVsiw==
dependencies:
- "@storybook/channels" "5.1.9"
- "@storybook/client-logger" "5.1.9"
- "@storybook/core-events" "5.1.9"
- "@storybook/router" "5.1.9"
- "@storybook/theming" "5.1.9"
+ "@storybook/channels" "5.1.10"
+ "@storybook/client-logger" "5.1.10"
+ "@storybook/core-events" "5.1.10"
+ "@storybook/router" "5.1.10"
+ "@storybook/theming" "5.1.10"
core-js "^3.0.1"
fast-deep-equal "^2.0.1"
global "^4.3.2"
@@ -2298,33 +2285,33 @@
telejson "^2.2.1"
util-deprecate "^1.0.2"
-"@storybook/channel-postmessage@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.1.9.tgz#bd710ca74d7998a234c6b1f38009020d7c34bbc0"
- integrity sha512-H71PsnDKW81eflOS48Lv9yK4O8AcoqXL6ohsWvLdrHWIBsH4zpjOIhdWHtmAaT3hyfMy+l49DQ+uCHLECEt55g==
+"@storybook/channel-postmessage@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.1.10.tgz#e0a58461d56ef20a87d8bc4df1067e7afc76950e"
+ integrity sha512-kQZIwltN2cWDXluhCfdModFDK1LHV9ZhNQ1b/uD9vn1c65rQ9u7r4lRajCfS0X1dmAWqz48cBcEurAubNgmswg==
dependencies:
- "@storybook/channels" "5.1.9"
- "@storybook/client-logger" "5.1.9"
+ "@storybook/channels" "5.1.10"
+ "@storybook/client-logger" "5.1.10"
core-js "^3.0.1"
global "^4.3.2"
telejson "^2.2.1"
-"@storybook/channels@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.1.9.tgz#003cfca0b9f1ba6cf47ce68304aedd71bdb55e74"
- integrity sha512-R6i7859FsXgY9XFFErVe7gS37wGYpQEEWsO1LzUW7YptGuFTUa8yLgKkNkgfy7Zs61Xm+GiBq8PvS/CWxjotPw==
+"@storybook/channels@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.1.10.tgz#04fd35c05032c675f7816ea1ca873c1a0415c6d9"
+ integrity sha512-w7n/bV1BLu51KI1eLc75lN9H1ssBc3PZMXk88GkMiKyBVRzPlJA5ixnzH86qwYGReE0dhRpsgHXZ5XmoKaVmPA==
dependencies:
core-js "^3.0.1"
-"@storybook/client-api@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.1.9.tgz#b598efe4ab07bffaeb4cb9e30ed9c21add739df1"
- integrity sha512-J5HDtOS7x5YRpF/CMiHdxywV5NIh1i/03Xh2RhG15lmPy87VStIGpLzhF71uCRPLEJinYelcjuXRNAJgRzUOlg==
+"@storybook/client-api@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.1.10.tgz#a10f028f2d33d044e5c3b3daea5d8375323e6a66"
+ integrity sha512-v2PqiNUhwDlVDLYL94f6LFjdYMToTpuwWh9aeqzt/4PAJUnIcA+2P8+qXiYdJTqQy/u7P72HFMlc9Ru4tl3QFg==
dependencies:
- "@storybook/addons" "5.1.9"
- "@storybook/client-logger" "5.1.9"
- "@storybook/core-events" "5.1.9"
- "@storybook/router" "5.1.9"
+ "@storybook/addons" "5.1.10"
+ "@storybook/client-logger" "5.1.10"
+ "@storybook/core-events" "5.1.10"
+ "@storybook/router" "5.1.10"
common-tags "^1.8.0"
core-js "^3.0.1"
eventemitter3 "^3.1.0"
@@ -2334,20 +2321,20 @@
memoizerific "^1.11.3"
qs "^6.6.0"
-"@storybook/client-logger@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.1.9.tgz#87e2f7578416269adeccd407584010bc353f14d3"
- integrity sha512-1+Otcn0EFgWNviDPNCR5LtUViADlboz9fmpZc7UY7bgaY5FVNIUO01E4T43tO7fduiRZoEvdltwTuQRm260Vjw==
+"@storybook/client-logger@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.1.10.tgz#f83a8717924dd222e0a6df82ae74701f27e0bb35"
+ integrity sha512-vB1NoFWRTgcERwodhbgoDwI00eqU8++nXI7GhMS1CY8haZaSp3gyKfHRWyfH+M+YjQuGBRUcvIk4gK6OtSrDOw==
dependencies:
core-js "^3.0.1"
-"@storybook/components@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.1.9.tgz#2a5258780fff07172d103287759946dbb4b13e2d"
- integrity sha512-F4xcRlifSAfqkuFWtCKRvQDahXyfWBWV2Wa+kYy4YGwEfm3kKtIHVlgdgARL22g9BdYpRFEOJ+42juOu5YvIeQ==
+"@storybook/components@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.1.10.tgz#4b6436f0b5bb2483fb231bee263d173a9ed7d241"
+ integrity sha512-QUQeeQp1xNWiL4VlxFAea0kqn2zvBfmfPlUddOFO9lBhT6pVy0xYPjXjbTVWjVcYzZpyUNWw5GplqrR5jhlaCA==
dependencies:
- "@storybook/client-logger" "5.1.9"
- "@storybook/theming" "5.1.9"
+ "@storybook/client-logger" "5.1.10"
+ "@storybook/theming" "5.1.10"
core-js "^3.0.1"
global "^4.3.2"
markdown-to-jsx "^6.9.1"
@@ -2365,32 +2352,32 @@
recompose "^0.30.0"
simplebar-react "^1.0.0-alpha.6"
-"@storybook/core-events@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.1.9.tgz#441a6297e2ccfa743e15d1db1f4ac445b91f40d8"
- integrity sha512-jHe2uyoLj9i6fntHtOj5azfGdLOb75LF0e1xXE8U2SX7Zp3uwbLAcfJ+dPStdc/q+f/wBiip3tH1dIjaNuUiMw==
+"@storybook/core-events@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.1.10.tgz#5aed88c572036b6bd6dfff28976ee96e6e175d7a"
+ integrity sha512-Lvu/rNcgS+XCkQKSGdNpUSWjpFF9AOSHPXsvkwHbRwJYdMDn3FznlXfDUiubOWtsziXHB6vl3wkKDlH+ckb32Q==
dependencies:
core-js "^3.0.1"
-"@storybook/core@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.1.9.tgz#8b30507676531fd41ac333b7c71b1c0db6b8da35"
- integrity sha512-P3aavCnl3Cl3WMXVERjQqnqV1Z8tN0tyOTqqiGb1fMxITSE8uZNvp33Dl0K3jr1PBl9trW+2t7eHH4h0sguLlQ==
+"@storybook/core@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.1.10.tgz#53d23d07716aa2721e1572d44a7f05967d7da39e"
+ integrity sha512-zkNjufOFrLpFpmr73F/gaJh0W0vWqXIo5zrKvQt1LqmMeCU/v8MstHi4XidlK43UpeogfaXl5tjNCQDO/bd0Dw==
dependencies:
"@babel/plugin-proposal-class-properties" "^7.3.3"
"@babel/plugin-proposal-object-rest-spread" "^7.3.2"
"@babel/plugin-syntax-dynamic-import" "^7.2.0"
"@babel/plugin-transform-react-constant-elements" "^7.2.0"
"@babel/preset-env" "^7.4.5"
- "@storybook/addons" "5.1.9"
- "@storybook/channel-postmessage" "5.1.9"
- "@storybook/client-api" "5.1.9"
- "@storybook/client-logger" "5.1.9"
- "@storybook/core-events" "5.1.9"
- "@storybook/node-logger" "5.1.9"
- "@storybook/router" "5.1.9"
- "@storybook/theming" "5.1.9"
- "@storybook/ui" "5.1.9"
+ "@storybook/addons" "5.1.10"
+ "@storybook/channel-postmessage" "5.1.10"
+ "@storybook/client-api" "5.1.10"
+ "@storybook/client-logger" "5.1.10"
+ "@storybook/core-events" "5.1.10"
+ "@storybook/node-logger" "5.1.10"
+ "@storybook/router" "5.1.10"
+ "@storybook/theming" "5.1.10"
+ "@storybook/ui" "5.1.10"
airbnb-js-shims "^1 || ^2"
autoprefixer "^9.4.9"
babel-plugin-add-react-displayname "^0.0.5"
@@ -2444,10 +2431,10 @@
webpack-dev-middleware "^3.7.0"
webpack-hot-middleware "^2.25.0"
-"@storybook/node-logger@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.1.9.tgz#4aacf0096811fde1639fc9d1d2d521f7220dd4be"
- integrity sha512-rcSuI5n53hDMHW83gl5TR0Yn885/i2XY0AzX1DsbTeGOl3x5LhrCSZsZWetKGcx7zsO4n7o5mQszLuN1JlyE8A==
+"@storybook/node-logger@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.1.10.tgz#92c80b46177687cd8fda1f93a055c22711984154"
+ integrity sha512-Z4UKh7QBOboQhUF5S/dKOx3OWWCNZGwYu8HZa/O+P68+XnQDhuZCYwqWG49xFhZd0Jb0W9gdUL2mWJw5POG9PA==
dependencies:
chalk "^2.4.2"
core-js "^3.0.1"
@@ -2455,16 +2442,16 @@
pretty-hrtime "^1.0.3"
regenerator-runtime "^0.12.1"
-"@storybook/react@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/react/-/react-5.1.9.tgz#4052f4b88e91d5a823bb9cbb61104c530fcfb1a1"
- integrity sha512-Byykpsttf6p2jv3LvqFtntEYfbUZSNTts0TjcZHNsHoUGmT7/M1PyqTeB7JUcYUNwSgdACY8FbowCrwZwDJDWQ==
+"@storybook/react@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/react/-/react-5.1.10.tgz#a5cf2b7d086e121c969d34100fb03fcfdc74cbed"
+ integrity sha512-wWy9l83KgbP8P2A8AbkwExEAdA0iznb4jEnCGzP1hAv8Q5LmL3MLPb1dIZqhWrg+E2m3tZei+7A7qu2Q8/cLLw==
dependencies:
"@babel/plugin-transform-react-constant-elements" "^7.2.0"
"@babel/preset-flow" "^7.0.0"
"@babel/preset-react" "^7.0.0"
- "@storybook/core" "5.1.9"
- "@storybook/node-logger" "5.1.9"
+ "@storybook/core" "5.1.10"
+ "@storybook/node-logger" "5.1.10"
"@svgr/webpack" "^4.0.3"
babel-plugin-add-react-displayname "^0.0.5"
babel-plugin-named-asset-import "^0.3.1"
@@ -2481,10 +2468,10 @@
semver "^6.0.0"
webpack "^4.33.0"
-"@storybook/router@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.1.9.tgz#8cd97bea4f2acf8ec5f6694d06fb0633dde33417"
- integrity sha512-eAmeerE/OTIwCV7WBnb1BPINVN1GTSMsUXLNWpqSISuyWJ+NZAJlObFkvXoc57QSQlv0cvXlm1FMkmRt8ku1Hw==
+"@storybook/router@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.1.10.tgz#d3cffd3f1105eb665882f389746ccabbb98c3c16"
+ integrity sha512-BdG6/essPZFHCP2ewCG0gYFQfmuuTSHXAB5fd/rwxLSYj1IzNznC5OxkvnSaTr4rgoxxaW/z1hbN1NuA0ivlFA==
dependencies:
"@reach/router" "^1.2.1"
core-js "^3.0.1"
@@ -2492,14 +2479,14 @@
memoizerific "^1.11.3"
qs "^6.6.0"
-"@storybook/theming@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.1.9.tgz#c425f5867fae0db79e01112853b1808332a5f1a2"
- integrity sha512-4jIFJwTWVf9tsv27noLoFHlKC2Jl9DHV3q+rxGPU8bTNbufCu4oby82SboO5GAKuS3eu1cxL1YY9pYad9WxfHg==
+"@storybook/theming@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.1.10.tgz#f9bd519cdf9cccf730656e3f5fd56a339dd07c9f"
+ integrity sha512-5cN1lmdVUwAR8U3T49Lfb8JW5RBvxBSPGZpUmbLGz1zi0tWBJgYXoGtw4RbTBjV9kCQOXkHGH12AsdDxHh931w==
dependencies:
"@emotion/core" "^10.0.9"
"@emotion/styled" "^10.0.7"
- "@storybook/client-logger" "5.1.9"
+ "@storybook/client-logger" "5.1.10"
common-tags "^1.8.0"
core-js "^3.0.1"
deep-object-diff "^1.1.0"
@@ -2510,19 +2497,19 @@
prop-types "^15.7.2"
resolve-from "^5.0.0"
-"@storybook/ui@5.1.9":
- version "5.1.9"
- resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.1.9.tgz#406667469e6dbdf320086647d8d80776bb051a51"
- integrity sha512-guzKv4VYM+06BzMXeO3QqlX0IwUHyeS6lwdPCL8Oy2V4Gi2IYHHiD6Hr1NgnBO18j9luxE38f4Ii7gEIzXMFbQ==
+"@storybook/ui@5.1.10":
+ version "5.1.10"
+ resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.1.10.tgz#4262b1b09efa43d125d694452ae879b89071edd1"
+ integrity sha512-ezkoVtzoKh93z2wzkqVIqyrIzTkj8tizgAkoPa7mUAbLCxu6LErHITODQoyEiJWI4Epy3yU9GYXFWwT71hdwsA==
dependencies:
- "@storybook/addons" "5.1.9"
- "@storybook/api" "5.1.9"
- "@storybook/channels" "5.1.9"
- "@storybook/client-logger" "5.1.9"
- "@storybook/components" "5.1.9"
- "@storybook/core-events" "5.1.9"
- "@storybook/router" "5.1.9"
- "@storybook/theming" "5.1.9"
+ "@storybook/addons" "5.1.10"
+ "@storybook/api" "5.1.10"
+ "@storybook/channels" "5.1.10"
+ "@storybook/client-logger" "5.1.10"
+ "@storybook/components" "5.1.10"
+ "@storybook/core-events" "5.1.10"
+ "@storybook/router" "5.1.10"
+ "@storybook/theming" "5.1.10"
copy-to-clipboard "^3.0.8"
core-js "^3.0.1"
core-js-pure "^3.0.1"
@@ -2655,6 +2642,15 @@
"@svgr/plugin-svgo" "^4.0.3"
loader-utils "^1.1.0"
+"@testing-library/react-hooks@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-1.1.0.tgz#14b6b5c7c3d0e2cb3e55e9cbb248b44321641c64"
+ integrity sha512-piE/ceQoNf134FFVXBABDbttBJ8eLPD4eg7zIciVJv92RyvoIsBHCvvG8Vd4IG5pyuWYrkLsZTO8ucZBwa4twA==
+ dependencies:
+ "@babel/runtime" "^7.4.2"
+ "@types/react" "^16.8.22"
+ "@types/react-test-renderer" "^16.8.2"
+
"@types/babel__core@^7.1.0":
version "7.1.0"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.0.tgz#710f2487dda4dcfd010ca6abb2b4dc7394365c51"
@@ -2732,10 +2728,10 @@
resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89"
integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==
-"@types/jest@24.0.15":
- version "24.0.15"
- resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.15.tgz#6c42d5af7fe3b44ffff7cc65de7bf741e8fa427f"
- integrity sha512-MU1HIvWUme74stAoc3mgAi+aMlgKOudgEvQDIm1v4RkrDudBh1T+NFp5sftpBAdXdx1J0PbdpJ+M2EsSOi1djA==
+"@types/jest@24.0.16":
+ version "24.0.16"
+ resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.16.tgz#8d3e406ec0f0dc1688d6711af3062ff9bd428066"
+ integrity sha512-JrAiyV+PPGKZzw6uxbI761cHZ0G7QMOHXPhtSpcl08rZH6CswXaaejckn3goFKmF7M3nzEoJ0lwYCbqLMmjziQ==
dependencies:
"@types/jest-diff" "*"
@@ -2764,6 +2760,13 @@
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==
+"@types/react-test-renderer@^16.8.2":
+ version "16.8.3"
+ resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-16.8.3.tgz#b6ca14d5fe4c742fd6d68ef42d45e3b5c6dd470a"
+ integrity sha512-vEEYh6gFk3jkPHqRe7N5CxWA+yb92hCZxNyhq/1Wj3mClqVWLJYakJDMp3iFmntCgEq96m68N9Oad3wOHm+pdQ==
+ dependencies:
+ "@types/react" "*"
+
"@types/react-wait@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@types/react-wait/-/react-wait-0.3.0.tgz#6f7ef17571a17e72c7864ede8cf7d3aa525a005e"
@@ -2779,6 +2782,14 @@
"@types/prop-types" "*"
csstype "^2.2.0"
+"@types/react@^16.8.22":
+ version "16.8.24"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.24.tgz#8d1ea1fcbfa214220da3d3c04e506f1077b0deac"
+ integrity sha512-VpFHUoD37YNY2+lr/+c7qL/tZsIU/bKuskUF3tmGUArbxIcQdb5j3zvo4cuuzu2A6UaVmVn7sJ4PgWYNFEBGzg==
+ dependencies:
+ "@types/prop-types" "*"
+ csstype "^2.2.0"
+
"@types/stack-utils@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
@@ -5697,16 +5708,6 @@ dom-serializer@0:
domelementtype "~1.1.1"
entities "~1.1.1"
-dom-testing-library@^3.19.0:
- version "3.19.0"
- resolved "https://registry.yarnpkg.com/dom-testing-library/-/dom-testing-library-3.19.0.tgz#652ade2cd93ae98beb52b2878eeb9420d7599832"
- integrity sha512-gkGXP5GevcjC24Tk6Y6RwrZ7Nz0Ul4bchXV4yHLcnMidMp/EdBCvtHEgHTsZ2yZ4DhUpLowGbJv/1u1Z7bPvtw==
- dependencies:
- "@babel/runtime" "^7.3.4"
- "@sheerun/mutationobserver-shim" "^0.3.2"
- pretty-format "^24.5.0"
- wait-for-expect "^1.1.0"
-
dom-walk@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
@@ -6871,10 +6872,10 @@ getpass@^0.1.1:
dependencies:
assert-plus "^1.0.0"
-gh-pages@2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/gh-pages/-/gh-pages-2.0.1.tgz#aefe47a43b8d9d2aa3130576b33fe95641e29a2f"
- integrity sha512-uFlk3bukljeiWKQ2XvPfjcSi/ou7IfoDf2p+Fj672saLAr8bnOdFVqI/JSgrSgInKpCg5BksxEwGUl++dbg8Dg==
+gh-pages@2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/gh-pages/-/gh-pages-2.1.0.tgz#dcf519825d77d3a3ee78763076f4158403fc88c4"
+ integrity sha512-QmV1fh/2W5GZkfoLsG4g6dRTWiNYuCetMQmm8CL6Us8JVnAufYtS0uJPD8NYogmNB4UZzdRG44uPAL+jcBzEwQ==
dependencies:
async "^2.6.1"
commander "^2.18.0"
@@ -7373,10 +7374,10 @@ humanize-url@^1.0.0:
normalize-url "^1.0.0"
strip-url-auth "^1.0.0"
-husky@3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/husky/-/husky-3.0.1.tgz#06152c28e129622b05fa09c494209de8cf2dfb59"
- integrity sha512-PXBv+iGKw23GHUlgELRlVX9932feFL407/wHFwtsGeArp0dDM4u+/QusSQwPKxmNgjpSL+ustbOdQ2jetgAZbA==
+husky@3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/husky/-/husky-3.0.2.tgz#e78fd2ae16edca59fc88e56aeb8d70acdcc1c082"
+ integrity sha512-WXCtaME2x0o4PJlKY4ap8BzLA+D0zlvefqAvLCPriOOu+x0dpO5uc5tlB7CY6/0SE2EESmoZsj4jW5D09KrJoA==
dependencies:
chalk "^2.4.2"
cosmiconfig "^5.2.1"
@@ -9338,13 +9339,13 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
-markdown-loader@5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/markdown-loader/-/markdown-loader-5.0.0.tgz#d6af0f2d5fe7713fb692cbd85b547ff0ef26baa8"
- integrity sha512-CnRuBrTQNJ2VNlyfPJl+14QU6Sfscse4M6TpwuY0KDuCafMHv6vAcVYInphXFtdvtvjG5kMpF+PwN6CWke0M3A==
+markdown-loader@5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/markdown-loader/-/markdown-loader-5.1.0.tgz#4efd5006b1514ca966141c661a47e542a9836e6e"
+ integrity sha512-xtQNozLEL+55ZSPTNwro8epZqf1h7HjAZd/69zNe8lbckDiGVHeLQm849bXzocln2pwRK2A/GrW/7MAmwjcFog==
dependencies:
loader-utils "^1.2.3"
- marked "^0.6.0"
+ marked "^0.7.0"
markdown-to-jsx@^6.9.1:
version "6.9.2"
@@ -9374,10 +9375,10 @@ marked-terminal@^3.2.0:
node-emoji "^1.4.1"
supports-hyperlinks "^1.0.1"
-marked@^0.6.0:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/marked/-/marked-0.6.1.tgz#a63addde477bca9613028de4b2bc3629e53a0562"
- integrity sha512-+H0L3ibcWhAZE02SKMqmvYsErLo4EAVJxu5h3bHBBDvvjeWXtl92rGUSBYHL2++5Y+RSNgl8dYOAXcYe7lp1fA==
+marked@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e"
+ integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==
material-colors@^1.2.1:
version "1.2.6"
@@ -11307,16 +11308,6 @@ pretty-error@^2.1.1:
renderkid "^2.0.1"
utila "~0.4"
-pretty-format@^24.5.0:
- version "24.7.0"
- resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.7.0.tgz#d23106bc2edcd776079c2daa5da02bcb12ed0c10"
- integrity sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==
- dependencies:
- "@jest/types" "^24.7.0"
- ansi-regex "^4.0.0"
- ansi-styles "^3.2.0"
- react-is "^16.8.4"
-
pretty-format@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2"
@@ -11759,14 +11750,6 @@ react-helmet-async@^1.0.2:
react-fast-compare "2.0.4"
shallowequal "1.1.0"
-react-hooks-testing-library@0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/react-hooks-testing-library/-/react-hooks-testing-library-0.4.1.tgz#481b960d647d3cc7c8bbaf410014daa8ce0b1360"
- integrity sha512-ogmlyW7ycZe3+HIk1Y+FUV5ExpZwLi/RlF1qGLLbTkUdaAsGgp9fSF+wFNWi2KNKBTWG0FkkqOrLkcwq0z3ebQ==
- dependencies:
- "@babel/runtime" "^7.4.2"
- react-testing-library "^6.0.3"
-
react-hotkeys@2.0.0-pre4:
version "2.0.0-pre4"
resolved "https://registry.yarnpkg.com/react-hotkeys/-/react-hotkeys-2.0.0-pre4.tgz#a1c248a51bdba4282c36bf3204f80d58abc73333"
@@ -11795,7 +11778,7 @@ react-is@^16.7.0, react-is@^16.8.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.4.tgz#90f336a68c3a29a096a3d648ab80e87ec61482a2"
integrity sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA==
-react-is@^16.8.4:
+react-is@^16.8.4, react-is@^16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
@@ -11868,13 +11851,15 @@ react-syntax-highlighter@^8.0.1:
prismjs "^1.8.4"
refractor "^2.4.1"
-react-testing-library@^6.0.3:
- version "6.1.2"
- resolved "https://registry.yarnpkg.com/react-testing-library/-/react-testing-library-6.1.2.tgz#f6bba6eeecedac736eb00b22b4c70bae04535a4f"
- integrity sha512-z69lhRDGe7u/NOjDCeFRoe1cB5ckJ4656n0tj/Fdcr6OoBUu7q9DBw0ftR7v5i3GRpdSWelnvl+feZFOyXyxwg==
+react-test-renderer@^16.8.6:
+ version "16.8.6"
+ resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.6.tgz#188d8029b8c39c786f998aa3efd3ffe7642d5ba1"
+ integrity sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==
dependencies:
- "@babel/runtime" "^7.4.2"
- dom-testing-library "^3.19.0"
+ object-assign "^4.1.1"
+ prop-types "^15.6.2"
+ react-is "^16.8.6"
+ scheduler "^0.13.6"
react-textarea-autosize@^7.1.0:
version "7.1.0"
@@ -12643,10 +12628,10 @@ select@^1.1.2:
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
-semantic-release@15.13.18:
- version "15.13.18"
- resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-15.13.18.tgz#72e284c6f7cb7817e1aaaa0a9d73600a9447d146"
- integrity sha512-JtfdrhF1zRm91nJH/Rg3taftbWGwktJqqrJJdbmZGKYx63cfC4PoaS0jxRifGJUdmmgW/Kxz8f5bhtB+p1bu8A==
+semantic-release@15.13.19:
+ version "15.13.19"
+ resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-15.13.19.tgz#d1d05b3516fb8701d81f4e6b9be42bafffef13cb"
+ integrity sha512-6eqqAmzGaJWgP5R5IkWIQK9is+cWUp/A+pwzxf/YaG1hJv1eD25klUP7Y0fedsPOxxI8eLuDUVlEs7U8SOlK0Q==
dependencies:
"@semantic-release/commit-analyzer" "^6.1.0"
"@semantic-release/error" "^2.2.0"
@@ -12665,7 +12650,7 @@ semantic-release@15.13.18:
hook-std "^2.0.0"
hosted-git-info "^2.7.1"
lodash "^4.17.4"
- marked "^0.6.0"
+ marked "^0.7.0"
marked-terminal "^3.2.0"
p-locate "^4.0.0"
p-reduce "^2.0.0"
@@ -14402,11 +14387,6 @@ w3c-hr-time@^1.0.1:
dependencies:
browser-process-hrtime "^0.1.2"
-wait-for-expect@^1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-1.1.1.tgz#9cd10e07d52810af9e0aaf509872e38f3c3d81ae"
- integrity sha512-vd9JOqqEcBbCDhARWhW85ecjaEcfBLuXgVBqatfS3iw6oU4kzAcs+sCNjF+TC9YHPImCW7ypsuQc+htscIAQCw==
-
walker@^1.0.7, walker@~1.0.5:
version "1.0.7"
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"