diff --git a/README.md b/README.md index 5eb1ef5e..053443eb 100644 --- a/README.md +++ b/README.md @@ -64,28 +64,28 @@ const useTheme = (initialTheme) => { } // useTheme.test.js -import { useHook, cleanup } from 'react-hooks-testing-library' +import { testHook, cleanup, act } from 'react-hooks-testing-library' describe('custom hook tests', () => { afterEach(cleanup) test('should use theme', () => { - const { getCurrentValue } = useHook(() => useTheme('light')) + const { result } = testHook(() => useTheme('light')) - const theme = getCurrentValue() + const theme = result.current expect(theme.primaryLight).toBe('#FFFFFF') expect(theme.primaryDark).toBe('#000000') }) test('should update theme', () => { - const { getCurrentValue, act } = useHook(() => useTheme('light')) + const { result } = testHook(() => useTheme('light')) - const { toggleTheme } = getCurrentValue() + const { toggleTheme } = result.current act(() => toggleTheme()) - const theme = getCurrentValue() + const theme = result.current expect(theme.primaryLight).toBe('#000000') expect(theme.primaryDark).toBe('#FFFFFF') @@ -97,11 +97,13 @@ describe('custom hook tests', () => { dark: { primaryLight: '#CCBBAA', primaryDark: '#AABBCC' } } - const { getCurrentValue, addContextProvider } = useHook(() => useTheme('light')) + const wrapper = ({ children }) => ( + {children} + ) - addContextProvider(ThemesContext, { value: customThemes }) + const { result } = testHook(() => useTheme('light'), { wrapper }) - const theme = getCurrentValue() + const theme = result.current expect(theme.primaryLight).toBe('#AABBCC') expect(theme.primaryDark).toBe('#CCBBAA') diff --git a/package-lock.json b/package-lock.json index cc4d95c3..d0d0ecb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-hooks-testing-library", - "version": "0.2.4", + "version": "0.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -32,22 +32,22 @@ } }, "@babel/core": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.2.2.tgz", - "integrity": "sha512-59vB0RWt09cAct5EIe58+NzGP4TFSD3Bz//2/ELy3ZeTeKF6VTD1AXlH8BGGbCX0PuobZBsIzO7IAI9PH67eKw==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.3.3.tgz", + "integrity": "sha512-w445QGI2qd0E0GlSnq6huRZWPMmQGCp5gd5ZWS4hagn0EiwzxD5QMFkpchyusAyVC1n27OKXzQ0/88aVU9n4xQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.2.2", + "@babel/generator": "^7.3.3", "@babel/helpers": "^7.2.0", - "@babel/parser": "^7.2.2", + "@babel/parser": "^7.3.3", "@babel/template": "^7.2.2", "@babel/traverse": "^7.2.2", - "@babel/types": "^7.2.2", + "@babel/types": "^7.3.3", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" @@ -71,14 +71,14 @@ } }, "@babel/generator": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.2.tgz", - "integrity": "sha512-f3QCuPppXxtZOEm5GWPra/uYUjmNQlu9pbAD8D/9jze4pTY83rTtB1igTBSwvkeNlC5gR24zFFkz+2WHLFQhqQ==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.3.tgz", + "integrity": "sha512-aEADYwRRZjJyMnKN7llGIlircxTCofm3dtV5pmY6ob18MSIuipHpA2yZWkPlycwu5HJcx/pADS3zssd8eY7/6A==", "dev": true, "requires": { - "@babel/types": "^7.3.2", + "@babel/types": "^7.3.3", "jsesc": "^2.5.1", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -308,9 +308,9 @@ } }, "@babel/parser": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.2.tgz", - "integrity": "sha512-QzNUC2RO1gadg+fs21fi0Uu0OuGNzRKEmgCxoLNzbCdoprLwjfmZwzUrpUNfJPaVRwBpDY47A17yYEGWyRelnQ==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.3.tgz", + "integrity": "sha512-xsH1CJoln2r74hR+y7cg2B5JCPaTh+Hd+EbBRk9nWGSNspuo6krjhX0Om6RnRQuIvFq8wVXCLKH3kwKDYhanSg==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -450,9 +450,9 @@ } }, "@babel/plugin-transform-classes": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.2.2.tgz", - "integrity": "sha512-gEZvgTy1VtcDOaQty1l10T3jQmJKlNVxLDCs+3rCVPr6nMkODLELxViq5X9l+rfxbie3XrfrMCYYY6eX3aOcOQ==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.3.3.tgz", + "integrity": "sha512-n0CLbsg7KOXsMF4tSTLCApNMoXk0wOPb0DYfsOO1e7SfIb9gOyfbpKI2MZ+AXfqvlfzq2qsflJ1nEns48Caf2w==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", @@ -611,9 +611,9 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.2.0.tgz", - "integrity": "sha512-kB9+hhUidIgUoBQ0MsxMewhzr8i60nMa2KgeJKQWYrqQpqcBYtnpR+JgkadZVZoaEZ/eKu9mclFaVwhRpLNSzA==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.3.3.tgz", + "integrity": "sha512-IrIP25VvXWu/VlBWTpsjGptpomtIkYrN/3aDp4UKm7xK6UxZY88kcJ1UwETbzHAlwN21MnNfwlar0u8y3KpiXw==", "dev": true, "requires": { "@babel/helper-call-delegate": "^7.1.0", @@ -846,13 +846,13 @@ } }, "@babel/types": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.2.tgz", - "integrity": "sha512-3Y6H8xlUlpbGR+XvawiH0UXehqydTmNmEpozWcXymqwcrwYAl5KMvKtQ+TF6f6E08V6Jur7v/ykdDSF+WDEIXQ==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.3.tgz", + "integrity": "sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, @@ -960,9 +960,9 @@ "dev": true }, "acorn": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.7.tgz", - "integrity": "sha512-HNJNgE60C9eOTgn974Tlp3dpLZdUr+SoxxDwPaY9J/kDNOLQTkaDgwBUXAF4SSsrAwD9RpdxuHK/EbuF+W9Ahw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.0.tgz", + "integrity": "sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw==", "dev": true }, "acorn-globals": { @@ -988,9 +988,9 @@ "dev": true }, "ajv": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz", - "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -1006,9 +1006,9 @@ "dev": true }, "all-contributors-cli": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/all-contributors-cli/-/all-contributors-cli-5.11.0.tgz", - "integrity": "sha512-+xL38RoYh4caJVlxqGsr7jzV5pXLquIEa5AsfUi6/8joOT1m18AKK0qwt3xgOG/P/zOdcs/PBLjmm8NqXh5T+g==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/all-contributors-cli/-/all-contributors-cli-6.1.1.tgz", + "integrity": "sha512-4Bzx/dphSydqnOostzVCxYStkfaz0AsXq3Spyuw3vAEOckr/jgHmwIXWZ6/Vjqdmc/TA5Ue2P2UlqknA/Ewq4A==", "dev": true, "requires": { "@babel/runtime": "^7.2.0", @@ -1164,12 +1164,12 @@ "dev": true }, "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "async-each": { @@ -1312,9 +1312,9 @@ "dev": true }, "babel-plugin-module-resolver": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.1.3.tgz", - "integrity": "sha512-QRfA8b2H7l9uSElLwS0rHoPhjPhgpncKUvrn42tJpdCoJ3IS6J+m4mp5FtnRoXHry3ZYJ2SMLLG/REikQA6tjg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.2.0.tgz", + "integrity": "sha512-tjR0GvSndzPew/Iayf4uICWZqjBwnlMWjSx6brryfQ81F9rxBVqwDJtFCV8oOs0+vJeefK9TmdZtkIFdFe1UnA==", "dev": true, "requires": { "find-babel-config": "^1.1.0", @@ -1598,9 +1598,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000935", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000935.tgz", - "integrity": "sha512-1Y2uJ5y56qDt3jsDTdBHL1OqiImzjoQcBG6Yl3Qizq8mcc2SgCFpi+ZwLLqkztYnk9l87IYqRlNBnPSOTbFkXQ==", + "version": "1.0.30000938", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000938.tgz", + "integrity": "sha512-ekW8NQ3/FvokviDxhdKLZZAx7PptXNwxKgXtnR5y+PR3hckwuP3yJ1Ir+4/c97dsHNqtAyfKUGdw8P4EYzBNgw==", "dev": true }, "capture-exit": { @@ -1636,9 +1636,9 @@ "dev": true }, "chokidar": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.0.tgz", - "integrity": "sha512-5t6G2SH8eO6lCvYOoUpaRnF5Qfd//gd7qJAkwRUw9qlGVkiQ13uwQngqbWWaurOsaAm9+kUGbITADxt6H0XFNQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.1.tgz", + "integrity": "sha512-gfw3p2oQV2wEt+8VuMlNsPjCxDxvvgnm/kz+uATu805mWVF8IJN7uz9DN7iBz+RMJISmiVbCOBFs9qBGMjtPfQ==", "dev": true, "optional": true, "requires": { @@ -1889,9 +1889,9 @@ "dev": true }, "core-js": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.3.tgz", - "integrity": "sha512-l00tmFFZOBHtYhN4Cz7k32VM7vTn3rE2ANjQDxdEN6zmXZ/xq1jQuutnmHvMG1ZJ7xd72+TA5YpUK8wz3rWsfQ==", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", + "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==", "dev": true }, "core-util-is": { @@ -1950,9 +1950,9 @@ "dev": true }, "cssstyle": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz", - "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.1.tgz", + "integrity": "sha512-7DYm8qe+gPx/h77QlCyFmX80+fGaE/6A/Ekl0zaszYOubvySO2saYFdQ78P29D0UsULxFKCetDGNaNRUdSF+2A==", "dev": true, "requires": { "cssom": "0.3.x" @@ -2136,18 +2136,18 @@ "dev": true }, "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { "esutils": "^2.0.2" } }, "dom-testing-library": { - "version": "3.16.5", - "resolved": "https://registry.npmjs.org/dom-testing-library/-/dom-testing-library-3.16.5.tgz", - "integrity": "sha512-t3OaTcDdsAqtAZNeZ13KnOJmt+2HaDJqYWyf0iBRzbG6GwrNtpF0122Ygu/qkerIwcnHMX1ihwZVx/DhaLpmTw==", + "version": "3.16.8", + "resolved": "https://registry.npmjs.org/dom-testing-library/-/dom-testing-library-3.16.8.tgz", + "integrity": "sha512-VGn2piehGoN9lmZDYd+xoTZwwcS+FoXebvZMw631UhS5LshiLTFNJs9bxRa9W7fVb1cAn9AYKAKZXh67rCDaqw==", "requires": { "@babel/runtime": "^7.1.5", "@sheerun/mutationobserver-shim": "^0.3.2", @@ -2186,6 +2186,12 @@ "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", "dev": true }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -2264,35 +2270,35 @@ } }, "eslint": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.13.0.tgz", - "integrity": "sha512-nqD5WQMisciZC5EHZowejLKQjWGuFS5c70fxqSKlnDME+oz9zmE8KTlX+lHSg+/5wsC/kf9Q9eMkC8qS3oM2fg==", + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.14.0.tgz", + "integrity": "sha512-jrOhiYyENRrRnWlMYANlGZTqb89r2FuRT+615AabBoajhNjeh9ywDNlh2LU9vTqf0WYN+L3xdXuIi7xuj/tK9w==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "ajv": "^6.5.3", + "ajv": "^6.9.1", "chalk": "^2.1.0", "cross-spawn": "^6.0.5", "debug": "^4.0.1", - "doctrine": "^2.1.0", + "doctrine": "^3.0.0", "eslint-scope": "^4.0.0", "eslint-utils": "^1.3.1", "eslint-visitor-keys": "^1.0.0", - "espree": "^5.0.0", + "espree": "^5.0.1", "esquery": "^1.0.1", "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", + "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob": "^7.1.2", "globals": "^11.7.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^6.1.0", + "inquirer": "^6.2.2", "js-yaml": "^3.12.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", - "lodash": "^4.17.5", + "lodash": "^4.17.11", "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", @@ -2303,7 +2309,7 @@ "semver": "^5.5.1", "strip-ansi": "^4.0.0", "strip-json-comments": "^2.0.1", - "table": "^5.0.2", + "table": "^5.2.3", "text-table": "^0.2.0" }, "dependencies": { @@ -2375,12 +2381,12 @@ "dev": true }, "espree": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.0.tgz", - "integrity": "sha512-1MpUfwsdS9MMoN7ZXqAr9e9UKdVHDcvrJpyx7mm1WuQlx/ygErEQBzgi5Nh5qBHIoYweprhtMkTCb9GhcAIcsA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", "dev": true, "requires": { - "acorn": "^6.0.2", + "acorn": "^6.0.7", "acorn-jsx": "^5.0.0", "eslint-visitor-keys": "^1.0.0" } @@ -2651,13 +2657,12 @@ } }, "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "^2.0.1" } }, "fileset": { @@ -2727,17 +2732,22 @@ } }, "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", "dev": true, "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" } }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "dev": true + }, "fn-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz", @@ -3420,9 +3430,9 @@ } }, "globals": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.10.0.tgz", - "integrity": "sha512-0GZF1RiPKU97IHUO5TORo9w1PwrH/NBPl+fS7oMLdaTRiYmYbwK4NWoZWrAdd0/abG9R2BU+OiwyQpTpE6pdfQ==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", "dev": true }, "globby": { @@ -3459,9 +3469,9 @@ "dev": true }, "handlebars": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", - "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz", + "integrity": "sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==", "dev": true, "requires": { "async": "^2.5.0", @@ -3707,6 +3717,7 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, "requires": { "loose-envify": "^1.0.0" } @@ -4017,9 +4028,9 @@ "dev": true }, "istanbul-api": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.0.tgz", - "integrity": "sha512-+Ygg4t1StoiNlBGc6x0f8q/Bv26FbZqP/+jegzfNpU7Q8o+4ZRoJxJPhBkgE/UonpAjtxnE4zCZIyJX+MwLRMQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.1.tgz", + "integrity": "sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw==", "dev": true, "requires": { "async": "^2.6.1", @@ -4030,7 +4041,7 @@ "istanbul-lib-instrument": "^3.1.0", "istanbul-lib-report": "^2.0.4", "istanbul-lib-source-maps": "^3.0.2", - "istanbul-reports": "^2.1.0", + "istanbul-reports": "^2.1.1", "js-yaml": "^3.12.0", "make-dir": "^1.3.0", "minimatch": "^3.0.4", @@ -4126,12 +4137,12 @@ } }, "istanbul-reports": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.1.0.tgz", - "integrity": "sha512-azQdSX+dtTtkQEfqq20ICxWi6eOHXyHIgMFw1VOOVi8iIPWeCWRgCyFh/CsBKIhcgskMI8ExXmU7rjXTRCIJ+A==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.1.1.tgz", + "integrity": "sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw==", "dev": true, "requires": { - "handlebars": "^4.0.11" + "handlebars": "^4.1.0" } }, "jest": { @@ -4552,7 +4563,8 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "js-yaml": { "version": "3.12.1", @@ -4684,9 +4696,9 @@ "dev": true }, "kleur": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.1.tgz", - "integrity": "sha512-P3kRv+B+Ra070ng2VKQqW4qW7gd/v3iD8sy/zOdcYRsfiD+QBokQNOps/AfP6Hr48cBhIIBFWckB9aO+IZhrWg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.2.tgz", + "integrity": "sha512-3h7B2WRT5LNXOtQiAaWonilegHcPSf9nLVXlSTci8lu1dZUuui61+EsPEZqSVxY7rXYmB2DVKMQILxaO5WL61Q==", "dev": true }, "lcid": { @@ -4721,9 +4733,9 @@ } }, "lint-staged": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-8.1.3.tgz", - "integrity": "sha512-6TGkikL1B+6mIOuSNq2TV6oP21IhPMnV8q0cf9oYZ296ArTVNcbFh1l1pfVOHHbBIYLlziWNsQ2q45/ffmJ4AA==", + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-8.1.4.tgz", + "integrity": "sha512-oFbbhB/VzN8B3i/sIdb9gMfngGArI6jIfxSn+WPdQb2Ni3GJeS6T4j5VriSbQfxfMuYoQlMHOoFt+lfcWV0HfA==", "dev": true, "requires": { "@iamstarkov/listr-update-renderer": "0.4.1", @@ -4739,7 +4751,7 @@ "is-glob": "^4.0.0", "is-windows": "^1.0.2", "listr": "^0.14.2", - "lodash": "^4.17.5", + "lodash": "^4.17.11", "log-symbols": "^2.2.0", "micromatch": "^3.1.8", "npm-which": "^3.0.1", @@ -5050,6 +5062,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } @@ -5230,18 +5243,18 @@ } }, "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", "dev": true }, "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", "dev": true, "requires": { - "mime-db": "~1.37.0" + "mime-db": "~1.38.0" } }, "mimic-fn": { @@ -5492,9 +5505,9 @@ } }, "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", "dev": true }, "object-visit": { @@ -5977,6 +5990,15 @@ "ms": "^2.1.1" } }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "eslint": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", @@ -6050,6 +6072,28 @@ "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", @@ -6128,6 +6172,15 @@ "slice-ansi": "1.0.0", "string-width": "^2.1.1" } + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } } } }, @@ -6283,6 +6336,15 @@ "ms": "^2.1.1" } }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "eslint": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", @@ -6371,6 +6433,16 @@ "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -6380,6 +6452,18 @@ "locate-path": "^2.0.0" } }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, "get-stdin": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", @@ -6560,6 +6644,15 @@ "string-width": "^2.1.1" } }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", @@ -6634,23 +6727,24 @@ "dev": true }, "prompts": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.0.1.tgz", - "integrity": "sha512-8lnEOSIGQbgbnO47+13S+H204L8ISogGulyi0/NNEFAQ9D1VMNTrJ9SBX2Ra03V4iPn/zt36HQMndRYkaPoWiQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.0.3.tgz", + "integrity": "sha512-H8oWEoRZpybm6NV4to9/1limhttEo13xK62pNvn2JzY0MA03p7s0OjtmhXyon3uJmxiJJVSuUwEJFFssI3eBiQ==", "dev": true, "requires": { - "kleur": "^3.0.0", + "kleur": "^3.0.2", "sisteransi": "^1.0.0" } }, "prop-types": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", - "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", "dev": true, "requires": { - "loose-envify": "^1.3.1", - "object-assign": "^4.1.1" + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" } }, "property-expr": { @@ -6700,34 +6794,41 @@ "dev": true }, "react": { - "version": "16.8.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.8.0.tgz", - "integrity": "sha512-g+nikW2D48kqgWSPwNo0NH9tIGG3DsQFlrtrQ1kj6W77z5ahyIHG0w8kPpz4Sdj6gyLnz0lEd/xsjOoGge2MYQ==", + "version": "16.8.2", + "resolved": "https://registry.npmjs.org/react/-/react-16.8.2.tgz", + "integrity": "sha512-aB2ctx9uQ9vo09HVknqv3DGRpI7OIGJhCx3Bt0QqoRluEjHSaObJl+nG12GDdYH6sTgE7YiPJ6ZUyMx9kICdXw==", "dev": true, "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "scheduler": "^0.13.0" + "scheduler": "^0.13.2" } }, "react-dom": { - "version": "16.8.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.0.tgz", - "integrity": "sha512-dBzoAGYZpW9Yggp+CzBPC7q1HmWSeRc93DWrwbskmG1eHJWznZB/p0l/Sm+69leIGUS91AXPB/qB3WcPnKx8Sw==", + "version": "16.8.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.2.tgz", + "integrity": "sha512-cPGfgFfwi+VCZjk73buu14pYkYBR1b/SRMSYqkLDdhSEHnSwcuYTPu6/Bh6ZphJFIk80XLvbSe2azfcRzNF+Xg==", "dev": true, "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "scheduler": "^0.13.0" + "scheduler": "^0.13.2" } }, + "react-is": { + "version": "16.8.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.2.tgz", + "integrity": "sha512-D+NxhSR2HUCjYky1q1DwpNUD44cDpUXzSmmFyC3ug1bClcU/iDNy0YNn1iwme28fn+NFhpA13IndOd42CrFb+Q==", + "dev": true + }, "react-testing-library": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/react-testing-library/-/react-testing-library-5.5.0.tgz", - "integrity": "sha512-58X5frBnjcgTckZUcp9+1D1P/uunIuceIfzne8/p0rGn/vhIodFEKGpkaOAEHE2k+t5cXFJ0fufjlc/ukblIOw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/react-testing-library/-/react-testing-library-5.8.0.tgz", + "integrity": "sha512-cYOX8aUKea5ojFVXkhLbNEAq86nYqBlhKulJI/0v8JfwWyQm+kbyNKFfyci6b2qI4KUEvBYZKWx+zZWeYrYOOA==", "requires": { + "@babel/runtime": "^7.3.1", "dom-testing-library": "^3.13.1" } }, @@ -6801,9 +6902,9 @@ } }, "realpath-native": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.0.2.tgz", - "integrity": "sha512-+S3zTvVt9yTntFrBpm7TQmQ3tzpCrnA1a/y+3cUHAc9ZR6aIjG0WNLR+Rj79QpJktY+VeW/TQtFlQ1bzsehI8g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", "dev": true, "requires": { "util.promisify": "^1.0.0" @@ -6949,23 +7050,23 @@ } }, "request-promise-core": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", - "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", "dev": true, "requires": { - "lodash": "^4.13.1" + "lodash": "^4.17.11" } }, "request-promise-native": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", - "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", "dev": true, "requires": { - "request-promise-core": "1.1.1", - "stealthy-require": "^1.1.0", - "tough-cookie": ">=2.3.3" + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" } }, "require-directory": { @@ -7193,9 +7294,9 @@ "dev": true }, "scheduler": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.0.tgz", - "integrity": "sha512-w7aJnV30jc7OsiZQNPVmBc+HooZuvQZIZIShKutC3tnMFMkcwVN9CZRRSSNw03OnSCKmEkK8usmwcw6dqBaLzw==", + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.2.tgz", + "integrity": "sha512-qK5P8tHS7vdEMCW5IPyt8v9MJOHqTrOUgPXib7tqm9vh834ibBX5BNhwkplX/0iOzHW5sXyluehYfS9yrkz9+w==", "dev": true, "requires": { "loose-envify": "^1.1.0", @@ -7681,15 +7782,37 @@ "dev": true }, "table": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/table/-/table-5.2.2.tgz", - "integrity": "sha512-f8mJmuu9beQEDkKHLzOv4VxVYlU68NpdzjbGPl69i4Hx0sTopJuNxuzJd17iV2h24dAfa93u794OnDA5jqXvfQ==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", + "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", "dev": true, "requires": { - "ajv": "^6.6.1", + "ajv": "^6.9.1", "lodash": "^4.17.11", - "slice-ansi": "^2.0.0", - "string-width": "^2.1.1" + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "string-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.0.0.tgz", + "integrity": "sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + } } }, "test-exclude": { @@ -8064,11 +8187,6 @@ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", "dev": true }, - "uuid-v4": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/uuid-v4/-/uuid-v4-0.1.0.tgz", - "integrity": "sha1-YtezEEBvbOz+oVKMafHo4LzsWjo=" - }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -8302,9 +8420,9 @@ "dev": true }, "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", "dev": true, "requires": { "mkdirp": "^0.5.1" diff --git a/package.json b/package.json index 841b1a95..8a6db737 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-hooks-testing-library", - "version": "0.2.4", + "version": "0.3.0", "description": "Simple component wrapper for testing React hooks", "main": "lib/index.js", "author": "Michael Peyper", @@ -17,31 +17,29 @@ "contributors:add": "all-contributors add" }, "dependencies": { - "invariant": "^2.2.4", - "react-testing-library": "^5.5.0", - "uuid-v4": "^0.1.0" + "react-testing-library": "^5.8.0" }, "devDependencies": { "@babel/cli": "^7.2.3", - "@babel/core": "^7.2.2", + "@babel/core": "^7.3.3", "@babel/plugin-proposal-object-rest-spread": "^7.3.2", "@babel/plugin-transform-modules-commonjs": "^7.2.0", "@babel/preset-env": "^7.3.1", "@babel/preset-react": "^7.0.0", - "all-contributors-cli": "^5.11.0", + "all-contributors-cli": "^6.1.1", "babel-eslint": "^10.0.1", - "babel-plugin-module-resolver": "^3.1.3", - "eslint": "^5.13.0", + "babel-plugin-module-resolver": "^3.2.0", + "eslint": "^5.14.0", "eslint-config-prettier": "^4.0.0", "eslint-plugin-prettier": "^3.0.1", "husky": "^1.3.1", "jest": "^24.1.0", - "lint-staged": "^8.1.3", + "lint-staged": "^8.1.4", "prettier": "^1.16.4", "prettier-eslint": "^8.8.2", "prettier-eslint-cli": "^4.7.1", - "react": "^16.8.0", - "react-dom": "^16.8.0" + "react": "^16.8.2", + "react-dom": "^16.8.2" }, "peerDependencies": { "react": "^16.8.0", diff --git a/src/index.js b/src/index.js index b3a7bd98..cf955c76 100644 --- a/src/index.js +++ b/src/index.js @@ -1,71 +1,44 @@ import React from 'react' -import { act } from 'react-dom/test-utils' -import { render, cleanup } from 'react-testing-library' -import invariant from 'invariant' -import uuid from 'uuid-v4' +import { render, cleanup, act } from 'react-testing-library' -export const useHook = (hook, ...props) => { - const context = { - id: uuid(), - resolveComponent: (Component) => Component, - rendered: false, - props - } - - const HookHarness = () => { - context.currentValue = hook(...context.props) - return
- } - - const renderHook = () => { - const { queryByTestId, rerender } = render(context.resolveComponent()) - const container = queryByTestId(context.id) - - invariant(container !== null, 'Failed to render wrapper component') +function TestHook({ callback, hookProps, children }) { + children(callback(hookProps)) + return null +} - context.rendered = true - context.rerender = () => rerender(context.resolveComponent()) - } +function renderHook(callback, options = {}) { + const result = { current: null } + const hookProps = { current: options.initialProps } + + const toRender = () => { + const hookRender = ( + + {(res) => { + result.current = res + }} + + ) - const getCurrentValue = () => { - act(() => { - if (!context.rendered) { - renderHook() - } else { - context.rerender() - } - }) - return context.currentValue + return options.wrapper ? React.createElement(options.wrapper, null, hookRender) : hookRender } - const setProps = (...newProps) => { - context.props = newProps - } + const { unmount, rerender: rerenderComponent } = render(toRender()) - const addContextProvider = (ContextProvider, contextProps) => { - const Provider = ContextProvider.Provider || ContextProvider - const { resolveComponent } = context - const updateContext = (newContextProps) => { - contextProps = newContextProps + return { + result, + unmount, + rerender: (newProps = hookProps.current) => { + hookProps.current = newProps + rerenderComponent(toRender()) } - context.resolveComponent = (Component) => ( - {resolveComponent(Component)} - ) - return { updateContext } - } - - const flushEffects = () => { - getCurrentValue() } +} - return { - getCurrentValue, - getCurrentValues: getCurrentValue, - flushEffects, - setProps, - addContextProvider, - act - } +function testHook(...args) { + console.warn( + '`testHook` has been deprecated and will be removed in a future release. Please use `renderHook` instead.' + ) + return renderHook(...args) } -export { cleanup } +export { renderHook, cleanup, act, testHook } diff --git a/test/customHook.test.js b/test/customHook.test.js index 98d50769..7ccdb1ed 100644 --- a/test/customHook.test.js +++ b/test/customHook.test.js @@ -1,5 +1,6 @@ +import React from 'react' import { useState, createContext, useContext, useMemo } from 'react' -import { useHook, cleanup } from 'src' +import { renderHook, cleanup, act } from 'src' describe('custom hook tests', () => { const themes = { @@ -12,52 +13,51 @@ describe('custom hook tests', () => { const useTheme = (initialTheme) => { const themes = useContext(ThemesContext) const [theme, setTheme] = useState(initialTheme) - const changeTheme = () => { + const toggleTheme = () => { setTheme(theme === 'light' ? 'dark' : 'light') } - return useMemo(() => ({ ...themes[theme], changeTheme }), [theme]) + return useMemo(() => ({ ...themes[theme], toggleTheme }), [theme]) } afterEach(cleanup) - test('should get initial theme from custom hook', () => { - const { getCurrentValue } = useHook(() => useTheme('light')) + test('should use theme', () => { + const { result } = renderHook(() => useTheme('light')) - const theme = getCurrentValue() + const theme = result.current expect(theme.primaryLight).toBe('#FFFFFF') expect(theme.primaryDark).toBe('#000000') - expect(typeof theme.changeTheme).toBe('function') }) - test('should update theme using custom hook', () => { - const { getCurrentValue, act } = useHook(() => useTheme('light')) + test('should update theme', () => { + const { result } = renderHook(() => useTheme('light')) - const { changeTheme } = getCurrentValue() + const { toggleTheme } = result.current - act(() => changeTheme()) + act(() => toggleTheme()) - const theme = getCurrentValue() + const theme = result.current expect(theme.primaryLight).toBe('#000000') expect(theme.primaryDark).toBe('#FFFFFF') - expect(typeof theme.changeTheme).toBe('function') }) - test('should get custom theme from custom hook', () => { + test('should use custom theme', () => { const customThemes = { light: { primaryLight: '#AABBCC', primaryDark: '#CCBBAA' }, dark: { primaryLight: '#CCBBAA', primaryDark: '#AABBCC' } } - const { getCurrentValue, addContextProvider } = useHook(() => useTheme('light')) + const wrapper = ({ children }) => ( + {children} + ) - addContextProvider(ThemesContext, { value: customThemes }) + const { result } = renderHook(() => useTheme('light'), { wrapper }) - const theme = getCurrentValue() + const theme = result.current expect(theme.primaryLight).toBe('#AABBCC') expect(theme.primaryDark).toBe('#CCBBAA') - expect(typeof theme.changeTheme).toBe('function') }) }) diff --git a/test/testHook.test.js b/test/testHook.test.js new file mode 100644 index 00000000..ea6dc7f7 --- /dev/null +++ b/test/testHook.test.js @@ -0,0 +1,83 @@ +import React, { useState, useEffect } from 'react' +import { testHook, cleanup, act } from 'src' + +describe('testHook tests', () => { + afterEach(cleanup) + + test('testHook calls the callback', () => { + const spy = jest.fn() + testHook(spy) + expect(spy).toHaveBeenCalledTimes(1) + }) + + test('confirm we can safely call a React Hook from within the callback', () => { + testHook(() => useState()) + }) + + test('returns a function to unmount component', () => { + let isMounted + const { unmount } = testHook(() => { + useEffect(() => { + isMounted = true + return () => { + isMounted = false + } + }) + }) + expect(isMounted).toBe(true) + unmount() + expect(isMounted).toBe(false) + }) + + test('returns a function to rerender component', () => { + let renderCount = 0 + const { rerender } = testHook(() => { + useEffect(() => { + renderCount++ + }) + }) + + expect(renderCount).toBe(1) + rerender() + expect(renderCount).toBe(2) + }) + + test('accepts wrapper option to wrap rendered hook with', () => { + const ctxA = React.createContext() + const ctxB = React.createContext() + const useHook = () => { + return React.useContext(ctxA) * React.useContext(ctxB) + } + let actual + testHook( + () => { + actual = useHook() + }, + { + // eslint-disable-next-line react/display-name + wrapper: (props) => ( + + + + ) + } + ) + expect(actual).toBe(12) + }) + + test('returns result ref with latest result from hook execution', () => { + function useCounter({ initialCount = 0, step = 1 } = {}) { + const [count, setCount] = React.useState(initialCount) + const increment = () => setCount((c) => c + step) + const decrement = () => setCount((c) => c - step) + return { count, increment, decrement } + } + + const { result } = testHook(useCounter) + expect(result.current.count).toBe(0) + act(() => { + result.current.increment() + }) + expect(result.current.count).toBe(1) + }) +}) diff --git a/test/useContext.test.js b/test/useContext.test.js index b0406f74..17ca3101 100644 --- a/test/useContext.test.js +++ b/test/useContext.test.js @@ -1,5 +1,6 @@ +import React from 'react' import { createContext, useContext } from 'react' -import { useHook, cleanup } from 'src' +import { renderHook, cleanup } from 'src' describe('useContext tests', () => { afterEach(cleanup) @@ -7,9 +8,9 @@ describe('useContext tests', () => { test('should get default value from context', () => { const TestContext = createContext('foo') - const { getCurrentValue } = useHook(() => useContext(TestContext)) + const { result } = renderHook(() => useContext(TestContext)) - const value = getCurrentValue() + const value = result.current expect(value).toBe('foo') }) @@ -17,9 +18,9 @@ describe('useContext tests', () => { test('should get default value from context provider', () => { const TestContext = createContext('foo') - const { getCurrentValue } = useHook(() => useContext(TestContext)) + const { result } = renderHook(() => useContext(TestContext)) - const value = getCurrentValue() + const value = result.current expect(value).toBe('foo') }) @@ -27,11 +28,13 @@ describe('useContext tests', () => { test('should get value from context', () => { const TestContext = createContext('foo') - const { getCurrentValue, addContextProvider } = useHook(() => useContext(TestContext)) + const wrapper = ({ children }) => ( + {children} + ) - addContextProvider(TestContext, { value: 'bar' }) + const { result } = renderHook(() => useContext(TestContext), { wrapper }) - const value = getCurrentValue() + const value = result.current expect(value).toBe('bar') }) @@ -39,40 +42,30 @@ describe('useContext tests', () => { test('should get value from context provider', () => { const TestContext = createContext('foo') - const { getCurrentValue, addContextProvider } = useHook(() => useContext(TestContext)) + const wrapper = ({ children }) => ( + {children} + ) - addContextProvider(TestContext.Provider, { value: 'bar' }) + const { result } = renderHook(() => useContext(TestContext), { wrapper }) - const value = getCurrentValue() - - expect(value).toBe('bar') + expect(result.current).toBe('bar') }) test('should update value in context', () => { const TestContext = createContext('foo') - const { getCurrentValue, addContextProvider } = useHook(() => useContext(TestContext)) - - const { updateContext } = addContextProvider(TestContext, { value: 'bar' }) - - updateContext({ value: 'baz' }) - - const value = getCurrentValue() - - expect(value).toBe('baz') - }) - - test('should update value in context provider', () => { - const TestContext = createContext('foo') + const value = { current: 'bar' } - const { getCurrentValue, addContextProvider } = useHook(() => useContext(TestContext)) + const wrapper = ({ children }) => ( + {children} + ) - const { updateContext } = addContextProvider(TestContext.Provider, { value: 'bar' }) + const { result, rerender } = renderHook(() => useContext(TestContext), { wrapper }) - updateContext({ value: 'baz' }) + value.current = 'baz' - const value = getCurrentValue() + rerender() - expect(value).toBe('baz') + expect(result.current).toBe('baz') }) }) diff --git a/test/useEffect.test.js b/test/useEffect.test.js index 8768fce4..6d2998e5 100644 --- a/test/useEffect.test.js +++ b/test/useEffect.test.js @@ -1,5 +1,5 @@ import { useEffect, useLayoutEffect } from 'react' -import { useHook, cleanup } from 'src' +import { renderHook, cleanup } from 'src' describe('useEffect tests', () => { afterEach(cleanup) @@ -7,7 +7,7 @@ describe('useEffect tests', () => { test('should handle useEffect hook', () => { const sideEffect = { [1]: false, [2]: false } - const { flushEffects, setProps } = useHook( + const { rerender, unmount } = renderHook( ({ id }) => { useEffect(() => { sideEffect[id] = true @@ -16,25 +16,27 @@ describe('useEffect tests', () => { } }, [id]) }, - { id: 1 } + { initialProps: { id: 1 } } ) - flushEffects() - expect(sideEffect[1]).toBe(true) expect(sideEffect[2]).toBe(false) - setProps({ id: 2 }) - flushEffects() + rerender({ id: 2 }) expect(sideEffect[1]).toBe(false) expect(sideEffect[2]).toBe(true) + + unmount() + + expect(sideEffect[1]).toBe(false) + expect(sideEffect[2]).toBe(false) }) test('should handle useLayoutEffect hook', () => { const sideEffect = { [1]: false, [2]: false } - const { flushEffects, setProps } = useHook( + const { rerender, unmount } = renderHook( ({ id }) => { useLayoutEffect(() => { sideEffect[id] = true @@ -43,18 +45,20 @@ describe('useEffect tests', () => { } }, [id]) }, - { id: 1 } + { initialProps: { id: 1 } } ) - flushEffects() - expect(sideEffect[1]).toBe(true) expect(sideEffect[2]).toBe(false) - setProps({ id: 2 }) - flushEffects() + rerender({ id: 2 }) expect(sideEffect[1]).toBe(false) expect(sideEffect[2]).toBe(true) + + unmount() + + expect(sideEffect[1]).toBe(false) + expect(sideEffect[2]).toBe(false) }) }) diff --git a/test/useMemo.test.js b/test/useMemo.test.js index 4ebb1de5..0783abf8 100644 --- a/test/useMemo.test.js +++ b/test/useMemo.test.js @@ -1,28 +1,29 @@ import { useMemo, useCallback } from 'react' -import { useHook, cleanup } from 'src' +import { renderHook, cleanup } from 'src' describe('useCallback tests', () => { afterEach(cleanup) test('should handle useMemo hook', () => { - const { getCurrentValue, setProps } = useHook( - ({ value }) => useMemo(() => ({ value }), [value]), - { value: 1 } - ) + const { result, rerender } = renderHook(({ value }) => useMemo(() => ({ value }), [value]), { + initialProps: { value: 1 } + }) - const value1 = getCurrentValue() + const value1 = result.current expect(value1).toEqual({ value: 1 }) - const value2 = getCurrentValue() + rerender() + + const value2 = result.current expect(value2).toEqual({ value: 1 }) expect(value2).toBe(value1) - setProps({ value: 2 }) + rerender({ value: 2 }) - const value3 = getCurrentValue() + const value3 = result.current expect(value3).toEqual({ value: 2 }) @@ -30,21 +31,21 @@ describe('useCallback tests', () => { }) test('should handle useCallback hook', () => { - const { getCurrentValue, setProps } = useHook( + const { result, rerender } = renderHook( ({ value }) => { const callback = () => ({ value }) return useCallback(callback, [value]) }, - { value: 1 } + { initialProps: { value: 1 } } ) - const callback1 = getCurrentValue() + const callback1 = result.current const calbackValue1 = callback1() expect(calbackValue1).toEqual({ value: 1 }) - const callback2 = getCurrentValue() + const callback2 = result.current const calbackValue2 = callback2() @@ -52,9 +53,9 @@ describe('useCallback tests', () => { expect(callback2).toBe(callback1) - setProps({ value: 2 }) + rerender({ value: 2 }) - const callback3 = getCurrentValue() + const callback3 = result.current const calbackValue3 = callback3() diff --git a/test/useReducer.test.js b/test/useReducer.test.js index bd2c9353..9e515297 100644 --- a/test/useReducer.test.js +++ b/test/useReducer.test.js @@ -1,20 +1,20 @@ import { useReducer } from 'react' -import { useHook, cleanup } from 'src' +import { renderHook, cleanup, act } from 'src' describe('useReducer tests', () => { afterEach(cleanup) test('should handle useReducer hook', () => { const reducer = (state, action) => (action.type === 'inc' ? state + 1 : state) - const { getCurrentValues, act } = useHook(() => useReducer(reducer, 0)) + const { result } = renderHook(() => useReducer(reducer, 0)) - const [initialState, dispatch] = getCurrentValues() + const [initialState, dispatch] = result.current expect(initialState).toBe(0) act(() => dispatch({ type: 'inc' })) - const [state] = getCurrentValues() + const [state] = result.current expect(state).toBe(1) }) diff --git a/test/useRef.test.js b/test/useRef.test.js index 55cbc3e1..c88ddc47 100644 --- a/test/useRef.test.js +++ b/test/useRef.test.js @@ -1,20 +1,20 @@ import { useRef, useImperativeHandle } from 'react' -import { useHook, cleanup } from 'src' +import { renderHook, cleanup } from 'src' describe('useHook tests', () => { afterEach(cleanup) test('should handle useRef hook', () => { - const { getCurrentValue } = useHook(() => useRef()) + const { result } = renderHook(() => useRef()) - const refContainer = getCurrentValue() + const refContainer = result.current expect(Object.keys(refContainer)).toEqual(['current']) expect(refContainer.current).toBeUndefined() }) test('should handle useImperativeHandle hook', () => { - const { getCurrentValue } = useHook(() => { + const { result } = renderHook(() => { const ref = useRef() useImperativeHandle(ref, () => ({ fakeImperativeMethod: () => true @@ -22,7 +22,7 @@ describe('useHook tests', () => { return ref }) - const refContainer = getCurrentValue() + const refContainer = result.current expect(refContainer.current.fakeImperativeMethod()).toBe(true) }) diff --git a/test/setState.test.js b/test/useState.test.js similarity index 51% rename from test/setState.test.js rename to test/useState.test.js index 64198a3f..71d5ab94 100644 --- a/test/setState.test.js +++ b/test/useState.test.js @@ -1,25 +1,25 @@ import { useState } from 'react' -import { useHook, cleanup } from 'src' +import { renderHook, cleanup, act } from 'src' describe('useState tests', () => { afterEach(cleanup) test('should use setState value', () => { - const { getCurrentValue } = useHook(() => useState('foo')) + const { result } = renderHook(() => useState('foo')) - const [value] = getCurrentValue() + const [value] = result.current expect(value).toBe('foo') }) test('should update setState value using setter', () => { - const { getCurrentValues, act } = useHook(() => useState('foo')) + const { result } = renderHook(() => useState('foo')) - const [_, setValue] = getCurrentValues() + const [_, setValue] = result.current act(() => setValue('bar')) - const [value] = getCurrentValues() + const [value] = result.current expect(value).toBe('bar') })