From b0e55faeafdc6f193e5fda338e5533e6f88725cf Mon Sep 17 00:00:00 2001 From: Alexander Karan <47707063+AlexanderKaran@users.noreply.github.com> Date: Fri, 24 Nov 2023 10:17:21 +0800 Subject: [PATCH] Rtl upgrade (#218) * Moved all tests to RTL * Updated testing config * Removed un-needed library * Updated tests to better checks * Removed un-needed comments --- jest.setup.js | 4 - package-lock.json | 1104 +---------------- package.json | 6 +- src/__tests__/integration.test.tsx | 64 +- src/controllers/redirect/test.tsx | 4 +- src/controllers/router-actions/test.tsx | 2 +- src/controllers/router-store/test.tsx | 16 +- src/controllers/router-subscriber/test.tsx | 4 +- src/controllers/router/test.tsx | 49 +- src/controllers/use-path-param/test.tsx | 17 +- src/controllers/use-query-param/test.tsx | 21 +- src/controllers/use-router-actions/test.tsx | 4 +- src/controllers/use-router/test.tsx | 4 +- src/controllers/use-timeout/test.tsx | 77 +- src/controllers/with-router/test.tsx | 197 +-- src/resources/__tests__/integration.test.tsx | 73 +- .../controllers/resource-store/test.tsx | 23 +- .../controllers/resource-subscriber/test.tsx | 35 +- .../controllers/use-resource/test.tsx | 35 +- src/ui/link/test.tsx | 250 ++-- src/ui/route-component/test.tsx | 15 +- 21 files changed, 474 insertions(+), 1530 deletions(-) diff --git a/jest.setup.js b/jest.setup.js index 5977e2b6..61c03cf8 100644 --- a/jest.setup.js +++ b/jest.setup.js @@ -1,8 +1,4 @@ import React from 'react'; -import Adapter from 'enzyme-adapter-react-16'; import '@testing-library/jest-dom/extend-expect'; -import { configure } from 'enzyme'; - -configure({ adapter: new Adapter() }); React.useLayoutEffect = React.useEffect; diff --git a/package-lock.json b/package-lock.json index 74a28372..0e8a3db5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,8 +34,8 @@ "@codeshift/test-utils": "^0.3.0", "@codeshift/utils": "^0.2.0", "@testing-library/jest-dom": "^5.7.0", - "@testing-library/react": "^10.0.4", - "@types/enzyme": "^3.10.5", + "@testing-library/react": "^10.4.9", + "@testing-library/user-event": "^14.5.1", "@types/history": "^4.7.6", "@types/history-5": "npm:@types/history@^5.0.0", "@types/jest": "^28.1.7", @@ -54,8 +54,6 @@ "babel-types": "^6.26.0", "docsify-cli": "^4.4.0", "dtslint": "^4.2.1", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.15.2", "eslint": "^8.22.0", "eslint-config-prettier": "^8.5.0", "eslint-import-resolver-typescript": "^3.5.2", @@ -4228,7 +4226,6 @@ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-10.4.9.tgz", "integrity": "sha512-pHZKkqUy0tmiD81afs8xfiuseXfU/N7rAX3iKjeZYje86t9VaB0LrxYVa+OOsvkrveX5jCK3IjajVn2MbePvqA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.3", "@testing-library/dom": "^7.22.3" @@ -4241,6 +4238,19 @@ "react-dom": "*" } }, + "node_modules/@testing-library/user-event": { + "version": "14.5.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.1.tgz", + "integrity": "sha512-UCcUKrUYGj7ClomOo2SpNVvx4/fkd/2BbIHDCle8A0ax+P3bU7yJwDBDrS6ZwdTMARWTGODX1hEsCcO+7beJjg==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -4322,16 +4332,6 @@ "@types/node": "*" } }, - "node_modules/@types/cheerio": { - "version": "0.22.31", - "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.31.tgz", - "integrity": "sha512-Kt7Cdjjdi2XWSfrZ53v4Of0wG3ZcmaegFXjMmz9tfNrZSkzzo36G0AL1YqSdcIA78Etjt6E609pt5h1xnQkPUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -4360,17 +4360,6 @@ "@types/ms": "*" } }, - "node_modules/@types/enzyme": { - "version": "3.10.12", - "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.12.tgz", - "integrity": "sha512-xryQlOEIe1TduDWAOphR0ihfebKFSWOXpIsk+70JskCfRfW+xALdnJ0r1ZOTo85F9Qsjk6vtlU7edTYHbls9tA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/cheerio": "*", - "@types/react": "*" - } - }, "node_modules/@types/express": { "version": "4.17.14", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", @@ -5422,30 +5411,6 @@ "node": ">= 6.0.0" } }, - "node_modules/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, - "license": "MIT", - "dependencies": { - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - }, - "peerDependencies": { - "react": "^0.14 || ^15.0.0 || ^16.0.0-alpha" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -5797,42 +5762,6 @@ "node": ">=0.10.0" } }, - "node_modules/array.prototype.filter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.1.tgz", - "integrity": "sha512-Dk3Ty7N42Odk7PjU/Ci3zT4pLj20YvuVnneG/58ICM6bt4Ij5kZaJTVQ9TSaWaIECX2sFyz4KItkVZqHNnciqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.find": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.2.0.tgz", - "integrity": "sha512-sn40qmUiLYAcRb/1HsIQjTTZ1kCy8II8VtZJpMn2Aoen9twULhbWXisfh3HimGqMlHGUul0/TfKCnXg42LuPpQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.4", - "es-shim-unscopables": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.flat": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", @@ -6689,13 +6618,6 @@ "multicast-dns": "^7.2.5" } }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, - "license": "ISC" - }, "node_modules/boxen": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", @@ -7296,46 +7218,6 @@ "inherits": "^2.0.1" } }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -8236,36 +8118,6 @@ "node": ">=8" } }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", @@ -8953,13 +8805,6 @@ "node": ">=8" } }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", - "dev": true, - "license": "MIT" - }, "node_modules/dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -9063,21 +8908,6 @@ "dev": true, "license": "MIT" }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, "node_modules/domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", @@ -9089,19 +8919,6 @@ "npm": ">=1.2" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, "node_modules/domexception": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", @@ -9125,22 +8942,6 @@ "node": ">=12" } }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, "node_modules/dompurify": { "version": "2.3.10", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.10.tgz", @@ -9148,21 +8949,6 @@ "dev": true, "license": "(MPL-2.0 OR Apache-2.0)" }, - "node_modules/domutils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.1" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -9438,19 +9224,6 @@ "node": ">=8.6" } }, - "node_modules/entities": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", - "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/envinfo": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", @@ -9465,122 +9238,6 @@ "node": ">=4" } }, - "node_modules/enzyme": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", - "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", - "dev": true, - "license": "MIT", - "dependencies": { - "array.prototype.flat": "^1.2.3", - "cheerio": "^1.0.0-rc.3", - "enzyme-shallow-equal": "^1.0.1", - "function.prototype.name": "^1.1.2", - "has": "^1.0.3", - "html-element-map": "^1.2.0", - "is-boolean-object": "^1.0.1", - "is-callable": "^1.1.5", - "is-number-object": "^1.0.4", - "is-regex": "^1.0.5", - "is-string": "^1.0.5", - "is-subset": "^0.1.1", - "lodash.escape": "^4.0.1", - "lodash.isequal": "^4.5.0", - "object-inspect": "^1.7.0", - "object-is": "^1.0.2", - "object.assign": "^4.1.0", - "object.entries": "^1.1.1", - "object.values": "^1.1.1", - "raf": "^3.4.1", - "rst-selector-parser": "^2.2.3", - "string.prototype.trim": "^1.2.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/enzyme-adapter-react-16": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.6.tgz", - "integrity": "sha512-yFlVJCXh8T+mcQo8M6my9sPgeGzj85HSHi6Apgf1Cvq/7EL/J9+1JoJmJsRxZgyTvPMAqOEpRSu/Ii/ZpyOk0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "enzyme-adapter-utils": "^1.14.0", - "enzyme-shallow-equal": "^1.0.4", - "has": "^1.0.3", - "object.assign": "^4.1.2", - "object.values": "^1.1.2", - "prop-types": "^15.7.2", - "react-is": "^16.13.1", - "react-test-renderer": "^16.0.0-0", - "semver": "^5.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - }, - "peerDependencies": { - "enzyme": "^3.0.0", - "react": "^16.0.0-0", - "react-dom": "^16.0.0-0" - } - }, - "node_modules/enzyme-adapter-react-16/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/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, - "license": "MIT", - "dependencies": { - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - }, - "peerDependencies": { - "react": "0.13.x || 0.14.x || ^15.0.0-0 || ^16.0.0-0" - } - }, - "node_modules/enzyme-adapter-utils/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/enzyme-shallow-equal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz", - "integrity": "sha512-MttIwB8kKxypwHvRynuC3ahyNc+cFbR8mjVIltnmzQ0uKGqmsfO4bfBuLxb0beLNPhjblUEYvEbsg+VSygvF1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has": "^1.0.3", - "object-is": "^1.1.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", @@ -9642,13 +9299,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true, - "license": "MIT" - }, "node_modules/es-shim-unscopables": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", @@ -12508,20 +12158,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/html-element-map": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.3.1.tgz", - "integrity": "sha512-6XMlxrAFX4UEEGxctfFnmrFaaZFNf9i5fNuV5wZ3WWQ4FVaNP1aX1LkX9j2mfEx1NpjeE/rL3nmgEn23GdFmrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array.prototype.filter": "^1.0.0", - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", @@ -12548,26 +12184,6 @@ "dev": true, "license": "MIT" }, - "node_modules/htmlparser2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", - "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "entities": "^4.3.0" - } - }, "node_modules/http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -13485,13 +13101,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==", - "dev": true, - "license": "MIT" - }, "node_modules/is-symbol": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", @@ -16746,27 +16355,6 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "license": "MIT" }, - "node_modules/lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -17569,13 +17157,6 @@ "dev": true, "license": "MIT" }, - "node_modules/moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -17681,36 +17262,6 @@ "dev": true, "license": "MIT" }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" - }, - "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" - } - }, - "node_modules/nearley/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "license": "MIT" - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -18038,19 +17589,6 @@ "set-blocking": "~2.0.0" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, "node_modules/number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -18190,23 +17728,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -18806,33 +18327,6 @@ "node": ">=6" } }, - "node_modules/parse5": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", - "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^4.3.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -19394,18 +18888,6 @@ "react-is": "^16.13.1" } }, - "node_modules/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, - "license": "MIT", - "dependencies": { - "has": "^1.0.3", - "object.assign": "^4.1.0", - "reflect.ownkeys": "^0.2.0" - } - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -19576,37 +19058,6 @@ "dev": true, "license": "MIT" }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "dev": true, - "license": "MIT", - "dependencies": { - "performance-now": "^2.1.0" - } - }, - "node_modules/railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -19749,33 +19200,6 @@ } } }, - "node_modules/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "react-is": "^16.8.6", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/react-test-renderer/node_modules/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, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -19853,13 +19277,6 @@ "node": ">=8" } }, - "node_modules/reflect.ownkeys": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", - "integrity": "sha512-qOLsBKHCpSOFKK1NUOCGC5VyeufB6lEsFe92AL2bhIJsacZS1qdoOZSbPk3MYKuT2cFlRDnulKXuuElIrMjGUg==", - "dev": true, - "license": "MIT" - }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -20294,17 +19711,6 @@ "inherits": "^2.0.1" } }, - "node_modules/rst-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", - "integrity": "sha512-nDG1rZeP6oFTLN6yNDV/uiAvs1+FS/KlrEwh7+y7dpuApDBy6bI2HTBcc0/V8lv9OTqfyD34eF7au2pm8aBbhA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "lodash.flattendeep": "^4.4.0", - "nearley": "^2.7.10" - } - }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -21610,24 +21016,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.6.tgz", - "integrity": "sha512-8lMR2m+U0VJTPp6JjvJTtGyc4FIGq9CdRt7O9p6T0e6K4vjU+OP+SQJpbe/SBmRcCUIvNUnjsbmY6lnMp8MhsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/string.prototype.trimend": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", @@ -27695,6 +27083,13 @@ "@testing-library/dom": "^7.22.3" } }, + "@testing-library/user-event": { + "version": "14.5.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.1.tgz", + "integrity": "sha512-UCcUKrUYGj7ClomOo2SpNVvx4/fkd/2BbIHDCle8A0ax+P3bU7yJwDBDrS6ZwdTMARWTGODX1hEsCcO+7beJjg==", + "dev": true, + "requires": {} + }, "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -27767,15 +27162,6 @@ "@types/node": "*" } }, - "@types/cheerio": { - "version": "0.22.31", - "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.31.tgz", - "integrity": "sha512-Kt7Cdjjdi2XWSfrZ53v4Of0wG3ZcmaegFXjMmz9tfNrZSkzzo36G0AL1YqSdcIA78Etjt6E609pt5h1xnQkPUw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -27804,16 +27190,6 @@ "@types/ms": "*" } }, - "@types/enzyme": { - "version": "3.10.12", - "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.12.tgz", - "integrity": "sha512-xryQlOEIe1TduDWAOphR0ihfebKFSWOXpIsk+70JskCfRfW+xALdnJ0r1ZOTo85F9Qsjk6vtlU7edTYHbls9tA==", - "dev": true, - "requires": { - "@types/cheerio": "*", - "@types/react": "*" - } - }, "@types/express": { "version": "4.17.14", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", @@ -28642,23 +28018,6 @@ "debug": "4" } }, - "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", @@ -28916,31 +28275,6 @@ "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", "dev": true }, - "array.prototype.filter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.1.tgz", - "integrity": "sha512-Dk3Ty7N42Odk7PjU/Ci3zT4pLj20YvuVnneG/58ICM6bt4Ij5kZaJTVQ9TSaWaIECX2sFyz4KItkVZqHNnciqw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - } - }, - "array.prototype.find": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.2.0.tgz", - "integrity": "sha512-sn40qmUiLYAcRb/1HsIQjTTZ1kCy8II8VtZJpMn2Aoen9twULhbWXisfh3HimGqMlHGUul0/TfKCnXg42LuPpQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.4", - "es-shim-unscopables": "^1.0.0" - } - }, "array.prototype.flat": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", @@ -29579,12 +28913,6 @@ "multicast-dns": "^7.2.5" } }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, "boxen": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", @@ -30018,35 +29346,6 @@ "inherits": "^2.0.1" } }, - "cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dev": true, - "requires": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - } - }, - "cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - } - }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -30720,25 +30019,6 @@ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true }, - "css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - } - }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true - }, "css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", @@ -31217,12 +30497,6 @@ "path-type": "^4.0.0" } }, - "discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", - "dev": true - }, "dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -31307,29 +30581,12 @@ "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==", "dev": true }, - "dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - } - }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, "domexception": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", @@ -31347,32 +30604,12 @@ } } }, - "domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "requires": { - "domelementtype": "^2.3.0" - } - }, "dompurify": { "version": "2.3.10", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.10.tgz", "integrity": "sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g==", "dev": true }, - "domutils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", - "dev": true, - "requires": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.1" - } - }, "dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -31591,12 +30828,6 @@ "ansi-colors": "^4.1.1" } }, - "entities": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", - "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==", - "dev": true - }, "envinfo": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", @@ -31604,94 +30835,6 @@ "dev": true, "peer": true }, - "enzyme": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", - "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", - "dev": true, - "requires": { - "array.prototype.flat": "^1.2.3", - "cheerio": "^1.0.0-rc.3", - "enzyme-shallow-equal": "^1.0.1", - "function.prototype.name": "^1.1.2", - "has": "^1.0.3", - "html-element-map": "^1.2.0", - "is-boolean-object": "^1.0.1", - "is-callable": "^1.1.5", - "is-number-object": "^1.0.4", - "is-regex": "^1.0.5", - "is-string": "^1.0.5", - "is-subset": "^0.1.1", - "lodash.escape": "^4.0.1", - "lodash.isequal": "^4.5.0", - "object-inspect": "^1.7.0", - "object-is": "^1.0.2", - "object.assign": "^4.1.0", - "object.entries": "^1.1.1", - "object.values": "^1.1.1", - "raf": "^3.4.1", - "rst-selector-parser": "^2.2.3", - "string.prototype.trim": "^1.2.1" - } - }, - "enzyme-adapter-react-16": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.6.tgz", - "integrity": "sha512-yFlVJCXh8T+mcQo8M6my9sPgeGzj85HSHi6Apgf1Cvq/7EL/J9+1JoJmJsRxZgyTvPMAqOEpRSu/Ii/ZpyOk0g==", - "dev": true, - "requires": { - "enzyme-adapter-utils": "^1.14.0", - "enzyme-shallow-equal": "^1.0.4", - "has": "^1.0.3", - "object.assign": "^4.1.2", - "object.values": "^1.1.2", - "prop-types": "^15.7.2", - "react-is": "^16.13.1", - "react-test-renderer": "^16.0.0-0", - "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "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" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "enzyme-shallow-equal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz", - "integrity": "sha512-MttIwB8kKxypwHvRynuC3ahyNc+cFbR8mjVIltnmzQ0uKGqmsfO4bfBuLxb0beLNPhjblUEYvEbsg+VSygvF1Q==", - "dev": true, - "requires": { - "has": "^1.0.3", - "object-is": "^1.1.2" - } - }, "errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", @@ -31741,12 +30884,6 @@ "unbox-primitive": "^1.0.2" } }, - "es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, "es-shim-unscopables": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", @@ -33797,16 +32934,6 @@ } } }, - "html-element-map": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.3.1.tgz", - "integrity": "sha512-6XMlxrAFX4UEEGxctfFnmrFaaZFNf9i5fNuV5wZ3WWQ4FVaNP1aX1LkX9j2mfEx1NpjeE/rL3nmgEn23GdFmrg==", - "dev": true, - "requires": { - "array.prototype.filter": "^1.0.0", - "call-bind": "^1.0.2" - } - }, "html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", @@ -33828,18 +32955,6 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "htmlparser2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", - "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", - "dev": true, - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "entities": "^4.3.0" - } - }, "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -34458,12 +33573,6 @@ "has-tostringtag": "^1.0.0" } }, - "is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==", - "dev": true - }, "is-symbol": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", @@ -36776,24 +35885,6 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, - "lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==", - "dev": true - }, - "lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "dev": true - }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -37381,12 +36472,6 @@ } } }, - "moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==", - "dev": true - }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -37472,26 +36557,6 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } - } - }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -37744,15 +36809,6 @@ "set-blocking": "~2.0.0" } }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -37851,16 +36907,6 @@ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", "dev": true }, - "object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -38284,25 +37330,6 @@ "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", "dev": true }, - "parse5": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", - "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", - "dev": true, - "requires": { - "entities": "^4.3.0" - } - }, - "parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "dev": true, - "requires": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - } - }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -38689,17 +37716,6 @@ "react-is": "^16.13.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" - } - }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -38827,31 +37843,6 @@ "integrity": "sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==", "dev": true }, - "raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "dev": true, - "requires": { - "performance-now": "^2.1.0" - } - }, - "railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", - "dev": true - }, - "randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dev": true, - "requires": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - } - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -38956,30 +37947,6 @@ "use-sync-external-store": "^1.0.0" } }, - "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==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "react-is": "^16.8.6", - "scheduler": "^0.19.1" - }, - "dependencies": { - "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" - } - } - } - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -39040,12 +38007,6 @@ "strip-indent": "^3.0.0" } }, - "reflect.ownkeys": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", - "integrity": "sha512-qOLsBKHCpSOFKK1NUOCGC5VyeufB6lEsFe92AL2bhIJsacZS1qdoOZSbPk3MYKuT2cFlRDnulKXuuElIrMjGUg==", - "dev": true - }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -39350,16 +38311,6 @@ "inherits": "^2.0.1" } }, - "rst-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", - "integrity": "sha512-nDG1rZeP6oFTLN6yNDV/uiAvs1+FS/KlrEwh7+y7dpuApDBy6bI2HTBcc0/V8lv9OTqfyD34eF7au2pm8aBbhA==", - "dev": true, - "requires": { - "lodash.flattendeep": "^4.4.0", - "nearley": "^2.7.10" - } - }, "run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -40370,17 +39321,6 @@ "side-channel": "^1.0.4" } }, - "string.prototype.trim": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.6.tgz", - "integrity": "sha512-8lMR2m+U0VJTPp6JjvJTtGyc4FIGq9CdRt7O9p6T0e6K4vjU+OP+SQJpbe/SBmRcCUIvNUnjsbmY6lnMp8MhsQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, "string.prototype.trimend": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", diff --git a/package.json b/package.json index 1b9c920b..adaa08df 100644 --- a/package.json +++ b/package.json @@ -90,8 +90,8 @@ "@codeshift/test-utils": "^0.3.0", "@codeshift/utils": "^0.2.0", "@testing-library/jest-dom": "^5.7.0", - "@testing-library/react": "^10.0.4", - "@types/enzyme": "^3.10.5", + "@testing-library/react": "^10.4.9", + "@testing-library/user-event": "^14.5.1", "@types/history": "^4.7.6", "@types/history-5": "npm:@types/history@^5.0.0", "@types/jest": "^28.1.7", @@ -110,8 +110,6 @@ "babel-types": "^6.26.0", "docsify-cli": "^4.4.0", "dtslint": "^4.2.1", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.15.2", "eslint": "^8.22.0", "eslint-config-prettier": "^8.5.0", "eslint-import-resolver-typescript": "^3.5.2", diff --git a/src/__tests__/integration.test.tsx b/src/__tests__/integration.test.tsx index 2f0b097a..649b2ae0 100644 --- a/src/__tests__/integration.test.tsx +++ b/src/__tests__/integration.test.tsx @@ -1,4 +1,4 @@ -import { mount } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import React, { Fragment } from 'react'; import { defaultRegistry } from 'react-sweet-state'; @@ -30,25 +30,17 @@ describe(' client-side integration tests', () => { const history = createMemoryHistory({ initialEntries: [location || routes[0].path], }); - const push: any = jest.spyOn(history, 'push'); - const waitForData = () => new Promise(resolve => setTimeout(resolve)); - const router = mount( + render( ); - return { - history: { - push, - }, - router, - waitForData, - }; + return { history }; } - it('renders route', async () => { + it('renders route', () => { const location = '/pathname?search=search#hash=hash'; const route = { component: () =>
test
, @@ -56,12 +48,12 @@ describe(' client-side integration tests', () => { path: location.substring(0, location.indexOf('?')), }; - const { router } = mountRouter({ routes: [route] }); + mountRouter({ routes: [route] }); - expect(router.html()).toBe('
test
'); + expect(screen.getByText('test')).toBeInTheDocument(); }); - it('triggers plugin.loadRoute when mounted', async () => { + it('triggers plugin.loadRoute when mounted', () => { const location = '/pathname?search=search#hash=hash'; const route = { component: () =>
test
, @@ -82,7 +74,7 @@ describe(' client-side integration tests', () => { expect(plugin.routeLoad).toBeCalled(); }); - it('renders next route', async () => { + it('renders next route', () => { const location = '/pathname?search=search#hash=hash'; const route = { component: () =>
first route
, @@ -96,16 +88,15 @@ describe(' client-side integration tests', () => { path: '/route2', }; - const { history, router } = mountRouter({ + const { history } = mountRouter({ routes: [route, route2], }); - expect(router.html()).toBe('
first route
'); + expect(screen.getByText('first route')).toBeInTheDocument(); history.push('/route2'); - router.update(); - expect(router.html()).toBe('
second route
'); + expect(screen.getByText('second route')).toBeInTheDocument(); }); it('triggers plugin.loadRoute after URL change', async () => { @@ -127,18 +118,14 @@ describe(' client-side integration tests', () => { routeLoad: jest.fn(), }; - const { history, router } = mountRouter({ + const { history } = mountRouter({ routes: [route, route2], plugins: [plugin], }); expect(plugin.routeLoad).toBeCalled(); - expect((plugin.routeLoad as any).mock.calls[0][0].context.route).toBe( - route - ); history.push('/route2'); - router.update(); expect((plugin.routeLoad as any).mock.calls[1][0].context.route).toBe( route2 @@ -146,7 +133,7 @@ describe(' client-side integration tests', () => { }); describe('route re-rendering', () => { - it('route loaded once as URL pathname did not change', async () => { + it('route loaded once as URL pathname did not change', () => { const location = '/pathname?search=search#hash=hash'; const route = { component: () =>
first route
, @@ -159,7 +146,7 @@ describe(' client-side integration tests', () => { routeLoad: jest.fn(), }; - const { history, router } = mountRouter({ + const { history } = mountRouter({ routes: [route], plugins: [plugin], }); @@ -167,12 +154,11 @@ describe(' client-side integration tests', () => { expect(plugin.routeLoad).toBeCalled(); history.push('/pathname?search=blah-blah-blah'); - router.update(); expect(plugin.routeLoad).toBeCalledTimes(1); }); - it('route loads twice as query params change', async () => { + it('route loads twice as query params change', () => { const location = '/pathname?search=search#hash=hash'; const route = { component: () =>
first route
, @@ -186,7 +172,7 @@ describe(' client-side integration tests', () => { routeLoad: jest.fn(), }; - const { history, router } = mountRouter({ + const { history } = mountRouter({ routes: [route], plugins: [plugin], location, @@ -195,12 +181,11 @@ describe(' client-side integration tests', () => { expect(plugin.routeLoad).toBeCalled(); history.push('/pathname?search=blah-blah-blah'); - router.update(); expect(plugin.routeLoad).toBeCalledTimes(2); }); - it('route loads once as defined query param did not change', async () => { + it('route loads once as defined query param did not change', () => { const location = '/pathname?search=search'; const route = { component: () =>
first route
, @@ -214,7 +199,7 @@ describe(' client-side integration tests', () => { routeLoad: jest.fn(), }; - const { history, router } = mountRouter({ + const { history } = mountRouter({ routes: [route], plugins: [plugin], location, @@ -223,7 +208,6 @@ describe(' client-side integration tests', () => { expect(plugin.routeLoad).toBeCalled(); history.push('/pathname?search=search&issue-key=1'); - router.update(); expect(plugin.routeLoad).toBeCalledTimes(1); }); @@ -241,8 +225,8 @@ describe(' server-side integration tests', () => { (isServerEnvironment as any).mockReturnValue(true); }); - it('renders the expected route when basePath is set', async () => { - const wrapper = mount( + it('renders the expected route when basePath is set', () => { + render( server-side integration tests', () => { ); - expect(wrapper.text()).toBe('route component'); + expect(screen.getByText('route component')).toBeInTheDocument(); }); - it('renders the expected route when basePath is not set', async () => { - const wrapper = mount( + it('renders the expected route when basePath is not set', () => { + render( server-side integration tests', () => { ); - expect(wrapper.text()).toBe('route component'); + expect(screen.getByText('route component')).toBeInTheDocument(); }); }); diff --git a/src/controllers/redirect/test.tsx b/src/controllers/redirect/test.tsx index 5c4087f4..641853c1 100644 --- a/src/controllers/redirect/test.tsx +++ b/src/controllers/redirect/test.tsx @@ -1,4 +1,4 @@ -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; import React from 'react'; import { defaultRegistry } from 'react-sweet-state'; @@ -41,7 +41,7 @@ const mockRoute: Route = { describe('', () => { const mountInRouter = (args: Partial) => - mount( + render( // @ts-expect-error diff --git a/src/controllers/router-actions/test.tsx b/src/controllers/router-actions/test.tsx index 2d192aac..426e8bf4 100644 --- a/src/controllers/router-actions/test.tsx +++ b/src/controllers/router-actions/test.tsx @@ -1,4 +1,4 @@ -import { render } from 'enzyme'; +import { render } from '@testing-library/react'; import noop from 'lodash.noop'; import React from 'react'; import { defaultRegistry } from 'react-sweet-state'; diff --git a/src/controllers/router-store/test.tsx b/src/controllers/router-store/test.tsx index 522f5bfd..ad96fe55 100644 --- a/src/controllers/router-store/test.tsx +++ b/src/controllers/router-store/test.tsx @@ -1,4 +1,4 @@ -import { mount } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import * as history4 from 'history'; import * as history5 from 'history-5'; import React from 'react'; @@ -50,7 +50,7 @@ describe('RouterStore', () => { const plugins = props.plugins || []; - mount( + render( { const RouteName = () => <>{useRouteName()}; const route = { - component: () => null, + component: () =>

home

, name: 'home', path: '', }; - const wrapper = mount( + render( { expect.objectContaining({ route }), undefined ); - expect(wrapper.html()).toEqual('home'); + expect(screen.getByText('home')).toBeInTheDocument(); }); it('should pass through single hook argument to selector', () => { @@ -582,12 +582,12 @@ describe('RouterStore', () => { ); const route = { - component: () => null, + component: () =>

home

, name: 'home', path: '', }; - const wrapper = mount( + render( { expect.objectContaining({ route }), 'bar' ); - expect(wrapper.html()).toEqual('home'); + expect(screen.getByText('home')).toBeInTheDocument(); }); }); }); diff --git a/src/controllers/router-subscriber/test.tsx b/src/controllers/router-subscriber/test.tsx index 5dae9476..9d7d9943 100644 --- a/src/controllers/router-subscriber/test.tsx +++ b/src/controllers/router-subscriber/test.tsx @@ -1,4 +1,4 @@ -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import React from 'react'; import * as isServerEnvironment from '../../common/utils/is-server-environment'; @@ -27,7 +27,7 @@ describe('', () => { // @ts-expect-error .mockImplementation(() => [state, { listen }]); - shallow({() =>
}); + render({() =>
}); return { listen }; } diff --git a/src/controllers/router/test.tsx b/src/controllers/router/test.tsx index 6835da95..7748a906 100644 --- a/src/controllers/router/test.tsx +++ b/src/controllers/router/test.tsx @@ -1,6 +1,6 @@ -import { mount } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import { createMemoryHistory } from 'history'; -import React, { ReactNode } from 'react'; +import React from 'react'; import { Route } from '../../common/types'; import * as isServerEnvironment from '../../common/utils/is-server-environment'; @@ -8,8 +8,15 @@ import * as isServerEnvironment from '../../common/utils/is-server-environment'; import { Router } from './index'; describe('', () => { + const basePath = '/basepath'; const history = createMemoryHistory(); - const routes: Route[] = []; + const routes: Route[] = [ + { + component: () =>

test

, + name: 'mock-route', + path: '/', + }, + ]; beforeEach(() => { jest @@ -23,35 +30,30 @@ describe('', () => { it('renders a RouterContainer', () => { const onPrefetch = jest.fn(); - const wrapper = mount( + render( + > +

test

+
); - const component = wrapper.find('RouterContainer'); - - expect(component).toHaveLength(1); - expect(component.props()).toMatchObject({ - basePath: '/basepath', - history, - onPrefetch, - routes, - }); + expect(screen.getByText('test')).toBeInTheDocument(); }); it('calls history.listen()() on unmount', () => { const unlisten = jest.fn(); jest.spyOn(history, 'listen').mockReturnValue(unlisten); - const wrapper = mount( + + const { unmount } = render( ); - wrapper.unmount(); + unmount(); expect(unlisten).toHaveBeenCalledTimes(1); }); @@ -62,7 +64,7 @@ describe('', () => { children, shouldRemount = false, }: { - children: ReactNode; + children: React.ReactNode; shouldRemount?: boolean; }) => { if (shouldRemount) { @@ -78,7 +80,7 @@ describe('', () => { listen.mockReturnValue(unlisten1); - const wrapper = mount( + const { rerender } = render( @@ -89,13 +91,14 @@ describe('', () => { listen.mockReturnValue(unlisten2); - // trigger the re-mount - wrapper.setProps({ shouldRemount: true }); + rerender( + + + + ); - // second listener is created by the RouterContainer on re-mount expect(listen).toHaveBeenCalledTimes(2); - // the original unlistener is called and the new one is not called expect(unlisten1).toHaveBeenCalled(); expect(unlisten2).not.toHaveBeenCalled(); }); diff --git a/src/controllers/use-path-param/test.tsx b/src/controllers/use-path-param/test.tsx index 0ee9c606..fbd90296 100644 --- a/src/controllers/use-path-param/test.tsx +++ b/src/controllers/use-path-param/test.tsx @@ -1,7 +1,6 @@ -import { mount } from 'enzyme'; +import { render, act } from '@testing-library/react'; import * as historyHelper from 'history'; import React from 'react'; -import { act } from 'react-dom/test-utils'; import { defaultRegistry } from 'react-sweet-state'; import { Router } from '../router'; @@ -61,7 +60,7 @@ describe('usePathParam()', () => { it('should return the right param value', () => { let ppVal: string | undefined; - mount( + render( {() => { @@ -78,7 +77,7 @@ describe('usePathParam()', () => { it('should return undefined for non-existent params', () => { let ppVal: string | undefined; - mount( + render( {() => { @@ -100,7 +99,7 @@ describe('usePathParam()', () => { updateType?: 'push' | 'replace' ) => void; - mount( + render( {() => { @@ -133,7 +132,7 @@ describe('usePathParam()', () => { let ppUpdateFn: (qp: string | undefined) => void; let renderCount = 0; - mount( + render( {() => { @@ -172,7 +171,7 @@ describe('usePathParam()', () => { updateType?: 'push' | 'replace' ) => void; - mount( + render( {() => { @@ -207,7 +206,7 @@ describe('usePathParam()', () => { component: () =>
path
, name: '', }; - mount( + render( { component: () =>
path
, name: '', }; - mount( + render( { }); it('should return the right param value', () => { - mount( + render( {() => { @@ -74,7 +73,7 @@ describe('useQueryParam()', () => { }); it('should return undefined for non-existent params', () => { - mount( + render( {() => { @@ -93,7 +92,7 @@ describe('useQueryParam()', () => { let qpVal: string | undefined; let qpUpdateFn: (qp: string) => void; - mount( + render( {() => { @@ -120,7 +119,7 @@ describe('useQueryParam()', () => { let qpVal: string | undefined; let qpUpdateFn: (qp: string, updateType?: 'push' | 'replace') => void; - mount( + render( {() => { @@ -150,7 +149,7 @@ describe('useQueryParam()', () => { let qpUpdateFn: (qp: string) => void; let renderCount = 0; - mount( + render( {() => { @@ -182,7 +181,7 @@ describe('useQueryParam()', () => { let qpVal: string | undefined; let qpUpdateFn: (qp: string, updateType?: 'push' | 'replace') => void; - mount( + render( {() => { @@ -209,7 +208,7 @@ describe('useQueryParam()', () => { let qpVal: string | undefined; let qpUpdateFn: (qp: string | undefined) => void; - mount( + render( {() => { @@ -258,7 +257,7 @@ describe('useQueryParam()', () => { return null; }; - mount( + render( { let barVal: string | undefined; let barUpdateFn: (qp: string) => void; - mount( + render( {() => { diff --git a/src/controllers/use-router-actions/test.tsx b/src/controllers/use-router-actions/test.tsx index 6e39e596..71592b01 100644 --- a/src/controllers/use-router-actions/test.tsx +++ b/src/controllers/use-router-actions/test.tsx @@ -1,4 +1,4 @@ -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; import React from 'react'; import { useRouterActions } from './index'; @@ -13,7 +13,7 @@ describe('useRouterActions()', () => { return null; } - mount(); + render(); expect(routerActions).toMatchInlineSnapshot(` Object { diff --git a/src/controllers/use-router/test.tsx b/src/controllers/use-router/test.tsx index d74e6cfa..2361c850 100644 --- a/src/controllers/use-router/test.tsx +++ b/src/controllers/use-router/test.tsx @@ -1,4 +1,4 @@ -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; import React from 'react'; import { useRouter } from './index'; @@ -17,7 +17,7 @@ describe('useRouter()', () => { return null; } - mount(); + render(); expect(state.location).toMatchInlineSnapshot(` Object { diff --git a/src/controllers/use-timeout/test.tsx b/src/controllers/use-timeout/test.tsx index e821d8ba..fa47b9a0 100644 --- a/src/controllers/use-timeout/test.tsx +++ b/src/controllers/use-timeout/test.tsx @@ -1,5 +1,7 @@ -import { shallow } from 'enzyme'; +import { render, screen } from '@testing-library/react'; +import { userEvent } from '@testing-library/user-event'; import React from 'react'; +import '@testing-library/jest-dom'; import { useTimeout } from './index'; @@ -16,8 +18,12 @@ const TestComponent = ({ return ( <> - + ); }; @@ -32,54 +38,73 @@ describe('useTimeout()', () => { jest.useRealTimers(); }); - it('calls setTimeout on schedule()', () => { - const setTimeout = jest.spyOn(global, 'setTimeout'); - const wrapper = shallow(); + it('calls setTimeout on schedule()', async () => { + const user = userEvent.setup({ + delay: DEFAULT_DELAY, + advanceTimers: delay => jest.advanceTimersByTime(delay), + }); + const callback = jest.fn(); + render(); - wrapper.find('#schedule').simulate('click'); + await user.click(screen.getByRole('button', { name: 'schedule' })); - expect(setTimeout).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenCalledTimes(1); }); - it('calls clearTimeout on cancel()', () => { + it('calls clearTimeout on cancel()', async () => { + const user = userEvent.setup({ + delay: DEFAULT_DELAY, + advanceTimers: delay => jest.advanceTimersByTime(delay), + }); const clearTimeout = jest.spyOn(global, 'clearTimeout'); - const wrapper = shallow(); + render(); - wrapper.find('#cancel').simulate('click'); + await user.click(screen.getByRole('button', { name: 'cancel' })); expect(clearTimeout).toHaveBeenCalledTimes(1); }); - it('schedules a callback to be fired', () => { + it('schedules a callback to be fired', async () => { + const user = userEvent.setup({ + delay: DEFAULT_DELAY, + advanceTimers: delay => jest.advanceTimersByTime(delay), + }); const callback = jest.fn(); - const wrapper = shallow(); + render(); - wrapper.find('#schedule').simulate('click'); - jest.runOnlyPendingTimers(); + await user.click(screen.getByRole('button', { name: 'schedule' })); expect(callback).toHaveBeenCalledTimes(1); }); - it('cancels a scheduled callback', () => { + it('cancels a scheduled callback', async () => { + const user = userEvent.setup({ + advanceTimers: delay => jest.advanceTimersByTime(delay), + }); const callback = jest.fn(); - const wrapper = shallow(); + render(); - wrapper.find('#schedule').simulate('click'); - wrapper.find('#cancel').simulate('click'); - jest.runAllTimers(); + await user.click(screen.getByRole('button', { name: 'schedule' })); + await user.click(screen.getByRole('button', { name: 'cancel' })); + + jest.advanceTimersByTime(DEFAULT_DELAY); expect(callback).not.toHaveBeenCalled(); }); - it('cancels a previously scheduled callback when schedule is called again', () => { + it('cancels a previously scheduled callback when schedule is called again', async () => { + const user = userEvent.setup({ + advanceTimers: delay => jest.advanceTimersByTime(delay), + }); const callback1 = jest.fn(); const callback2 = jest.fn(); - const wrapper = shallow(); + const { rerender } = render(); + + await user.click(screen.getByRole('button', { name: 'schedule' })); + rerender(); + await user.click(screen.getByRole('button', { name: 'schedule' })); - wrapper.find('#schedule').simulate('click'); - wrapper.setProps({ callback: callback2 }); - wrapper.find('#schedule').simulate('click'); - jest.runAllTimers(); + jest.advanceTimersByTime(DEFAULT_DELAY); expect(callback1).not.toHaveBeenCalled(); expect(callback2).toHaveBeenCalledTimes(1); diff --git a/src/controllers/with-router/test.tsx b/src/controllers/with-router/test.tsx index 15c3b2b4..9da0430e 100644 --- a/src/controllers/with-router/test.tsx +++ b/src/controllers/with-router/test.tsx @@ -1,4 +1,4 @@ -import { mount } from 'enzyme'; +import { render, screen, waitFor } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import React from 'react'; import { defaultRegistry } from 'react-sweet-state'; @@ -8,58 +8,65 @@ import { Router } from '../router'; import { withRouter } from './index'; -const waitALilBit = () => new Promise(resolve => setTimeout(resolve)); - jest.mock('../../common/utils/is-server-environment'); describe('withRouter()', () => { - const ComponentToBeWrapped = (props: any) => ( -
deep component {props.foo}
- ); - const ComponentWithRouter = withRouter(ComponentToBeWrapped); - beforeEach(() => { defaultRegistry.stores.clear(); }); - test('should pass original props to the wrapped component and set displayName', () => { - const wrapper = mount(); - expect(wrapper.find(ComponentToBeWrapped).prop('foo')).toEqual('bar'); - expect(wrapper.find('withRouter(ComponentToBeWrapped)')).toHaveLength(1); + it('should pass original props to the wrapped component and set displayName', () => { + const ComponentToBeWrapped = (props: any) => ( +
deep component {props.foo}
+ ); + const ComponentWithRouter = withRouter(ComponentToBeWrapped); + + render(); + expect(screen.getByText('deep component bar')).toBeInTheDocument(); }); - test('should provide match, route, location and history props to the wrapped component', () => { + it('should provide match, route, location and history props to the wrapped component', () => { const history = createMemoryHistory(); - const wrapper = mount( + const MockComponent = jest.fn(() => null); + const ComponentWithRouter = withRouter(MockComponent); + + render( ); - expect(wrapper.find(ComponentToBeWrapped).props()).toEqual({ - foo: 'bar', - location: expect.objectContaining({ - hash: '', - pathname: '/', - search: '', - }), - history, - match: expect.objectContaining({ - isExact: false, - path: expect.any(String), - url: expect.any(String), - params: expect.any(Object), + + expect(MockComponent).toHaveBeenCalledWith( + expect.objectContaining({ + foo: 'bar', + location: expect.objectContaining({ + hash: '', + pathname: '/', + search: '', + }), + history: expect.any(Object), + match: expect.objectContaining({ + isExact: expect.any(Boolean), + path: expect.any(String), + url: expect.any(String), + params: expect.any(Object), + query: expect.any(Object), + }), + route: DEFAULT_ROUTE, + action: DEFAULT_ACTION, query: expect.any(Object), + push: expect.any(Function), + replace: expect.any(Function), }), - route: DEFAULT_ROUTE, - action: DEFAULT_ACTION, - query: {}, - push: expect.any(Function), - replace: expect.any(Function), - }); + {} + ); }); - test('should provide the matched route and current location to the wrapped component', async () => { + it('should provide the matched route and current location to the wrapped component', async () => { const history = createMemoryHistory(); + const MockComponent = jest.fn(() => null); + const ComponentWithRouter = withRouter(MockComponent); + const routes = [ { name: 'Example A', @@ -74,85 +81,85 @@ describe('withRouter()', () => { { name: 'Example C', path: '/', component: () =>
Home
}, ]; - const wrapper = mount( + render( ); - expect(wrapper.find(ComponentToBeWrapped).props()).toMatchObject({ - location: { - hash: '', - pathname: '/', - search: '', - }, - match: { - isExact: true, - params: {}, - path: '/', - url: '/', - }, - action: DEFAULT_ACTION, - }); + // Initial route + expect(MockComponent).toHaveBeenCalledWith( + expect.objectContaining({ + location: expect.objectContaining({ + pathname: '/', + }), + match: expect.objectContaining({ + isExact: true, + params: {}, + }), + action: DEFAULT_ACTION, + }), + {} + ); history.push('/atlassian/jira'); - - await waitALilBit(); - - wrapper.update(); - expect(wrapper.find(ComponentToBeWrapped).props()).toMatchObject({ - location: { - hash: '', - pathname: '/atlassian/jira', - search: '', - }, - match: { - isExact: true, - params: { name: 'jira' }, - path: '/atlassian/:name', - url: '/atlassian/jira', - }, - action: 'PUSH', + await waitFor(() => { + expect(MockComponent).toHaveBeenCalledWith( + expect.objectContaining({ + location: expect.objectContaining({ + pathname: '/atlassian/jira', + }), + match: expect.objectContaining({ + params: { name: 'jira' }, + }), + action: 'PUSH', + }), + {} + ); }); history.replace('/atlassian/foo'); - - await waitALilBit(); - - wrapper.update(); - expect(wrapper.find(ComponentToBeWrapped).props()).toMatchObject({ - location: { - hash: '', - pathname: '/atlassian/foo', - search: '', - }, - match: { - isExact: true, - params: { name: 'foo' }, - path: '/atlassian/:name', - url: '/atlassian/foo', - }, - action: 'REPLACE', + await waitFor(() => { + expect(MockComponent).toHaveBeenCalledWith( + expect.objectContaining({ + location: expect.objectContaining({ + pathname: '/atlassian/foo', + }), + match: expect.objectContaining({ + params: { name: 'foo' }, + }), + action: 'REPLACE', + }), + {} + ); }); }); - test('should pass null match to the wrapped component when no route has matched', () => { + test('should pass null match to the wrapped component when no route has matched', async () => { const history = createMemoryHistory(); - const wrapper = mount( + const MockComponent = jest.fn(() => null); + const ComponentWithRouter = withRouter(MockComponent); + + render( ); + history.push('/blabla'); - wrapper.update(); - expect(wrapper.find(ComponentToBeWrapped).prop('match')).toEqual( - expect.objectContaining({ - isExact: false, - path: expect.any(String), - url: expect.any(String), - params: expect.any(Object), - query: expect.any(Object), - }) - ); + await waitFor(() => { + expect(MockComponent).toHaveBeenCalledWith( + expect.objectContaining({ + match: expect.objectContaining({ + isExact: false, + path: expect.any(String), + url: expect.any(String), + params: expect.any(Object), + query: expect.any(Object), + }), + }), + {} + ); + }); }); }); diff --git a/src/resources/__tests__/integration.test.tsx b/src/resources/__tests__/integration.test.tsx index d635d717..3f48cb12 100644 --- a/src/resources/__tests__/integration.test.tsx +++ b/src/resources/__tests__/integration.test.tsx @@ -1,4 +1,5 @@ -import { mount } from 'enzyme'; +import { render, screen, waitFor } from '@testing-library/react'; +import '@testing-library/jest-dom'; import { createMemoryHistory } from 'history'; import React, { Fragment } from 'react'; import { defaultRegistry } from 'react-sweet-state'; @@ -103,7 +104,7 @@ describe(' with resources client-side integration tests', () => { jest.useFakeTimers(); - mount( + render( with resources client-side integration tests', () => { function renderRouter(routes: Route[]) { const history = createMemoryHistory({ initialEntries: [routes[0].path] }); const push: any = jest.spyOn(history, 'push'); - const waitForData = () => new Promise(resolve => setTimeout(resolve)); - const router = mount( + render( + {/* Assuming RouteComponent and other relevant components are correctly set up */} ); - return { - history: { - push, - }, - router, - waitForData, - }; + return { history, push }; } function createResources() { @@ -250,21 +245,22 @@ describe(' with resources client-side integration tests', () => { resources: [cacheResource, networkResource], }; - const { history, router, waitForData } = renderRouter([route]); + const { history } = renderRouter([route]); - expect(router.html()).toBe('loading:cache loading:network'); - await waitForData(); + expect(screen.getByText(/loading:\s*cache/i)).toBeInTheDocument(); + expect(screen.getByText(/loading:\s*network/i)).toBeInTheDocument(); - router.update(); - expect(router.html()).toBe('data:cache-1 data:network-1'); + await waitFor(() => { + expect(screen.getByText(/data:\s*cache-1/i)).toBeInTheDocument(); + expect(screen.getByText(/data:\s*network-1/i)).toBeInTheDocument(); + }); history.push(route.path + '?query#hash'); - router.update(); - expect(router.html()).toBe('data:cache-1 data:network-1'); - await waitForData(); - router.update(); - expect(router.html()).toBe('data:cache-1 data:network-1'); + await waitFor(() => { + expect(screen.getByText(/data:\s*cache-1/i)).toBeInTheDocument(); + expect(screen.getByText(/data:\s*network-1/i)).toBeInTheDocument(); + }); }); it('fresh data when transitioning to a new route', async () => { @@ -286,20 +282,27 @@ describe(' with resources client-side integration tests', () => { }, ]; - const { history, router, waitForData } = renderRouter(routes); + const { history } = renderRouter(routes); - expect(router.html()).toBe('loading:cache loading:network'); - await waitForData(); - router.update(); - expect(router.html()).toBe('data:cache-1 data:network-1'); + expect(screen.getByText(/loading:\s*cache/i)).toBeInTheDocument(); + expect(screen.getByText(/loading:\s*network/i)).toBeInTheDocument(); + + await waitFor(() => { + expect(screen.getByText(/data:\s*cache-1/i)).toBeInTheDocument(); + expect(screen.getByText(/data:\s*network-1/i)).toBeInTheDocument(); + }); history.push(routes[1].path); - router.update(); - expect(router.html()).toBe('data:cache-1 loading:network'); - await waitForData(); - router.update(); - expect(router.html()).toBe('data:cache-1 data:network-2'); + await waitFor(() => { + expect(screen.getByText(/data:\s*cache-1/i)).toBeInTheDocument(); + expect(screen.getByText(/loading:\s*network/i)).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(screen.getByText(/data:\s*cache-1/i)).toBeInTheDocument(); + expect(screen.getByText(/data:\s*network-2/i)).toBeInTheDocument(); + }); }); }); }); @@ -316,7 +319,7 @@ describe(' server-side integration tests', () => { }); it('renders the expected route when basePath is set', async () => { - const wrapper = mount( + render( server-side integration tests', () => { ); - expect(wrapper.text()).toBe('route component'); + expect(screen.getByText('route component')).toBeInTheDocument(); }); it('renders the expected route when basePath is not set', async () => { - const wrapper = mount( + render( server-side integration tests', () => { ); - expect(wrapper.text()).toBe('route component'); + expect(screen.getByText('route component')).toBeInTheDocument(); }); }); diff --git a/src/resources/controllers/resource-store/test.tsx b/src/resources/controllers/resource-store/test.tsx index 07f4d7a2..bc4689f3 100644 --- a/src/resources/controllers/resource-store/test.tsx +++ b/src/resources/controllers/resource-store/test.tsx @@ -1,5 +1,6 @@ -import { mount } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import React from 'react'; +import '@testing-library/jest-dom'; import { BoundActions, defaultRegistry } from 'react-sweet-state'; import { isServerEnvironment } from '../../../common/utils/is-server-environment'; @@ -844,19 +845,19 @@ describe('resource store', () => { const { data, loading } = useResource(mockResource); if (loading) { - return
; + return
; } if (data) { - return
; + return
; } return null; }; - const wrapper = mount(); + render(); - expect(wrapper.find('#loading')).toHaveLength(1); - expect(wrapper.find('#data')).toHaveLength(0); + expect(screen.getByTestId('loading')).toBeInTheDocument(); + expect(screen.queryByTestId('data')).not.toBeInTheDocument(); }); it('should select the right resource slice out of the state', () => { @@ -927,20 +928,20 @@ describe('resource store', () => { const { data, loading } = useResource(mockResource); if (loading) { - return
; + return
; } if (data) { // @ts-ignore - return
; + return
; } return null; }; - const wrapper = mount(); + render(); - expect(wrapper.find('#loading')).toHaveLength(0); - expect(wrapper.find(`#${id}`)).toHaveLength(1); + expect(screen.queryByTestId('loading')).not.toBeInTheDocument(); + expect(screen.getByTestId(id)).toBeInTheDocument(); }); }); diff --git a/src/resources/controllers/resource-subscriber/test.tsx b/src/resources/controllers/resource-subscriber/test.tsx index e62d2157..92684856 100644 --- a/src/resources/controllers/resource-subscriber/test.tsx +++ b/src/resources/controllers/resource-subscriber/test.tsx @@ -1,6 +1,6 @@ -import { mount } from 'enzyme'; +import { render, act, screen } from '@testing-library/react'; import React from 'react'; -import { act } from 'react-dom/test-utils'; +import '@testing-library/jest-dom'; import { defaultRegistry } from 'react-sweet-state'; import { DEFAULT_MATCH, DEFAULT_ROUTE } from '../../../index'; @@ -63,25 +63,23 @@ describe('', () => { }, }); - const Component = () => ( + render( {({ data, loading }) => { if (loading) { - return
; + return
; } if (data) { - return
; + return
; } return null; }} ); - const wrapper = mount(); - - expect(wrapper.find('#loading')).toHaveLength(1); - expect(wrapper.find('#data')).toHaveLength(0); + expect(screen.getByTestId('loading')).toBeInTheDocument(); + expect(screen.queryByTestId('data')).not.toBeInTheDocument(); }); it('should get the slice of data for the type and key', async () => { @@ -98,15 +96,15 @@ describe('', () => { }, }); - const Component = () => ( + render( {({ data, loading }) => { if (loading) { - return
; + return
loading
; } if (data) { - return
; + return
data
; } return null; @@ -114,10 +112,8 @@ describe('', () => { ); - const wrapper = mount(); - - expect(wrapper.find('#loading')).toHaveLength(0); - expect(wrapper.find('#data')).toHaveLength(1); + expect(screen.getByText('data')).toBeInTheDocument(); + expect(screen.queryByText('loading')).not.toBeInTheDocument(); }); describe('update action', () => { @@ -131,7 +127,7 @@ describe('', () => { }, }, }); - mount( + render( {({ data, loading, update }) => { subscriberUpdate = update; @@ -152,7 +148,6 @@ describe('', () => { act(() => subscriberUpdate(() => newData)); const storeData = storeState.getState(); - expect(storeData.data[type][key]).toEqual({ ...mockSlice, data: newData, @@ -169,7 +164,7 @@ describe('', () => { }, }, }); - mount( + render( {({ data, loading, update }) => { subscriberUpdate = update; @@ -204,7 +199,7 @@ describe('', () => { .spyOn(actions, 'getResourceFromRemote') .mockImplementation(() => {}); let subscriberRefresh: any; - mount( + render( {({ data, loading, refresh }) => { subscriberRefresh = refresh; diff --git a/src/resources/controllers/use-resource/test.tsx b/src/resources/controllers/use-resource/test.tsx index 0cbee6c6..cd93c8d8 100644 --- a/src/resources/controllers/use-resource/test.tsx +++ b/src/resources/controllers/use-resource/test.tsx @@ -1,6 +1,6 @@ -import { mount } from 'enzyme'; +import { render, act } from '@testing-library/react'; import React from 'react'; -import { act } from 'react-dom/test-utils'; +import '@testing-library/jest-dom'; import { defaultRegistry } from 'react-sweet-state'; import { createRouterContext } from '../../../common/utils'; @@ -95,7 +95,7 @@ describe('useResource()', () => { }); it('should return the slice and bound actions for a given resource', () => { - mount( + render( {() => { const resource = useResource(mockResource); @@ -120,7 +120,7 @@ describe('useResource()', () => { it('should update a resource with the provided data', () => { const newData = 'my-better-data'; let resourceResponse: any; - mount( + render( {() => { resourceResponse = useResource(mockResource); @@ -145,7 +145,7 @@ describe('useResource()', () => { it('should update a resource with the data set to null', () => { const newData = null; let resourceResponse: any; - mount( + render( {() => { resourceResponse = useResource(mockResource); @@ -172,7 +172,7 @@ describe('useResource()', () => { const mockGetData = jest.fn(); let resourceResponse: any; - mount( + render( {() => { resourceResponse = useResource(mockResource); @@ -195,7 +195,7 @@ describe('useResource()', () => { .spyOn(actions, 'getResourceFromRemote') .mockImplementation(() => {}); let resourceResponse: any; - mount( + render( {() => { resourceResponse = useResource(mockResource); @@ -223,7 +223,7 @@ describe('useResource()', () => { getData: () => Promise.resolve('original-data'), }); let resourceResponse: any; - const wrapper = mount( + const { rerender } = render( {({ page }: { page: string }) => { resourceResponse = useResource(mockRes, { @@ -243,8 +243,19 @@ describe('useResource()', () => { data: 'new-data', }); - // should retrieve data also on router context change - wrapper.setProps({ page: 'page2' }); + rerender( + + {({ page }: { page: string }) => { + resourceResponse = useResource(mockRes, { + routerContext: createRouterContext(mockRoute, { + params: { page }, + }), + }); + + return

my test

; + }} +
+ ); act(() => resourceResponse.update(() => 'new-data-2')); expect(storeState.getState().data[mockType]['page2']).toMatchObject({ @@ -256,7 +267,7 @@ describe('useResource()', () => { describe('clear action', () => { it('should clear the resource', () => { let resourceResponse: any; - mount( + render( {() => { resourceResponse = useResource(mockResource); @@ -288,7 +299,7 @@ describe('useResource()', () => { let resourceResponse: any; - mount( + render( {() => { resourceResponse = useResource(mockResource); diff --git a/src/ui/link/test.tsx b/src/ui/link/test.tsx index 143f1d30..e3ab693c 100644 --- a/src/ui/link/test.tsx +++ b/src/ui/link/test.tsx @@ -1,6 +1,7 @@ -import { mount } from 'enzyme'; +import { render, screen, act } from '@testing-library/react'; +import { userEvent } from '@testing-library/user-event'; import React from 'react'; -import { act } from 'react-dom/test-utils'; +import '@testing-library/jest-dom'; import { defaultRegistry } from 'react-sweet-state'; import { LinkProps } from '../../common/types'; @@ -29,35 +30,23 @@ const defaultProps = { href: '/my-link', }; -const baseClickEvent = { - preventDefault: jest.fn(), - button: 0, -}; - const newPath = '/my-new-path'; -const eventModifiers = [['metaKey'], ['altKey'], ['ctrlKey'], ['shiftKey']]; - -// https://github.com/facebook/jest/pull/5267#issuecomment-356605468 -const withoutConsoleError = (fn: () => void) => () => { - const consoleError = jest - .spyOn(console, 'error') - .mockImplementation(() => undefined); - fn(); - consoleError.mockRestore(); -}; +// const eventModifiers = [['metaKey'], ['altKey'], ['ctrlKey'], ['shiftKey']]; +const eventModifiers = ['ShiftLeft', 'ControlLeft', 'AltLeft', 'MetaLeft']; describe('', () => { - const mountInRouter = ( + const renderInRouter = ( children: LinkProps['children'], props: Partial = defaultProps, basePath = '' - ) => - mount( + ) => { + return render( // @ts-expect-error {children} ); + }; afterEach(() => { jest.resetAllMocks(); @@ -65,137 +54,138 @@ describe('', () => { }); it('should render a ', () => { - const wrapper = mountInRouter('my link'); - const anchor = wrapper.find('a'); + renderInRouter('my link'); - expect(anchor.prop('href')).toEqual(defaultProps.href); + const anchor = screen.getByRole('link', { name: 'my link' }); + expect(anchor).toHaveAttribute('href', defaultProps.href); }); it('should support the `to` prop', () => { - const wrapper = mountInRouter('my link', { + renderInRouter('my link', { to: newPath, }); - const anchor = wrapper.find('a'); - - expect(anchor.prop('href')).toEqual(newPath); + const linkElement = screen.getByRole('link', { name: 'my link' }); + expect(linkElement).toHaveAttribute('href', newPath); }); it('should pass props to the child element', () => { - const wrapper = mountInRouter('my link', { + renderInRouter('my link', { ...defaultProps, // @ts-expect-error 'data-qa': '.my-test-class', }); - const component = wrapper.find('a'); - - expect(component).toHaveLength(1); - expect(component.prop('data-qa')).toEqual('.my-test-class'); - expect(component.prop('href')).toEqual(defaultProps.href); + const linkElement = screen.getByRole('link', { name: 'my link' }); + expect(linkElement).toHaveAttribute('data-qa', '.my-test-class'); + expect(linkElement).toHaveAttribute('href', defaultProps.href); }); it('should render as a button if the type prop is `button`', () => { - const wrapper = mountInRouter('my link', { type: 'button' }); - const component = wrapper.find('button'); - - expect(component).toHaveLength(1); + renderInRouter('my link', { type: 'button' }); + const buttonElement = screen.getByRole('button', { name: 'my link' }); + expect(buttonElement).toBeInTheDocument(); }); it('should render as an anchor if the type prop is neither `a` nor `button`', () => { // @ts-expect-error - const wrapper = mountInRouter('my link', { type: 'somethingwrong' }); - const component = wrapper.find('a'); - - expect(component).toHaveLength(1); + renderInRouter('my link', { type: 'somethingwrong' }); + const anchorElement = screen.getByRole('link', { name: 'my link' }); + expect(anchorElement).toBeInTheDocument(); }); - it('should use `history.push` to navigate on click', () => { - const wrapper = mountInRouter('my link', { href: newPath }); - const component = wrapper.find('Link'); + it('should use `history.push` to navigate on click', async () => { + const user = userEvent.setup(); + renderInRouter('my link', { href: newPath }); - component.simulate('click', baseClickEvent); + await user.click(screen.getByRole('link', { name: 'my link' })); expect(HistoryMock.push).toHaveBeenCalledTimes(1); expect(HistoryMock.push).toHaveBeenCalledWith(newPath, undefined); }); - it('should call `event.preventDefault() on navigation`', () => { - const wrapper = mountInRouter('my link', { href: newPath }); - const component = wrapper.find('Link'); + it('should call `event.preventDefault()` on navigation', () => { + renderInRouter('my link', { href: newPath }); + const linkElement = screen.getByRole('link', { name: 'my link' }); + + const mockPreventDefault = jest.fn(); - component.simulate('click', baseClickEvent); + const event = new MouseEvent('click', { bubbles: true }); + event.preventDefault = mockPreventDefault; - expect(baseClickEvent.preventDefault).toHaveBeenCalledTimes(1); + act(() => { + linkElement.dispatchEvent(event); + }); + + expect(mockPreventDefault).toHaveBeenCalledTimes(1); }); - it('should call the `onClick` prop when it is provided', () => { + it('should call the `onClick` prop when it is provided', async () => { + const user = userEvent.setup(); const mockOnClick = jest.fn(); - const wrapper = mountInRouter('my link', { + renderInRouter('my link', { href: newPath, onClick: mockOnClick, }); - const component = wrapper.find('Link'); - component.simulate('click', baseClickEvent); + await user.click(screen.getByRole('link', { name: 'my link' })); expect(mockOnClick).toHaveBeenCalledTimes(1); - expect(baseClickEvent.preventDefault).toHaveBeenCalledTimes(1); expect(HistoryMock.push).toHaveBeenCalledTimes(1); }); - it('should use `history.replace` to navigate when `replace` is `true`', () => { - const wrapper = mountInRouter('my link', { href: newPath, replace: true }); - const component = wrapper.find('Link'); + it('should use `history.replace` to navigate when `replace` is `true`', async () => { + const user = userEvent.setup(); + renderInRouter('my link', { href: newPath, replace: true }); - component.simulate('click', baseClickEvent); + await user.click(screen.getByRole('link', { name: 'my link' })); expect(HistoryMock.replace).toHaveBeenCalledTimes(1); expect(HistoryMock.replace).toHaveBeenCalledWith(newPath, undefined); }); describe('preventing navigation', () => { - it.each(eventModifiers)( - 'should not navigate if the %i modifier is present', - modifier => { - const wrapper = mountInRouter('my link', { href: newPath }); - const component = wrapper.find('Link'); + eventModifiers.forEach(modifier => { + it(`should not navigate if the ${modifier} modifier is present`, async () => { + const user = userEvent.setup(); + renderInRouter('my link', { href: newPath }); - component.simulate('click', { ...baseClickEvent, [modifier]: true }); + await user.keyboard(`[${modifier}>]`); + await user.click(screen.getByRole('link', { name: 'my link' })); - expect(HistoryMock.push).toHaveBeenCalledTimes(0); - } - ); + expect(HistoryMock.push).not.toHaveBeenCalled(); + }); + }); - it('should not navigate if the events default behaviour has already been prevented', () => { - const wrapper = mountInRouter('my link', { href: newPath }); - const component = wrapper.find('Link'); + it('should not navigate if the event’s default behavior has already been prevented', async () => { + const user = userEvent.setup(); + renderInRouter('my link', { href: newPath }); - component.simulate('click', { - ...baseClickEvent, - defaultPrevented: true, - }); + const linkElement = screen.getByRole('link', { name: 'my link' }); + linkElement.addEventListener('click', e => e.preventDefault()); + await user.click(linkElement); - expect(HistoryMock.push).toHaveBeenCalledTimes(0); + expect(HistoryMock.push).not.toHaveBeenCalled(); }); - it('should not navigate if the button that initiated the event was not a left-click', () => { - const wrapper = mountInRouter('my link', { href: newPath }); - const component = wrapper.find('Link'); + it('should not navigate if the button that initiated the event was not a left-click', async () => { + const user = userEvent.setup(); + renderInRouter('my link', { href: newPath }); - component.simulate('click', { ...baseClickEvent, button: 42 }); + const linkElement = screen.getByRole('link', { name: 'my link' }); + await user.pointer({ + target: linkElement, + keys: '[MouseRight]', + }); - expect(HistoryMock.push).toHaveBeenCalledTimes(0); + expect(HistoryMock.push).not.toHaveBeenCalled(); }); - it('should allow the browser to handle navigation if the Links target is not `_self`', () => { - const wrapper = mountInRouter('my link', { - href: newPath, - target: '_blank', - }); - const component = wrapper.find('Link'); + it('should allow the browser to handle navigation if the Link’s target is not `_self`', async () => { + const user = userEvent.setup(); + renderInRouter('my link', { href: newPath, target: '_blank' }); - component.simulate('click', baseClickEvent); + await user.click(screen.getByRole('link', { name: 'my link' })); - expect(HistoryMock.push).toHaveBeenCalledTimes(0); + expect(HistoryMock.push).not.toHaveBeenCalled(); }); }); @@ -207,7 +197,7 @@ describe('', () => { }; it('should render the correct link', () => { - const wrapper = mountInRouter( + renderInRouter( 'my link', { to: route, @@ -216,14 +206,15 @@ describe('', () => { }, '/base' ); - - expect(wrapper.html()).toEqual( - 'my link' + expect(screen.getByRole('link', { name: 'my link' })).toHaveAttribute( + 'href', + '/base/my-page/1?foo=bar' ); }); - it('should push history with correct link', () => { - const wrapper = mountInRouter( + it('should push history with correct link', async () => { + const user = userEvent.setup(); + renderInRouter( 'my link', { to: route, @@ -232,11 +223,9 @@ describe('', () => { }, '/base' ); - const component = wrapper.find('Link'); - component.simulate('click', baseClickEvent); + await user.click(screen.getByRole('link', { name: 'my link' })); - expect(HistoryMock.push).toHaveBeenCalledTimes(1); expect(HistoryMock.push).toHaveBeenCalledWith( { hash: '', @@ -248,20 +237,20 @@ describe('', () => { }); it('should handle async route imports', async () => { - const wrapper = mountInRouter('my link', { + const user = userEvent.setup(); + renderInRouter('my link', { to: Promise.resolve({ default: route }), params: { id: '1' }, query: { foo: 'bar' }, }); await act(() => Promise.resolve()); - const component = wrapper.find('Link'); - component.simulate('click', baseClickEvent); + await user.click(screen.getByRole('link', { name: 'my link' })); - expect(wrapper.html()).toEqual( - 'my link' + expect(screen.getByRole('link', { name: 'my link' })).toHaveAttribute( + 'href', + '/my-page/1?foo=bar' ); - expect(HistoryMock.push).toHaveBeenCalledTimes(1); expect(HistoryMock.push).toHaveBeenCalledWith( { hash: '', @@ -273,60 +262,55 @@ describe('', () => { }); it('should error if required route parameters are missing', () => { - expect( - withoutConsoleError(() => { - mountInRouter('my link', { to: route }); - }) - ).toThrow(); + const renderWithMissingParams = () => { + renderInRouter('my link', { to: route }); + }; + expect(renderWithMissingParams).toThrow(); }); }); describe('when the link has focus, and a keypress is fired', () => { - it('should navigate if the key was an `enter`', () => { - const wrapper = mountInRouter('my link', { href: newPath }); - const component = wrapper.find('Link'); - - component.simulate('click', { - ...baseClickEvent, - type: 'keypress', - keyCode: 13, - }); + it('should navigate if the key was an `enter`', async () => { + const user = userEvent.setup(); + renderInRouter('my link', { href: newPath }); + + const linkElement = screen.getByRole('link', { name: 'my link' }); + linkElement.focus(); + await user.keyboard('{Enter}'); expect(HistoryMock.push).toHaveBeenCalledTimes(1); expect(HistoryMock.push).toHaveBeenCalledWith(newPath, undefined); }); - it('should not navigate for any other key', () => { - const wrapper = mountInRouter('my link', { href: newPath }); - const component = wrapper.find('Link'); + it('should not navigate for any other key', async () => { + const user = userEvent.setup(); + renderInRouter('my link', { href: newPath }); - component.simulate('click', { - ...baseClickEvent, - type: 'keypress', - keyCode: 10, - }); + const linkElement = screen.getByRole('link', { name: 'my link' }); + linkElement.focus(); + await user.keyboard('{a}'); - expect(HistoryMock.push).toHaveBeenCalledTimes(0); + expect(HistoryMock.push).not.toHaveBeenCalled(); }); }); describe('when styles are passed into Link, element should be rendered with styles', () => { it('should add style to button when creating `button`', () => { - const wrapper = mountInRouter('my link', { + renderInRouter('my link', { type: 'button', style: { color: 'yellow' }, }); - const component = wrapper.find('button'); - expect(component.props()).toMatchObject({ style: { color: 'yellow' } }); + const buttonElement = screen.getByRole('button', { name: 'my link' }); + expect(buttonElement).toHaveStyle('color: yellow'); }); it('should add style to anchor when creating `a`', () => { - const wrapper = mountInRouter('my link', { + renderInRouter('my link', { to: 'abc', style: { color: 'yellow' }, }); - const anchor = wrapper.find('a'); - expect(anchor.props()).toMatchObject({ style: { color: 'yellow' } }); + const anchorElement = screen.getByRole('link', { name: 'my link' }); + expect(anchorElement).toHaveStyle('color: yellow'); }); }); }); diff --git a/src/ui/route-component/test.tsx b/src/ui/route-component/test.tsx index e97050a0..14fcfadb 100644 --- a/src/ui/route-component/test.tsx +++ b/src/ui/route-component/test.tsx @@ -1,5 +1,6 @@ -import { mount } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import React from 'react'; +import '@testing-library/jest-dom'; import { Router } from '../../controllers'; @@ -33,18 +34,16 @@ const routes = [ ]; describe('', () => { - it('renders a the route component', () => { - const wrapper = mount( + it('renders the route component', () => { + render( // @ts-expect-error ); - const component = wrapper.find(MockComponent); - - expect(component).toHaveLength(1); - - expect(component.prop('location')).toEqual(MockLocation); + // Check if the mock component is rendered + const component = screen.getByText('My component'); + expect(component).toBeInTheDocument(); }); });