From f2ec0792cd0245af31180fd59fe2f45a268ffa25 Mon Sep 17 00:00:00 2001 From: gaeaehrlich Date: Mon, 3 May 2021 11:41:18 +0300 Subject: [PATCH] fix(#7): Upgraded to React 17, including fix to Scrollable and effect cleanup timing --- package-lock.json | 178 +++++++----------- package.json | 2 +- .../useClickOutside/useClickOutside.test.js | 25 +-- src/hooks/useDebounce/useDebounce.js | 5 +- src/hooks/useDebounce/useDebounce.test.js | 16 +- src/hooks/useDimensions/useDimensions.test.js | 4 +- src/hooks/useThrottle/useThrottle.js | 7 +- src/hooks/useThrottle/useThrottle.test.js | 16 +- .../ResizeObserver/ResizeObserver.test.js | 5 +- test/setup.js | 2 +- 10 files changed, 120 insertions(+), 140 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0cfa1c8..cb45a22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2056,6 +2056,65 @@ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "@wojtekmaj/enzyme-adapter-react-17": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@wojtekmaj/enzyme-adapter-react-17/-/enzyme-adapter-react-17-0.6.1.tgz", + "integrity": "sha512-xgPfzLVpN0epIHeZofahwr5qwpukEDNAbrufgeDWN6vZPtfblGCC+OZG5TlfK+A6ePVy8sBkD8S2X4tO17JKjg==", + "dev": true, + "requires": { + "@wojtekmaj/enzyme-adapter-utils": "^0.1.0", + "enzyme-shallow-equal": "^1.0.0", + "has": "^1.0.0", + "object.assign": "^4.1.0", + "object.values": "^1.1.0", + "prop-types": "^15.7.0", + "react-is": "^17.0.0", + "react-test-renderer": "^17.0.0" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "react-test-renderer": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.2.tgz", + "integrity": "sha512-yaQ9cB89c17PUb0x6UfWRs7kQCorVdHlutU1boVPEsB8IDZH6n9tHxMacc3y0JoXOJUsZb/t/Mb8FUWMKaM7iQ==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "react-is": "^17.0.2", + "react-shallow-renderer": "^16.13.1", + "scheduler": "^0.20.2" + } + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, + "@wojtekmaj/enzyme-adapter-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@wojtekmaj/enzyme-adapter-utils/-/enzyme-adapter-utils-0.1.0.tgz", + "integrity": "sha512-EYK/Vy0Y1ap0jH2UNQjOKtR/7HWkbEq8N+cwC5+yDf+Mwp5uu7j4Qg70RmWuzsA35DGGwgkop6m4pQsGwNOF2A==", + "dev": true, + "requires": { + "function.prototype.name": "^1.1.0", + "has": "^1.0.0", + "object.assign": "^4.1.0", + "object.fromentries": "^2.0.0", + "prop-types": "^15.7.0" + } + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -2144,23 +2203,6 @@ } } }, - "airbnb-prop-types": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.16.0.tgz", - "integrity": "sha512-7WHOFolP/6cS96PhKNrslCLMYAI8yB1Pp6u6XmxozQOiZbsI5ycglZr5cHhBFfuRcQQjzCMith5ZPZdYiJCxUg==", - "dev": true, - "requires": { - "array.prototype.find": "^2.1.1", - "function.prototype.name": "^1.1.2", - "is-regex": "^1.1.0", - "object-is": "^1.1.2", - "object.assign": "^4.1.0", - "object.entries": "^1.1.2", - "prop-types": "^15.7.2", - "prop-types-exact": "^1.2.0", - "react-is": "^16.13.1" - } - }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -2341,37 +2383,6 @@ "dev": true, "optional": true }, - "array.prototype.find": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.1.1.tgz", - "integrity": "sha512-mi+MYNJYLTx2eNYy+Yh6raoQacCsNeeMUaspFPh9Y141lFSsWxxB8V9mM2ye+eqiRs917J6/pJ4M9ZPzenWckA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.4" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - }, "array.prototype.flat": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", @@ -4603,38 +4614,6 @@ "string.prototype.trim": "^1.2.1" } }, - "enzyme-adapter-react-16": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.5.tgz", - "integrity": "sha512-33yUJGT1nHFQlbVI5qdo5Pfqvu/h4qPwi1o0a6ZZsjpiqq92a3HjynDhwd1IeED+Su60HDWV8mxJqkTnLYdGkw==", - "dev": true, - "requires": { - "enzyme-adapter-utils": "^1.13.1", - "enzyme-shallow-equal": "^1.0.4", - "has": "^1.0.3", - "object.assign": "^4.1.0", - "object.values": "^1.1.1", - "prop-types": "^15.7.2", - "react-is": "^16.13.1", - "react-test-renderer": "^16.0.0-0", - "semver": "^5.7.0" - } - }, - "enzyme-adapter-utils": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.0.tgz", - "integrity": "sha512-F/z/7SeLt+reKFcb7597IThpDp0bmzcH1E9Oabqv+o01cID2/YInlqHbFl7HzWBl4h3OdZYedtwNDOmSKkk0bg==", - "dev": true, - "requires": { - "airbnb-prop-types": "^2.16.0", - "function.prototype.name": "^1.1.3", - "has": "^1.0.3", - "object.assign": "^4.1.2", - "object.fromentries": "^2.0.3", - "prop-types": "^15.7.2", - "semver": "^5.7.1" - } - }, "enzyme-shallow-equal": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz", @@ -13889,17 +13868,6 @@ "react-is": "^16.8.1" } }, - "prop-types-exact": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", - "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", - "dev": true, - "requires": { - "has": "^1.0.3", - "object.assign": "^4.1.0", - "reflect.ownkeys": "^0.2.0" - } - }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -14033,16 +14001,14 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, - "react-test-renderer": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.14.0.tgz", - "integrity": "sha512-L8yPjqPE5CZO6rKsKXRO/rVPiaCOy0tQQJbC+UjPNlobl5mad59lvPjwFsQHTvL03caVDIVr9x9/OSgDe6I5Eg==", + "react-shallow-renderer": { + "version": "16.14.1", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.14.1.tgz", + "integrity": "sha512-rkIMcQi01/+kxiTE9D3fdS959U1g7gs+/rborw++42m1O9FAQiNI/UNRZExVUoAOprn4umcXf+pFRou8i4zuBg==", "dev": true, "requires": { "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "react-is": "^16.8.6", - "scheduler": "^0.19.1" + "react-is": "^16.12.0 || ^17.0.0" } }, "read-pkg": { @@ -14147,12 +14113,6 @@ "esprima": "~4.0.0" } }, - "reflect.ownkeys": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", - "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=", - "dev": true - }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -14653,16 +14613,6 @@ "xmlchars": "^2.2.0" } }, - "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "dev": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "schema-utils": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", diff --git a/package.json b/package.json index 0197ad7..97fcde9 100644 --- a/package.json +++ b/package.json @@ -42,13 +42,13 @@ "@rollup/plugin-babel": "5.2.1", "@rollup/plugin-commonjs": "16.0.0", "@rollup/plugin-node-resolve": "10.0.0", + "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1", "babel-eslint": "10.1.0", "babel-loader": "8.2.2", "babel-plugin-module-resolver": "4.0.0", "babel-plugin-rewire": "1.2.0", "chai": "4.2.0", "enzyme": "3.11.0", - "enzyme-adapter-react-16": "1.15.5", "eslint": "7.15.0", "eslint-plugin-import": "2.22.1", "eslint-plugin-notice": "0.9.10", diff --git a/src/hooks/useClickOutside/useClickOutside.test.js b/src/hooks/useClickOutside/useClickOutside.test.js index 08ba70c..3b2d15a 100644 --- a/src/hooks/useClickOutside/useClickOutside.test.js +++ b/src/hooks/useClickOutside/useClickOutside.test.js @@ -7,31 +7,34 @@ import {mount, shallow} from 'enzyme'; import OverrideContext from './useClickOutside.context'; import {useClickOutside, ClickOutside, ClickOutsideOverride} from './useClickOutside'; -const Elem = () => { - let test = 1234; - const ref = sinon.spy(); - useClickOutside(ref, () => test = 4321); - return
{test}
; +const Elem = callback => { + useClickOutside(callback); + return
; }; describe('useClickOutside()', () => { it('Should add an event listener to the document', () => { document.addEventListener = sinon.spy(); document.removeEventListener = sinon.spy(); - let elem; - act(() => { - elem = mount(); - }); - expect(elem.text()).to.eql('1234'); + act(() => {elem = mount()}); expect(document.addEventListener.calledTwice).to.eql(true); expect(document.addEventListener.calledWith('mousedown')).to.eql(true); expect(document.addEventListener.calledWith('mouseup')).to.eql(true); - elem.unmount(); + act(() => {elem.unmount()}); + expect(document.removeEventListener.calledTwice).to.eql(true); expect(document.removeEventListener.calledWith('mousedown')).to.eql(true); expect(document.removeEventListener.calledWith('mouseup')).to.eql(true); }); + it('Should not trigger the callback on click inside', () => { + const callback = sinon.spy(); + const elem = mount(); + expect(elem.find('div')); + elem.simulate('click'); + expect(callback.callCount).to.eql(0); + }); + it('', () => { const wrapper = shallow(
); expect(() => shallow()).to.throw(); diff --git a/src/hooks/useDebounce/useDebounce.js b/src/hooks/useDebounce/useDebounce.js index c3eb9d0..c7ab498 100644 --- a/src/hooks/useDebounce/useDebounce.js +++ b/src/hooks/useDebounce/useDebounce.js @@ -24,7 +24,10 @@ export default (callback, wait) => { useEffect(() => {cb.current = callback}, [callback]); // Cleanup pending timeouts when unmounting. - useEffect(() => () => clearTimeout(timeout.current), []); + useEffect(() => { + const _timeout = timeout.current; + return () => clearTimeout(_timeout); + }, []); return useCallback((...args) => { clearTimeout(timeout.current); diff --git a/src/hooks/useDebounce/useDebounce.test.js b/src/hooks/useDebounce/useDebounce.test.js index d18b656..d949843 100644 --- a/src/hooks/useDebounce/useDebounce.test.js +++ b/src/hooks/useDebounce/useDebounce.test.js @@ -18,6 +18,18 @@ const Elem = () => { }; describe('useDebounce()', () => { + let spy; + beforeEach(() => { + spy = sinon.spy(global, 'clearTimeout') + }); + afterEach(() => { + spy.resetHistory(); + spy.restore(); + }); + after(() => { + spy.restore(); + }); + it('Should delay calls', async () => { let wrapper = null; act(() => {wrapper = mount()}); @@ -40,10 +52,8 @@ describe('useDebounce()', () => { }); it('Should cleanup', async () => { let wrapper = null; - const spy = sinon.spy(global, 'clearTimeout'); act(() => {wrapper = mount()}); - wrapper.unmount(); + act(() => {wrapper.unmount()}); expect(spy.callCount).to.eql(1); - spy.restore(); }); }); \ No newline at end of file diff --git a/src/hooks/useDimensions/useDimensions.test.js b/src/hooks/useDimensions/useDimensions.test.js index 64858a3..ec4bc95 100644 --- a/src/hooks/useDimensions/useDimensions.test.js +++ b/src/hooks/useDimensions/useDimensions.test.js @@ -11,7 +11,7 @@ const Elem = () => { ); }; -describe('useDebounce()', () => { +describe('useDimensions()', () => { it('Should return the previous value', async () => { let wrapper = null; let observed = 0, disconnected = 0; @@ -24,7 +24,7 @@ describe('useDebounce()', () => { expect(observed).to.eql(1); expect(disconnected).to.eql(0); - wrapper.unmount(); + act(() => {wrapper.unmount()}); expect(observed).to.eql(1); expect(disconnected).to.eql(1); }); diff --git a/src/hooks/useThrottle/useThrottle.js b/src/hooks/useThrottle/useThrottle.js index 81e2b24..9f1e595 100644 --- a/src/hooks/useThrottle/useThrottle.js +++ b/src/hooks/useThrottle/useThrottle.js @@ -20,8 +20,11 @@ export default (callback, threshold) => { const wait = useRef(false); const timeout = useRef(-1); - useEffect(() => () => { - clearTimeout(timeout.current); + useEffect(() => { + const _timeout = timeout.current; + return () => { + clearTimeout(_timeout); + } }, []); // No need for deps here since 'timeout' is mutated return useCallback((...args) => { diff --git a/src/hooks/useThrottle/useThrottle.test.js b/src/hooks/useThrottle/useThrottle.test.js index bbfb0fb..60e8760 100644 --- a/src/hooks/useThrottle/useThrottle.test.js +++ b/src/hooks/useThrottle/useThrottle.test.js @@ -19,6 +19,18 @@ const Elem = () => { }; describe('useThrottle()', () => { + let spy; + beforeEach(() => { + spy = sinon.spy(global, 'clearTimeout') + }); + afterEach(() => { + spy.resetHistory(); + spy.restore(); + }); + after(() => { + spy.restore(); + }); + it('Should delay calls', async () => { let wrapper = null; act(() => {wrapper = mount()}); @@ -41,10 +53,8 @@ describe('useThrottle()', () => { }); it('Should cleanup', async () => { let wrapper = null; - const spy = sinon.spy(global, 'clearTimeout'); act(() => {wrapper = mount()}); - wrapper.unmount(); + act(() => {wrapper.unmount()}); expect(spy.callCount).to.eql(1); - spy.restore(); }); }); \ No newline at end of file diff --git a/src/tools/ResizeObserver/ResizeObserver.test.js b/src/tools/ResizeObserver/ResizeObserver.test.js index b3214e5..cd7c0a7 100644 --- a/src/tools/ResizeObserver/ResizeObserver.test.js +++ b/src/tools/ResizeObserver/ResizeObserver.test.js @@ -1,5 +1,6 @@ import React from 'react'; import {mount} from 'enzyme'; +import {act} from 'react-dom/test-utils'; import {expect} from 'chai'; import sinon from 'sinon'; import ResizeObserver from './ResizeObserver'; @@ -14,11 +15,11 @@ describe('', () => { }; const handleOnResize = sinon.spy(); - const wrapper = mount(
); + const wrapper = mount(
); expect(observed).to.eql(1); expect(disconnected).to.eql(0); - wrapper.unmount(); + act(() => {wrapper.unmount()}); expect(observed).to.eql(1); expect(disconnected).to.eql(1); }); diff --git a/test/setup.js b/test/setup.js index 6cd9cc2..fdb18cc 100644 --- a/test/setup.js +++ b/test/setup.js @@ -1,5 +1,5 @@ import {configure} from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; +import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; import {JSDOM} from 'jsdom'; import sinon from 'sinon';