diff --git a/CHANGELOG.md b/CHANGELOG.md index d5928ee8..16379d97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org). +## [3.10.1] - 2023-04-23 +### Added +* *Nothing* + +### Changed +* *Nothing* + +### Deprecated +* *Nothing* + +### Removed +* *Nothing* + +### Fixed +* [#826](https://github.com/shlinkio/shlink-web-client/issues/826) Fix generated short URLs CSV so that it can be used to import on Shlink. + + ## [3.10.0] - 2023-03-19 ### Added * [#807](https://github.com/shlinkio/shlink-web-client/issues/807) Add support for device-specific long-URLs when creating or editing short URLs. diff --git a/package-lock.json b/package-lock.json index c7d394ed..137c1214 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,7 +37,7 @@ "react-copy-to-clipboard": "^5.1.0", "react-datepicker": "^4.8.0", "react-dom": "^18.2.0", - "react-external-link": "^2.0.0", + "react-external-link": "^2.2.0", "react-leaflet": "^4.2.0", "react-redux": "^8.0.5", "react-router-dom": "^6.6.1", @@ -60,6 +60,7 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.4.3", + "@total-typescript/shoehorn": "^0.1.0", "@types/jest": "^29.2.4", "@types/json2csv": "^5.0.3", "@types/leaflet": "^1.9.0", @@ -72,7 +73,7 @@ "@types/react-dom": "^18.0.10", "@types/react-tag-autocomplete": "^6.3.0", "@types/uuid": "^8.3.4", - "@vitejs/plugin-react": "^3.1.0", + "@vitejs/plugin-react": "^4.0.0", "adm-zip": "^0.5.10", "babel-jest": "^29.5.0", "chalk": "^5.2.0", @@ -84,9 +85,8 @@ "resize-observer-polyfill": "^1.5.1", "sass": "^1.57.1", "stylelint": "^14.16.0", - "ts-mockery": "^1.2.0", "typescript": "^5.0.2", - "vite": "^4.2.0", + "vite": "^4.3.1", "vite-plugin-pwa": "^0.14.4" } }, @@ -118,8 +118,9 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "license": "MIT", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -128,30 +129,32 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.20.10", - "license": "MIT", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", + "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.20.7", - "license": "MIT", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", + "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.20.7", - "@babel/helpers": "^7.20.7", - "@babel/parser": "^7.20.7", + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", + "@babel/helper-compilation-targets": "^7.21.4", + "@babel/helper-module-transforms": "^7.21.2", + "@babel/helpers": "^7.21.0", + "@babel/parser": "^7.21.4", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7", + "@babel/traverse": "^7.21.4", + "@babel/types": "^7.21.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", + "json5": "^2.2.2", "semver": "^6.3.0" }, "engines": { @@ -189,11 +192,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.20.7", - "license": "MIT", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", + "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", "dependencies": { - "@babel/types": "^7.20.7", + "@babel/types": "^7.21.4", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -222,11 +227,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "license": "MIT", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", + "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.21.4", + "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" @@ -558,8 +564,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.7", - "license": "MIT", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", + "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1392,11 +1399,12 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.18.6", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.21.0.tgz", + "integrity": "sha512-f/Eq+79JEu+KUANFks9UZCcvydOOGMgF7jBrcwjHa5jTZD8JivnhCJYvmlhR/WTXBWonDExPoW0eO/CR4QJirA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1745,17 +1753,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.21.2", - "license": "MIT", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", + "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.1", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.2", - "@babel/types": "^7.21.2", + "@babel/parser": "^7.21.4", + "@babel/types": "^7.21.4", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1763,29 +1772,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.21.1", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.21.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/parser": { - "version": "7.21.2", - "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/traverse/node_modules/debug": { "version": "4.2.0", "license": "MIT", @@ -1806,8 +1792,9 @@ "license": "MIT" }, "node_modules/@babel/types": { - "version": "7.21.2", - "license": "MIT", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", + "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -3563,6 +3550,12 @@ "node": ">= 10" } }, + "node_modules/@total-typescript/shoehorn": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@total-typescript/shoehorn/-/shoehorn-0.1.0.tgz", + "integrity": "sha512-XKig6hXxWnUh0fsW3LR2vxpxwLlPFokfOSR0riHKA9uXvdHDfwOOPdAOi4U/YNKLmgYUu/plUfnF3yiAAz1+Zg==", + "dev": true + }, "node_modules/@types/aria-query": { "version": "4.2.2", "dev": true, @@ -4225,98 +4218,23 @@ } }, "node_modules/@vitejs/plugin-react": { - "version": "3.1.0", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.0.tgz", + "integrity": "sha512-HX0XzMjL3hhOYm+0s95pb0Z7F8O81G7joUHgfDd/9J/ZZf5k4xX6QAMFkKsHFxaHlf6X7GD7+XuaZ66ULiJuhQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/core": "^7.20.12", - "@babel/plugin-transform-react-jsx-self": "^7.18.6", + "@babel/core": "^7.21.4", + "@babel/plugin-transform-react-jsx-self": "^7.21.0", "@babel/plugin-transform-react-jsx-source": "^7.19.6", - "magic-string": "^0.27.0", "react-refresh": "^0.14.0" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "peerDependencies": { - "vite": "^4.1.0-beta.0" + "vite": "^4.2.0" } }, - "node_modules/@vitejs/plugin-react/node_modules/@babel/core": { - "version": "7.21.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.0", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.0", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.0", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@vitejs/plugin-react/node_modules/@babel/generator": { - "version": "7.21.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.21.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@vitejs/plugin-react/node_modules/@babel/parser": { - "version": "7.21.2", - "dev": true, - "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@vitejs/plugin-react/node_modules/debug": { - "version": "4.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@vitejs/plugin-react/node_modules/ms": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, "node_modules/@vitejs/plugin-react/node_modules/react-refresh": { "version": "0.14.0", "dev": true, @@ -4325,14 +4243,6 @@ "node": ">=0.10.0" } }, - "node_modules/@vitejs/plugin-react/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/abab": { "version": "2.0.6", "dev": true, @@ -4951,7 +4861,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001415", + "version": "1.0.30001480", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001480.tgz", + "integrity": "sha512-q7cpoPPvZYgtyC4VaBSN0Bt+PJ4c4EYRf0DrduInOz2SkFpHD5p3LnvEpqBp7UnJn+8x1Ogl1s38saUxe+ihQQ==", "funding": [ { "type": "opencollective", @@ -4960,9 +4872,12 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } - ], - "license": "CC-BY-4.0" + ] }, "node_modules/chalk": { "version": "5.2.0", @@ -10604,8 +10519,9 @@ } }, "node_modules/react-external-link": { - "version": "2.0.0", - "license": "MIT", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/react-external-link/-/react-external-link-2.2.0.tgz", + "integrity": "sha512-XH7XFvnsF4/ERKBoROOkh1f+YMWK4swXGB7l3OqrTzlABKYuOpD0QybOnDIMoc58vAjtiwRTRKE/UqMRoRD2xQ==", "peerDependencies": { "react": "^17.0 || ^18.0", "react-dom": "^17.0 || ^18.0" @@ -11084,9 +11000,10 @@ } }, "node_modules/rollup": { - "version": "3.18.0", + "version": "3.20.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.6.tgz", + "integrity": "sha512-2yEB3nQXp/tBQDN0hJScJQheXdvU2wFhh6ld7K/aiZ1vYcak6N/BKjY1QrU6BvO2JWYS8bEs14FRaxXosxy2zw==", "dev": true, - "license": "MIT", "bin": { "rollup": "dist/bin/rollup" }, @@ -11895,14 +11812,6 @@ "node": ">=8" } }, - "node_modules/ts-mockery": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "typescript": ">= 2.8" - } - }, "node_modules/ts-toolbelt": { "version": "6.15.5", "dev": true, @@ -12156,15 +12065,14 @@ } }, "node_modules/vite": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.2.0.tgz", - "integrity": "sha512-AbDTyzzwuKoRtMIRLGNxhLRuv1FpRgdIw+1y6AQG73Q5+vtecmvzKo/yk8X/vrHDpETRTx01ABijqUHIzBXi0g==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.1.tgz", + "integrity": "sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==", "dev": true, "dependencies": { "esbuild": "^0.17.5", "postcss": "^8.4.21", - "resolve": "^1.22.1", - "rollup": "^3.18.0" + "rollup": "^3.20.2" }, "bin": { "vite": "bin/vite.js" @@ -12964,31 +12872,37 @@ } }, "@babel/code-frame": { - "version": "7.18.6", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "requires": { "@babel/highlight": "^7.18.6" } }, "@babel/compat-data": { - "version": "7.20.10" + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", + "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==" }, "@babel/core": { - "version": "7.20.7", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", + "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.20.7", - "@babel/helpers": "^7.20.7", - "@babel/parser": "^7.20.7", + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", + "@babel/helper-compilation-targets": "^7.21.4", + "@babel/helper-module-transforms": "^7.21.2", + "@babel/helpers": "^7.21.0", + "@babel/parser": "^7.21.4", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7", + "@babel/traverse": "^7.21.4", + "@babel/types": "^7.21.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", + "json5": "^2.2.2", "semver": "^6.3.0" }, "dependencies": { @@ -13007,10 +12921,13 @@ } }, "@babel/generator": { - "version": "7.20.7", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", + "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", "requires": { - "@babel/types": "^7.20.7", + "@babel/types": "^7.21.4", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" } }, @@ -13028,10 +12945,12 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.20.7", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", + "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.21.4", + "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" @@ -13241,7 +13160,9 @@ } }, "@babel/parser": { - "version": "7.20.7" + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", + "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.18.6", @@ -13674,10 +13595,12 @@ } }, "@babel/plugin-transform-react-jsx-self": { - "version": "7.18.6", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.21.0.tgz", + "integrity": "sha512-f/Eq+79JEu+KUANFks9UZCcvydOOGMgF7jBrcwjHa5jTZD8JivnhCJYvmlhR/WTXBWonDExPoW0eO/CR4QJirA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-transform-react-jsx-source": { @@ -13902,32 +13825,22 @@ } }, "@babel/traverse": { - "version": "7.21.2", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", + "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.1", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.2", - "@babel/types": "^7.21.2", + "@babel/parser": "^7.21.4", + "@babel/types": "^7.21.4", "debug": "^4.1.0", "globals": "^11.1.0" }, "dependencies": { - "@babel/generator": { - "version": "7.21.1", - "requires": { - "@babel/types": "^7.21.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/parser": { - "version": "7.21.2" - }, "debug": { "version": "4.2.0", "requires": { @@ -13940,7 +13853,9 @@ } }, "@babel/types": { - "version": "7.21.2", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", + "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", "requires": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -14987,6 +14902,12 @@ "version": "2.0.0", "dev": true }, + "@total-typescript/shoehorn": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@total-typescript/shoehorn/-/shoehorn-0.1.0.tgz", + "integrity": "sha512-XKig6hXxWnUh0fsW3LR2vxpxwLlPFokfOSR0riHKA9uXvdHDfwOOPdAOi4U/YNKLmgYUu/plUfnF3yiAAz1+Zg==", + "dev": true + }, "@types/aria-query": { "version": "4.2.2", "dev": true @@ -15440,69 +15361,20 @@ } }, "@vitejs/plugin-react": { - "version": "3.1.0", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.0.tgz", + "integrity": "sha512-HX0XzMjL3hhOYm+0s95pb0Z7F8O81G7joUHgfDd/9J/ZZf5k4xX6QAMFkKsHFxaHlf6X7GD7+XuaZ66ULiJuhQ==", "dev": true, "requires": { - "@babel/core": "^7.20.12", - "@babel/plugin-transform-react-jsx-self": "^7.18.6", + "@babel/core": "^7.21.4", + "@babel/plugin-transform-react-jsx-self": "^7.21.0", "@babel/plugin-transform-react-jsx-source": "^7.19.6", - "magic-string": "^0.27.0", "react-refresh": "^0.14.0" }, "dependencies": { - "@babel/core": { - "version": "7.21.0", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.0", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.0", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.0", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - } - }, - "@babel/generator": { - "version": "7.21.1", - "dev": true, - "requires": { - "@babel/types": "^7.21.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/parser": { - "version": "7.21.2", - "dev": true - }, - "debug": { - "version": "4.3.4", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "dev": true - }, "react-refresh": { "version": "0.14.0", "dev": true - }, - "semver": { - "version": "6.3.0", - "dev": true } } }, @@ -15885,7 +15757,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001415" + "version": "1.0.30001480", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001480.tgz", + "integrity": "sha512-q7cpoPPvZYgtyC4VaBSN0Bt+PJ4c4EYRf0DrduInOz2SkFpHD5p3LnvEpqBp7UnJn+8x1Ogl1s38saUxe+ihQQ==" }, "chalk": { "version": "5.2.0", @@ -19450,7 +19324,9 @@ } }, "react-external-link": { - "version": "2.0.0", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/react-external-link/-/react-external-link-2.2.0.tgz", + "integrity": "sha512-XH7XFvnsF4/ERKBoROOkh1f+YMWK4swXGB7l3OqrTzlABKYuOpD0QybOnDIMoc58vAjtiwRTRKE/UqMRoRD2xQ==", "requires": {} }, "react-fast-compare": { @@ -19740,7 +19616,9 @@ } }, "rollup": { - "version": "3.18.0", + "version": "3.20.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.6.tgz", + "integrity": "sha512-2yEB3nQXp/tBQDN0hJScJQheXdvU2wFhh6ld7K/aiZ1vYcak6N/BKjY1QrU6BvO2JWYS8bEs14FRaxXosxy2zw==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -20275,11 +20153,6 @@ "version": "3.0.1", "dev": true }, - "ts-mockery": { - "version": "1.2.0", - "dev": true, - "requires": {} - }, "ts-toolbelt": { "version": "6.15.5", "dev": true @@ -20433,16 +20306,15 @@ } }, "vite": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.2.0.tgz", - "integrity": "sha512-AbDTyzzwuKoRtMIRLGNxhLRuv1FpRgdIw+1y6AQG73Q5+vtecmvzKo/yk8X/vrHDpETRTx01ABijqUHIzBXi0g==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.1.tgz", + "integrity": "sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==", "dev": true, "requires": { "esbuild": "^0.17.5", "fsevents": "~2.3.2", "postcss": "^8.4.21", - "resolve": "^1.22.1", - "rollup": "^3.18.0" + "rollup": "^3.20.2" } }, "vite-plugin-pwa": { diff --git a/package.json b/package.json index 66ebcd44..0a9a2eb5 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "react-copy-to-clipboard": "^5.1.0", "react-datepicker": "^4.8.0", "react-dom": "^18.2.0", - "react-external-link": "^2.0.0", + "react-external-link": "^2.2.0", "react-leaflet": "^4.2.0", "react-redux": "^8.0.5", "react-router-dom": "^6.6.1", @@ -77,6 +77,7 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.4.3", + "@total-typescript/shoehorn": "^0.1.0", "@types/jest": "^29.2.4", "@types/json2csv": "^5.0.3", "@types/leaflet": "^1.9.0", @@ -89,7 +90,7 @@ "@types/react-dom": "^18.0.10", "@types/react-tag-autocomplete": "^6.3.0", "@types/uuid": "^8.3.4", - "@vitejs/plugin-react": "^3.1.0", + "@vitejs/plugin-react": "^4.0.0", "adm-zip": "^0.5.10", "babel-jest": "^29.5.0", "chalk": "^5.2.0", @@ -101,9 +102,8 @@ "resize-observer-polyfill": "^1.5.1", "sass": "^1.57.1", "stylelint": "^14.16.0", - "ts-mockery": "^1.2.0", "typescript": "^5.0.2", - "vite": "^4.2.0", + "vite": "^4.3.1", "vite-plugin-pwa": "^0.14.4" }, "browserslist": [ diff --git a/src/common/services/ReportExporter.ts b/src/common/services/ReportExporter.ts index 2ea0cd11..d23b3bfe 100644 --- a/src/common/services/ReportExporter.ts +++ b/src/common/services/ReportExporter.ts @@ -24,7 +24,6 @@ export class ReportExporter { private readonly exportCsv = (filename: string, rows: object[]) => { const csv = this.jsonToCsv(rows); - saveCsv(this.window, csv, filename); }; } diff --git a/src/short-urls/data/index.ts b/src/short-urls/data/index.ts index 7d37e935..28219583 100644 --- a/src/short-urls/data/index.ts +++ b/src/short-urls/data/index.ts @@ -79,6 +79,8 @@ export interface ExportableShortUrl { createdAt: string; title: string; shortUrl: string; + domain?: string; + shortCode: string; longUrl: string; tags: string; visits: number; diff --git a/src/short-urls/helpers/ExportShortUrlsBtn.tsx b/src/short-urls/helpers/ExportShortUrlsBtn.tsx index 88f502e7..7fcc01ee 100644 --- a/src/short-urls/helpers/ExportShortUrlsBtn.tsx +++ b/src/short-urls/helpers/ExportShortUrlsBtn.tsx @@ -1,4 +1,5 @@ import type { FC } from 'react'; +import { useCallback } from 'react'; import type { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; import type { ReportExporter } from '../../common/services/ReportExporter'; import type { SelectedServer } from '../../servers/data'; @@ -24,7 +25,7 @@ export const ExportShortUrlsBtn = ( ): FC => ({ amount = 0, selectedServer }) => { const [{ tags, search, startDate, endDate, orderBy, tagsMode }] = useShortUrlsQuery(); const [loading,, startLoading, stopLoading] = useToggle(); - const exportAllUrls = async () => { + const exportAllUrls = useCallback(async () => { if (!isServerWithId(selectedServer)) { return; } @@ -47,16 +48,23 @@ export const ExportShortUrlsBtn = ( startLoading(); const shortUrls = await loadAllUrls(); - exportShortUrls(shortUrls.map((shortUrl) => ({ - createdAt: shortUrl.dateCreated, - shortUrl: shortUrl.shortUrl, - longUrl: shortUrl.longUrl, - title: shortUrl.title ?? '', - tags: shortUrl.tags.join(','), - visits: shortUrl?.visitsSummary?.total ?? shortUrl.visitsCount, - }))); + exportShortUrls(shortUrls.map((shortUrl) => { + const { hostname: domain, pathname } = new URL(shortUrl.shortUrl); + const shortCode = pathname.substring(1); // Remove trailing slash + + return { + createdAt: shortUrl.dateCreated, + domain, + shortCode, + shortUrl: shortUrl.shortUrl, + longUrl: shortUrl.longUrl, + title: shortUrl.title ?? '', + tags: shortUrl.tags.join('|'), + visits: shortUrl?.visitsSummary?.total ?? shortUrl.visitsCount, + }; + })); stopLoading(); - }; + }, [selectedServer]); return ; }; diff --git a/stryker.conf.js b/stryker.conf.js deleted file mode 100644 index 7a392fe1..00000000 --- a/stryker.conf.js +++ /dev/null @@ -1,32 +0,0 @@ -const jestConfig = require(`${__dirname}/jest.config.js`); - -module.exports = { - mutate: jestConfig.collectCoverageFrom, - checkers: [ 'typescript' ], - tsconfigFile: 'tsconfig.json', - testRunner: 'jest', - reporters: [ 'progress', 'clear-text' ], - ignorePatterns: [ - 'coverage', - 'reports', - 'build', - 'dist', - 'home', - 'scripts', - 'docker-compose.*', - 'public/servers.json*', - ], - jest: { - projectType: 'custom', - config: jestConfig, - enableFindRelatedTests: true, - }, - thresholds: { - high: 80, - low: 60, - break: null, - }, - clearTextReporter: { - logTests: false, - }, -}; diff --git a/test/__mocks__/Window.mock.ts b/test/__mocks__/Window.mock.ts index 69cb1f4e..dbd91da6 100644 --- a/test/__mocks__/Window.mock.ts +++ b/test/__mocks__/Window.mock.ts @@ -1,4 +1,4 @@ -import { Mock } from 'ts-mockery'; +import { fromAny, fromPartial } from '@total-typescript/shoehorn'; const createLinkMock = () => ({ setAttribute: jest.fn(), @@ -10,9 +10,9 @@ export const appendChild = jest.fn(); export const removeChild = jest.fn(); -export const windowMock = Mock.of({ - document: { +export const windowMock = fromPartial({ + document: fromAny({ createElement: jest.fn(createLinkMock), body: { appendChild, removeChild }, - }, + }), }); diff --git a/test/api/ShlinkApiError.test.tsx b/test/api/ShlinkApiError.test.tsx index daa42f69..1690b5ce 100644 --- a/test/api/ShlinkApiError.test.tsx +++ b/test/api/ShlinkApiError.test.tsx @@ -1,5 +1,5 @@ import { render, screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkApiErrorProps } from '../../src/api/ShlinkApiError'; import { ShlinkApiError } from '../../src/api/ShlinkApiError'; import type { InvalidArgumentError, ProblemDetailsError } from '../../src/api/types/errors'; @@ -10,8 +10,8 @@ describe('', () => { it.each([ [undefined, 'the fallback', 'the fallback'], - [Mock.all(), 'the fallback', 'the fallback'], - [Mock.of({ detail: 'the detail' }), 'the fallback', 'the detail'], + [fromPartial({}), 'the fallback', 'the fallback'], + [fromPartial({ detail: 'the detail' }), 'the fallback', 'the detail'], ])('renders proper message', (errorData, fallbackMessage, expectedMessage) => { const { container } = setUp({ errorData, fallbackMessage }); @@ -21,9 +21,9 @@ describe('', () => { it.each([ [undefined, 0], - [Mock.all(), 0], - [Mock.of({ type: ErrorTypeV2.INVALID_ARGUMENT, invalidElements: [] }), 1], - [Mock.of({ type: ErrorTypeV3.INVALID_ARGUMENT, invalidElements: [] }), 1], + [fromPartial({}), 0], + [fromPartial({ type: ErrorTypeV2.INVALID_ARGUMENT, invalidElements: [] }), 1], + [fromPartial({ type: ErrorTypeV3.INVALID_ARGUMENT, invalidElements: [] }), 1], ])('renders list of invalid elements when provided error is an InvalidError', (errorData, expectedElementsCount) => { setUp({ errorData }); expect(screen.queryAllByText(/^Invalid elements/)).toHaveLength(expectedElementsCount); diff --git a/test/api/services/ShlinkApiClient.test.ts b/test/api/services/ShlinkApiClient.test.ts index 408f6903..8423e68d 100644 --- a/test/api/services/ShlinkApiClient.test.ts +++ b/test/api/services/ShlinkApiClient.test.ts @@ -1,4 +1,4 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkDomain, ShlinkVisits, ShlinkVisitsOverview } from '../../../src/api/types'; import { ErrorTypeV2, ErrorTypeV3 } from '../../../src/api/types/errors'; @@ -9,7 +9,7 @@ import type { OptionalString } from '../../../src/utils/utils'; describe('ShlinkApiClient', () => { const fetchJson = jest.fn().mockResolvedValue({}); const fetchEmpty = jest.fn().mockResolvedValue(undefined); - const httpClient = Mock.of({ fetchJson, fetchEmpty }); + const httpClient = fromPartial({ fetchJson, fetchEmpty }); const buildApiClient = () => new ShlinkApiClient(httpClient, '', ''); const shortCodesWithDomainCombinations: [string, OptionalString][] = [ ['abc123', null], @@ -177,7 +177,7 @@ describe('ShlinkApiClient', () => { maxVisits: 50, validSince: '2025-01-01T10:00:00+01:00', }; - const expectedResp = Mock.of(); + const expectedResp = fromPartial({}); fetchJson.mockResolvedValue(expectedResp); const { updateShortUrl } = buildApiClient(); const expectedQuery = domain ? `?domain=${domain}` : ''; @@ -311,7 +311,7 @@ describe('ShlinkApiClient', () => { describe('listDomains', () => { it('returns domains', async () => { - const expectedData = { data: [Mock.all(), Mock.all()] }; + const expectedData = { data: [fromPartial({}), fromPartial({})] }; fetchJson.mockResolvedValue({ domains: expectedData }); const { listDomains } = buildApiClient(); @@ -324,7 +324,7 @@ describe('ShlinkApiClient', () => { describe('getVisitsOverview', () => { it('returns visits overview', async () => { - const expectedData = Mock.all(); + const expectedData = fromPartial({}); fetchJson.mockResolvedValue({ visits: expectedData }); const { getVisitsOverview } = buildApiClient(); @@ -337,7 +337,7 @@ describe('ShlinkApiClient', () => { describe('getOrphanVisits', () => { it('returns orphan visits', async () => { - fetchJson.mockResolvedValue({ visits: Mock.of({ data: [] }) }); + fetchJson.mockResolvedValue({ visits: fromPartial({ data: [] }) }); const { getOrphanVisits } = buildApiClient(); const result = await getOrphanVisits(); @@ -349,7 +349,7 @@ describe('ShlinkApiClient', () => { describe('getNonOrphanVisits', () => { it('returns non-orphan visits', async () => { - fetchJson.mockResolvedValue({ visits: Mock.of({ data: [] }) }); + fetchJson.mockResolvedValue({ visits: fromPartial({ data: [] }) }); const { getNonOrphanVisits } = buildApiClient(); const result = await getNonOrphanVisits(); diff --git a/test/api/services/ShlinkApiClientBuilder.test.ts b/test/api/services/ShlinkApiClientBuilder.test.ts index 3729bf07..af5d3faa 100644 --- a/test/api/services/ShlinkApiClientBuilder.test.ts +++ b/test/api/services/ShlinkApiClientBuilder.test.ts @@ -1,15 +1,13 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import { buildShlinkApiClient } from '../../../src/api/services/ShlinkApiClientBuilder'; -import type { HttpClient } from '../../../src/common/services/HttpClient'; -import type { ShlinkState } from '../../../src/container/types'; import type { ReachableServer, SelectedServer } from '../../../src/servers/data'; describe('ShlinkApiClientBuilder', () => { - const server = (data: Partial) => Mock.of(data); + const server = fromPartial; const createBuilder = () => { - const builder = buildShlinkApiClient(Mock.of()); - return (selectedServer: SelectedServer) => builder(() => Mock.of({ selectedServer })); + const builder = buildShlinkApiClient(fromPartial({})); + return (selectedServer: SelectedServer) => builder(() => fromPartial({ selectedServer })); }; it('creates new instances when provided params are different', async () => { @@ -42,7 +40,7 @@ describe('ShlinkApiClientBuilder', () => { it('does not fetch from state when provided param is already selected server', () => { const url = 'url'; const apiKey = 'apiKey'; - const apiClient = buildShlinkApiClient(Mock.of())(server({ url, apiKey })); + const apiClient = buildShlinkApiClient(fromPartial({}))(server({ url, apiKey })); expect(apiClient['baseUrl']).toEqual(url); // eslint-disable-line @typescript-eslint/dot-notation expect(apiClient['apiKey']).toEqual(apiKey); // eslint-disable-line @typescript-eslint/dot-notation diff --git a/test/app/App.test.tsx b/test/app/App.test.tsx index 345ce5d6..6063b05a 100644 --- a/test/app/App.test.tsx +++ b/test/app/App.test.tsx @@ -1,9 +1,8 @@ import { render, screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { createMemoryHistory } from 'history'; import { Router } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import { App as createApp } from '../../src/app/App'; -import type { Settings } from '../../src/settings/reducers/settings'; describe('', () => { const App = createApp( @@ -25,7 +24,7 @@ describe('', () => { {}} servers={{}} - settings={Mock.all()} + settings={fromPartial({})} appUpdated resetAppUpdate={() => {}} /> diff --git a/test/common/AsideMenu.test.tsx b/test/common/AsideMenu.test.tsx index 7e149e15..c0fa448a 100644 --- a/test/common/AsideMenu.test.tsx +++ b/test/common/AsideMenu.test.tsx @@ -1,14 +1,13 @@ import { render, screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import { AsideMenu as createAsideMenu } from '../../src/common/AsideMenu'; -import type { ReachableServer } from '../../src/servers/data'; describe('', () => { const AsideMenu = createAsideMenu(() => <>DeleteServerButton); const setUp = (id: string | false = 'abc123') => render( - ({ id: id || undefined, version: '2.8.0' })} /> + , ); diff --git a/test/common/ErrorHandler.test.tsx b/test/common/ErrorHandler.test.tsx index 67d271c4..41c82dde 100644 --- a/test/common/ErrorHandler.test.tsx +++ b/test/common/ErrorHandler.test.tsx @@ -1,5 +1,5 @@ import { render, screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import { ErrorHandler as createErrorHandler } from '../../src/common/ErrorHandler'; import { renderWithEvents } from '../__helpers__/setUpTest'; @@ -9,10 +9,10 @@ const ComponentWithError = () => { describe('', () => { const reload = jest.fn(); - const window = Mock.of({ + const window = fromPartial({ location: { reload }, }); - const cons = Mock.of({ error: jest.fn() }); + const cons = fromPartial({ error: jest.fn() }); const ErrorHandler = createErrorHandler(window, cons); beforeEach(() => { diff --git a/test/common/Home.test.tsx b/test/common/Home.test.tsx index 9f389c83..8e619b89 100644 --- a/test/common/Home.test.tsx +++ b/test/common/Home.test.tsx @@ -1,6 +1,6 @@ import { render, screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import { Home } from '../../src/common/Home'; import type { ServersMap, ServerWithId } from '../../src/servers/data'; @@ -19,9 +19,9 @@ describe('', () => { it.each([ [ { - '1a': Mock.of({ name: 'foo', id: '1' }), - '2b': Mock.of({ name: 'bar', id: '2' }), - '3c': Mock.of({ name: 'baz', id: '3' }), + '1a': fromPartial({ name: 'foo', id: '1' }), + '2b': fromPartial({ name: 'bar', id: '2' }), + '3c': fromPartial({ name: 'baz', id: '3' }), }, 3, ], diff --git a/test/common/MenuLayout.test.tsx b/test/common/MenuLayout.test.tsx index 644235f6..a6ae0191 100644 --- a/test/common/MenuLayout.test.tsx +++ b/test/common/MenuLayout.test.tsx @@ -1,9 +1,9 @@ import { render, screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { createMemoryHistory } from 'history'; import { Router, useParams } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import { MenuLayout as createMenuLayout } from '../../src/common/MenuLayout'; -import type { NonReachableServer, NotFoundServer, ReachableServer, SelectedServer } from '../../src/servers/data'; +import type { NonReachableServer, NotFoundServer, SelectedServer } from '../../src/servers/data'; import type { SemVer } from '../../src/utils/helpers/version'; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useParams: jest.fn() })); @@ -54,8 +54,8 @@ describe('', () => { }); it.each([ - [Mock.of({ serverNotFound: true })], - [Mock.of({ serverNotReachable: true })], + [fromPartial({ serverNotFound: true })], + [fromPartial({ serverNotReachable: true })], ])('shows error for non reachable servers', (selectedServer) => { setUp(selectedServer); @@ -81,7 +81,7 @@ describe('', () => { ])( 'renders expected component based on location and server version', (version, currentPath, expectedContent) => { - setUp(Mock.of({ version }), currentPath); + setUp(fromPartial({ version }), currentPath); expect(screen.getByText(expectedContent)).toBeInTheDocument(); }, ); diff --git a/test/common/ShlinkVersions.test.tsx b/test/common/ShlinkVersions.test.tsx index cd35d9d7..e079e9c8 100644 --- a/test/common/ShlinkVersions.test.tsx +++ b/test/common/ShlinkVersions.test.tsx @@ -1,5 +1,5 @@ import { render, screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkVersionsProps } from '../../src/common/ShlinkVersions'; import { ShlinkVersions } from '../../src/common/ShlinkVersions'; import type { NonReachableServer, NotFoundServer, ReachableServer } from '../../src/servers/data'; @@ -8,11 +8,11 @@ describe('', () => { const setUp = (props: ShlinkVersionsProps) => render(); it.each([ - ['1.2.3', Mock.of({ version: '1.0.0', printableVersion: 'foo' }), 'v1.2.3', 'foo'], - ['foo', Mock.of({ version: '1.0.0', printableVersion: '1.2.3' }), 'latest', '1.2.3'], - ['latest', Mock.of({ version: '1.0.0', printableVersion: 'latest' }), 'latest', 'latest'], - ['5.5.0', Mock.of({ version: '1.0.0', printableVersion: '0.2.8' }), 'v5.5.0', '0.2.8'], - ['not-semver', Mock.of({ version: '1.0.0', printableVersion: 'some' }), 'latest', 'some'], + ['1.2.3', fromPartial({ version: '1.0.0', printableVersion: 'foo' }), 'v1.2.3', 'foo'], + ['foo', fromPartial({ version: '1.0.0', printableVersion: '1.2.3' }), 'latest', '1.2.3'], + ['latest', fromPartial({ version: '1.0.0', printableVersion: 'latest' }), 'latest', 'latest'], + ['5.5.0', fromPartial({ version: '1.0.0', printableVersion: '0.2.8' }), 'v5.5.0', '0.2.8'], + ['not-semver', fromPartial({ version: '1.0.0', printableVersion: 'some' }), 'latest', 'some'], ])( 'displays expected versions when selected server is reachable', (clientVersion, selectedServer, expectedClientVersion, expectedServerVersion) => { @@ -34,8 +34,8 @@ describe('', () => { it.each([ ['1.2.3', null], - ['1.2.3', Mock.of({ serverNotFound: true })], - ['1.2.3', Mock.of({ serverNotReachable: true })], + ['1.2.3', fromPartial({ serverNotFound: true })], + ['1.2.3', fromPartial({ serverNotReachable: true })], ])('displays only client version when selected server is not reachable', (clientVersion, selectedServer) => { setUp({ clientVersion, selectedServer }); const links = screen.getAllByRole('link'); diff --git a/test/common/ShlinkVersionsContainer.test.tsx b/test/common/ShlinkVersionsContainer.test.tsx index 75f3143a..1676ebfa 100644 --- a/test/common/ShlinkVersionsContainer.test.tsx +++ b/test/common/ShlinkVersionsContainer.test.tsx @@ -1,12 +1,11 @@ import { render } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { Sidebar } from '../../src/common/reducers/sidebar'; import { ShlinkVersionsContainer } from '../../src/common/ShlinkVersionsContainer'; -import type { SelectedServer } from '../../src/servers/data'; describe('', () => { const setUp = (sidebar: Sidebar) => render( - ()} sidebar={sidebar} />, + , ); it.each([ diff --git a/test/common/services/ImageDownloader.test.ts b/test/common/services/ImageDownloader.test.ts index 498b9e60..d7c80dc7 100644 --- a/test/common/services/ImageDownloader.test.ts +++ b/test/common/services/ImageDownloader.test.ts @@ -1,11 +1,11 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { HttpClient } from '../../../src/common/services/HttpClient'; import { ImageDownloader } from '../../../src/common/services/ImageDownloader'; import { windowMock } from '../../__mocks__/Window.mock'; describe('ImageDownloader', () => { const fetchBlob = jest.fn(); - const httpClient = Mock.of({ fetchBlob }); + const httpClient = fromPartial({ fetchBlob }); let imageDownloader: ImageDownloader; beforeEach(() => { diff --git a/test/common/services/ReportExporter.test.ts b/test/common/services/ReportExporter.test.ts index 3d786787..8fdc9cce 100644 --- a/test/common/services/ReportExporter.test.ts +++ b/test/common/services/ReportExporter.test.ts @@ -53,6 +53,7 @@ describe('ReportExporter', () => { createdAt: '', longUrl: '', tags: '', + shortCode: '', }, ]; diff --git a/test/domains/DomainRow.test.tsx b/test/domains/DomainRow.test.tsx index 2fd4f26d..a6d2969a 100644 --- a/test/domains/DomainRow.test.tsx +++ b/test/domains/DomainRow.test.tsx @@ -1,17 +1,16 @@ import { render, screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkDomainRedirects } from '../../src/api/types'; import type { Domain } from '../../src/domains/data'; import { DomainRow } from '../../src/domains/DomainRow'; -import type { SelectedServer } from '../../src/servers/data'; describe('', () => { const redirectsCombinations = [ - [Mock.of({ baseUrlRedirect: 'foo' })], - [Mock.of({ invalidShortUrlRedirect: 'bar' })], - [Mock.of({ baseUrlRedirect: 'baz', regular404Redirect: 'foo' })], + [fromPartial({ baseUrlRedirect: 'foo' })], + [fromPartial({ invalidShortUrlRedirect: 'bar' })], + [fromPartial({ baseUrlRedirect: 'baz', regular404Redirect: 'foo' })], [ - Mock.of( + fromPartial( { baseUrlRedirect: 'baz', regular404Redirect: 'bar', invalidShortUrlRedirect: 'foo' }, ), ], @@ -22,7 +21,7 @@ describe('', () => { ()} + selectedServer={fromPartial({})} editDomainRedirects={jest.fn()} checkDomainHealth={jest.fn()} /> @@ -31,7 +30,7 @@ describe('', () => { ); it.each(redirectsCombinations)('shows expected redirects', (redirects) => { - setUp(Mock.of({ domain: '', isDefault: true, redirects })); + setUp(fromPartial({ domain: '', isDefault: true, redirects })); const cells = screen.getAllByRole('cell'); redirects?.baseUrlRedirect && expect(cells[1]).toHaveTextContent(redirects.baseUrlRedirect); @@ -42,9 +41,9 @@ describe('', () => { it.each([ [undefined], - [Mock.of()], + [fromPartial({})], ])('shows expected "no redirects"', (redirects) => { - setUp(Mock.of({ domain: '', isDefault: true, redirects })); + setUp(fromPartial({ domain: '', isDefault: true, redirects })); const cells = screen.getAllByRole('cell'); expect(cells[1]).toHaveTextContent('No redirect'); @@ -54,7 +53,7 @@ describe('', () => { }); it.each(redirectsCombinations)('shows expected fallback redirects', (fallbackRedirects) => { - setUp(Mock.of({ domain: '', isDefault: true }), fallbackRedirects); + setUp(fromPartial({ domain: '', isDefault: true }), fallbackRedirects); const cells = screen.getAllByRole('cell'); fallbackRedirects?.baseUrlRedirect && expect(cells[1]).toHaveTextContent( @@ -69,7 +68,7 @@ describe('', () => { }); it.each([[true], [false]])('shows icon on default domain only', (isDefault) => { - const { container } = setUp(Mock.of({ domain: '', isDefault })); + const { container } = setUp(fromPartial({ domain: '', isDefault })); if (isDefault) { expect(container.querySelector('#defaultDomainIcon')).toBeInTheDocument(); diff --git a/test/domains/DomainSelector.test.tsx b/test/domains/DomainSelector.test.tsx index 065201bc..008414af 100644 --- a/test/domains/DomainSelector.test.tsx +++ b/test/domains/DomainSelector.test.tsx @@ -1,16 +1,15 @@ import { screen, waitFor } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; -import type { ShlinkDomain } from '../../src/api/types'; +import { fromPartial } from '@total-typescript/shoehorn'; import { DomainSelector } from '../../src/domains/DomainSelector'; import type { DomainsList } from '../../src/domains/reducers/domainsList'; import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { - const domainsList = Mock.of({ + const domainsList = fromPartial({ domains: [ - Mock.of({ domain: 'default.com', isDefault: true }), - Mock.of({ domain: 'foo.com' }), - Mock.of({ domain: 'bar.com' }), + fromPartial({ domain: 'default.com', isDefault: true }), + fromPartial({ domain: 'foo.com' }), + fromPartial({ domain: 'bar.com' }), ], }); const setUp = (value = '') => renderWithEvents( diff --git a/test/domains/ManageDomains.test.tsx b/test/domains/ManageDomains.test.tsx index fc3c295d..30cf6048 100644 --- a/test/domains/ManageDomains.test.tsx +++ b/test/domains/ManageDomains.test.tsx @@ -1,10 +1,9 @@ import { screen, waitFor } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkDomain } from '../../src/api/types'; import type { ProblemDetailsError } from '../../src/api/types/errors'; import { ManageDomains } from '../../src/domains/ManageDomains'; import type { DomainsList } from '../../src/domains/reducers/domainsList'; -import type { SelectedServer } from '../../src/servers/data'; import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { @@ -17,14 +16,14 @@ describe('', () => { editDomainRedirects={jest.fn()} checkDomainHealth={jest.fn()} domainsList={domainsList} - selectedServer={Mock.all()} + selectedServer={fromPartial({})} />, ); afterEach(jest.clearAllMocks); it('shows loading message while domains are loading', () => { - setUp(Mock.of({ loading: true, filteredDomains: [] })); + setUp(fromPartial({ loading: true, filteredDomains: [] })); expect(screen.getByText('Loading...')).toBeInTheDocument(); expect(screen.queryByText('Error loading domains :(')).not.toBeInTheDocument(); @@ -32,17 +31,17 @@ describe('', () => { it.each([ [undefined, 'Error loading domains :('], - [Mock.of(), 'Error loading domains :('], - [Mock.of({ detail: 'Foo error!!' }), 'Foo error!!'], + [fromPartial({}), 'Error loading domains :('], + [fromPartial({ detail: 'Foo error!!' }), 'Foo error!!'], ])('shows error result when domains loading fails', (errorData, expectedErrorMessage) => { - setUp(Mock.of({ loading: false, error: true, errorData, filteredDomains: [] })); + setUp(fromPartial({ loading: false, error: true, errorData, filteredDomains: [] })); expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); expect(screen.getByText(expectedErrorMessage)).toBeInTheDocument(); }); it('filters domains when SearchField changes', async () => { - const { user } = setUp(Mock.of({ loading: false, error: false, filteredDomains: [] })); + const { user } = setUp(fromPartial({ loading: false, error: false, filteredDomains: [] })); expect(filterDomains).not.toHaveBeenCalled(); await user.type(screen.getByPlaceholderText('Search...'), 'Foo'); @@ -50,19 +49,19 @@ describe('', () => { }); it('shows expected headers and one row when list of domains is empty', () => { - setUp(Mock.of({ loading: false, error: false, filteredDomains: [] })); + setUp(fromPartial({ loading: false, error: false, filteredDomains: [] })); expect(screen.getAllByRole('columnheader')).toHaveLength(7); expect(screen.getByText('No results found')).toBeInTheDocument(); }); it('has many rows if multiple domains are provided', () => { - const filteredDomains = [ - Mock.of({ domain: 'foo' }), - Mock.of({ domain: 'bar' }), - Mock.of({ domain: 'baz' }), + const filteredDomains: ShlinkDomain[] = [ + fromPartial({ domain: 'foo' }), + fromPartial({ domain: 'bar' }), + fromPartial({ domain: 'baz' }), ]; - setUp(Mock.of({ loading: false, error: false, filteredDomains })); + setUp(fromPartial({ loading: false, error: false, filteredDomains })); expect(screen.getAllByRole('row')).toHaveLength(filteredDomains.length + 1); expect(screen.getByText('foo')).toBeInTheDocument(); diff --git a/test/domains/helpers/DomainDropdown.test.tsx b/test/domains/helpers/DomainDropdown.test.tsx index 6acd0b9b..f121978b 100644 --- a/test/domains/helpers/DomainDropdown.test.tsx +++ b/test/domains/helpers/DomainDropdown.test.tsx @@ -1,9 +1,9 @@ import { screen, waitForElementToBeRemoved } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { Domain } from '../../../src/domains/data'; import { DomainDropdown } from '../../../src/domains/helpers/DomainDropdown'; -import type { ReachableServer, SelectedServer } from '../../../src/servers/data'; +import type { SelectedServer } from '../../../src/servers/data'; import type { SemVer } from '../../../src/utils/helpers/version'; import { renderWithEvents } from '../../__helpers__/setUpTest'; @@ -12,8 +12,8 @@ describe('', () => { const setUp = (domain?: Domain, selectedServer?: SelectedServer) => renderWithEvents( ()} - selectedServer={selectedServer ?? Mock.all()} + domain={domain ?? fromPartial({})} + selectedServer={selectedServer ?? fromPartial({})} editDomainRedirects={editDomainRedirects} /> , @@ -33,8 +33,8 @@ describe('', () => { [false, ''], ])('points first link to the proper section', (isDefault, expectedLink) => { setUp( - Mock.of({ domain: 'foo.com', isDefault }), - Mock.of({ version: '3.1.0', id: '123' }), + fromPartial({ domain: 'foo.com', isDefault }), + fromPartial({ version: '3.1.0', id: '123' }), ); expect(screen.getByText('Visit stats')).toHaveAttribute('href', `/server/123/domain/foo.com${expectedLink}/visits`); @@ -46,8 +46,8 @@ describe('', () => { [false, '2.9.0' as SemVer, true], ])('allows editing certain the domains', (isDefault, serverVersion, canBeEdited) => { setUp( - Mock.of({ domain: 'foo.com', isDefault }), - Mock.of({ version: serverVersion, id: '123' }), + fromPartial({ domain: 'foo.com', isDefault }), + fromPartial({ version: serverVersion, id: '123' }), ); if (canBeEdited) { @@ -62,7 +62,7 @@ describe('', () => { ['bar.org'], ['baz.net'], ])('displays modal when editing redirects', async (domain) => { - const { user } = setUp(Mock.of({ domain, isDefault: false })); + const { user } = setUp(fromPartial({ domain, isDefault: false })); expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); expect(screen.queryByRole('form')).not.toBeInTheDocument(); diff --git a/test/domains/helpers/DomainStatusIcon.test.tsx b/test/domains/helpers/DomainStatusIcon.test.tsx index ee5d3410..d695a92b 100644 --- a/test/domains/helpers/DomainStatusIcon.test.tsx +++ b/test/domains/helpers/DomainStatusIcon.test.tsx @@ -1,11 +1,11 @@ import { screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { DomainStatus } from '../../../src/domains/data'; import { DomainStatusIcon } from '../../../src/domains/helpers/DomainStatusIcon'; import { renderWithEvents } from '../../__helpers__/setUpTest'; describe('', () => { - const matchMedia = jest.fn().mockReturnValue(Mock.of({ matches: false })); + const matchMedia = jest.fn().mockReturnValue(fromPartial({ matches: false })); const setUp = (status: DomainStatus) => renderWithEvents( , ); diff --git a/test/domains/helpers/EditDomainRedirectsModal.test.tsx b/test/domains/helpers/EditDomainRedirectsModal.test.tsx index fb9a98fc..dad4e887 100644 --- a/test/domains/helpers/EditDomainRedirectsModal.test.tsx +++ b/test/domains/helpers/EditDomainRedirectsModal.test.tsx @@ -1,5 +1,5 @@ import { fireEvent, screen, waitFor } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkDomain } from '../../../src/api/types'; import { EditDomainRedirectsModal } from '../../../src/domains/helpers/EditDomainRedirectsModal'; import { renderWithEvents } from '../../__helpers__/setUpTest'; @@ -7,7 +7,7 @@ import { renderWithEvents } from '../../__helpers__/setUpTest'; describe('', () => { const editDomainRedirects = jest.fn().mockResolvedValue(undefined); const toggle = jest.fn(); - const domain = Mock.of({ + const domain = fromPartial({ domain: 'foo.com', redirects: { baseUrlRedirect: 'baz', diff --git a/test/domains/reducers/domainRedirects.test.ts b/test/domains/reducers/domainRedirects.test.ts index 99c41554..e9f092b9 100644 --- a/test/domains/reducers/domainRedirects.test.ts +++ b/test/domains/reducers/domainRedirects.test.ts @@ -1,7 +1,6 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkDomainRedirects } from '../../../src/api/types'; -import type { EditDomainRedirects } from '../../../src/domains/reducers/domainRedirects'; import { editDomainRedirects } from '../../../src/domains/reducers/domainRedirects'; describe('domainRedirectsReducer', () => { @@ -9,17 +8,17 @@ describe('domainRedirectsReducer', () => { describe('editDomainRedirects', () => { const domain = 'example.com'; - const redirects = Mock.all(); + const redirects = fromPartial({}); const dispatch = jest.fn(); const getState = jest.fn(); const editDomainRedirectsCall = jest.fn(); - const buildShlinkApiClient = () => Mock.of({ editDomainRedirects: editDomainRedirectsCall }); + const buildShlinkApiClient = () => fromPartial({ editDomainRedirects: editDomainRedirectsCall }); const editDomainRedirectsAction = editDomainRedirects(buildShlinkApiClient); it('dispatches domain and redirects once loaded', async () => { editDomainRedirectsCall.mockResolvedValue(redirects); - await editDomainRedirectsAction(Mock.of({ domain }))(dispatch, getState, {}); + await editDomainRedirectsAction(fromPartial({ domain }))(dispatch, getState, {}); expect(dispatch).toHaveBeenCalledTimes(2); expect(dispatch).toHaveBeenLastCalledWith(expect.objectContaining({ diff --git a/test/domains/reducers/domainsList.test.ts b/test/domains/reducers/domainsList.test.ts index 842f8ab5..9381e671 100644 --- a/test/domains/reducers/domainsList.test.ts +++ b/test/domains/reducers/domainsList.test.ts @@ -1,4 +1,4 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkDomainRedirects } from '../../../src/api/types'; import { parseApiError } from '../../../src/api/utils'; @@ -6,26 +6,23 @@ import type { ShlinkState } from '../../../src/container/types'; import type { Domain } from '../../../src/domains/data'; import type { EditDomainRedirects } from '../../../src/domains/reducers/domainRedirects'; import { editDomainRedirects } from '../../../src/domains/reducers/domainRedirects'; -import type { - DomainsList } from '../../../src/domains/reducers/domainsList'; import { domainsListReducerCreator, replaceRedirectsOnDomain, replaceStatusOnDomain, } from '../../../src/domains/reducers/domainsList'; -import type { SelectedServer, ServerData } from '../../../src/servers/data'; describe('domainsListReducer', () => { const dispatch = jest.fn(); const getState = jest.fn(); const listDomains = jest.fn(); const health = jest.fn(); - const buildShlinkApiClient = () => Mock.of({ listDomains, health }); - const filteredDomains = [ - Mock.of({ domain: 'foo', status: 'validating' }), - Mock.of({ domain: 'Boo', status: 'validating' }), + const buildShlinkApiClient = () => fromPartial({ listDomains, health }); + const filteredDomains: Domain[] = [ + fromPartial({ domain: 'foo', status: 'validating' }), + fromPartial({ domain: 'Boo', status: 'validating' }), ]; - const domains = [...filteredDomains, Mock.of({ domain: 'bar', status: 'validating' })]; + const domains: Domain[] = [...filteredDomains, fromPartial({ domain: 'bar', status: 'validating' })]; const error = { type: 'NOT_FOUND', status: 404 } as unknown as Error; const editDomainRedirectsThunk = editDomainRedirects(buildShlinkApiClient); const { reducer, listDomains: listDomainsAction, checkDomainHealth, filterDomains } = domainsListReducerCreator( @@ -55,7 +52,7 @@ describe('domainsListReducer', () => { }); it('filters domains on FILTER_DOMAINS', () => { - expect(reducer(Mock.of({ domains }), filterDomains('oO'))).toEqual({ domains, filteredDomains }); + expect(reducer(fromPartial({ domains }), filterDomains('oO'))).toEqual({ domains, filteredDomains }); }); it.each([ @@ -71,7 +68,7 @@ describe('domainsListReducer', () => { const editDomainRedirects: EditDomainRedirects = { domain, redirects }; expect(reducer( - Mock.of({ domains, filteredDomains }), + fromPartial({ domains, filteredDomains }), editDomainRedirectsThunk.fulfilled(editDomainRedirects, '', editDomainRedirects), )).toEqual({ domains: domains.map(replaceRedirectsOnDomain(editDomainRedirects)), @@ -85,7 +82,7 @@ describe('domainsListReducer', () => { ['does_not_exist'], ])('replaces status on proper domain on VALIDATE_DOMAIN', (domain) => { expect(reducer( - Mock.of({ domains, filteredDomains }), + fromPartial({ domains, filteredDomains }), checkDomainHealth.fulfilled({ domain, status: 'valid' }, '', ''), )).toEqual({ domains: domains.map(replaceStatusOnDomain(domain, 'valid')), @@ -122,8 +119,8 @@ describe('domainsListReducer', () => { const domain = 'example.com'; it('dispatches invalid status when selected server does not have all required data', async () => { - getState.mockReturnValue(Mock.of({ - selectedServer: Mock.all(), + getState.mockReturnValue(fromPartial({ + selectedServer: {}, })); await checkDomainHealth(domain)(dispatch, getState, {}); @@ -136,11 +133,11 @@ describe('domainsListReducer', () => { }); it('dispatches invalid status when health endpoint returns an error', async () => { - getState.mockReturnValue(Mock.of({ - selectedServer: Mock.of({ + getState.mockReturnValue(fromPartial({ + selectedServer: { url: 'https://myerver.com', apiKey: '123', - }), + }, })); health.mockRejectedValue({}); @@ -160,11 +157,11 @@ describe('domainsListReducer', () => { healthStatus, expectedStatus, ) => { - getState.mockReturnValue(Mock.of({ - selectedServer: Mock.of({ + getState.mockReturnValue(fromPartial({ + selectedServer: { url: 'https://myerver.com', apiKey: '123', - }), + }, })); health.mockResolvedValue({ status: healthStatus }); diff --git a/test/mercure/helpers/index.test.tsx b/test/mercure/helpers/index.test.tsx index 335cd79c..15a76d15 100644 --- a/test/mercure/helpers/index.test.tsx +++ b/test/mercure/helpers/index.test.tsx @@ -1,6 +1,6 @@ +import { fromPartial } from '@total-typescript/shoehorn'; import { EventSourcePolyfill } from 'event-source-polyfill'; import { identity } from 'ramda'; -import { Mock } from 'ts-mockery'; import { bindToMercureTopic } from '../../../src/mercure/helpers'; import type { MercureInfo } from '../../../src/mercure/reducers/mercureInfo'; @@ -14,11 +14,11 @@ describe('helpers', () => { const onTokenExpired = jest.fn(); it.each([ - [Mock.of({ loading: true, error: false, mercureHubUrl: 'foo' })], - [Mock.of({ loading: false, error: true, mercureHubUrl: 'foo' })], - [Mock.of({ loading: true, error: true, mercureHubUrl: 'foo' })], - [Mock.of({ loading: false, error: false, mercureHubUrl: undefined })], - [Mock.of({ loading: true, error: true, mercureHubUrl: undefined })], + [fromPartial({ loading: true, error: false, mercureHubUrl: 'foo' })], + [fromPartial({ loading: false, error: true, mercureHubUrl: 'foo' })], + [fromPartial({ loading: true, error: true, mercureHubUrl: 'foo' })], + [fromPartial({ loading: false, error: false, mercureHubUrl: undefined })], + [fromPartial({ loading: true, error: true, mercureHubUrl: undefined })], ])('does not bind an EventSource when loading, error or no hub URL', (mercureInfo) => { bindToMercureTopic(mercureInfo, [''], identity, () => {}); diff --git a/test/mercure/reducers/mercureInfo.test.ts b/test/mercure/reducers/mercureInfo.test.ts index 27be5710..907a7b67 100644 --- a/test/mercure/reducers/mercureInfo.test.ts +++ b/test/mercure/reducers/mercureInfo.test.ts @@ -1,4 +1,4 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { GetState } from '../../../src/container/types'; import { mercureInfoReducerCreator } from '../../../src/mercure/reducers/mercureInfo'; @@ -9,7 +9,7 @@ describe('mercureInfoReducer', () => { token: 'abc.123.def', }; const getMercureInfo = jest.fn(); - const buildShlinkApiClient = () => Mock.of({ mercureInfo: getMercureInfo }); + const buildShlinkApiClient = () => fromPartial({ mercureInfo: getMercureInfo }); const { loadMercureInfo, reducer } = mercureInfoReducerCreator(buildShlinkApiClient); beforeEach(jest.resetAllMocks); diff --git a/test/servers/CreateServer.test.tsx b/test/servers/CreateServer.test.tsx index 4930d9f7..adbc1b2c 100644 --- a/test/servers/CreateServer.test.tsx +++ b/test/servers/CreateServer.test.tsx @@ -1,6 +1,6 @@ import { fireEvent, screen, waitFor } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { useNavigate } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import { CreateServer as createCreateServer } from '../../src/servers/CreateServer'; import type { ServerWithId } from '../../src/servers/data'; import { renderWithEvents } from '../__helpers__/setUpTest'; @@ -10,7 +10,7 @@ jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom') describe('', () => { const createServersMock = jest.fn(); const navigate = jest.fn(); - const servers = { foo: Mock.of({ url: 'https://existing_url.com', apiKey: 'existing_api_key' }) }; + const servers = { foo: fromPartial({ url: 'https://existing_url.com', apiKey: 'existing_api_key' }) }; const setUp = (serversImported = false, importFailed = false) => { (useNavigate as any).mockReturnValue(navigate); diff --git a/test/servers/DeleteServerButton.test.tsx b/test/servers/DeleteServerButton.test.tsx index 4b17fcb0..2b3e69f9 100644 --- a/test/servers/DeleteServerButton.test.tsx +++ b/test/servers/DeleteServerButton.test.tsx @@ -1,7 +1,6 @@ import { screen, waitFor } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ReactNode } from 'react'; -import { Mock } from 'ts-mockery'; -import type { ServerWithId } from '../../src/servers/data'; import { DeleteServerButton as createDeleteServerButton } from '../../src/servers/DeleteServerButton'; import { renderWithEvents } from '../__helpers__/setUpTest'; @@ -10,7 +9,7 @@ describe('', () => { ({ isOpen }) => <>DeleteServerModal {isOpen ? '[Open]' : '[Closed]'}, ); const setUp = (children?: ReactNode) => renderWithEvents( - ()} textClassName="button">{children}, + {children}, ); it.each([ diff --git a/test/servers/DeleteServerModal.test.tsx b/test/servers/DeleteServerModal.test.tsx index 3df5a2e5..f2f66d42 100644 --- a/test/servers/DeleteServerModal.test.tsx +++ b/test/servers/DeleteServerModal.test.tsx @@ -1,7 +1,6 @@ import { screen, waitFor } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { useNavigate } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; -import type { ServerWithId } from '../../src/servers/data'; import { DeleteServerModal } from '../../src/servers/DeleteServerModal'; import { renderWithEvents } from '../__helpers__/setUpTest'; import { TestModalWrapper } from '../__helpers__/TestModalWrapper'; @@ -20,7 +19,7 @@ describe('', () => { renderModal={(args) => ( ({ name: serverName })} + server={fromPartial({ name: serverName })} deleteServer={deleteServerMock} /> )} diff --git a/test/servers/EditServer.test.tsx b/test/servers/EditServer.test.tsx index f38b2e64..4d680158 100644 --- a/test/servers/EditServer.test.tsx +++ b/test/servers/EditServer.test.tsx @@ -1,6 +1,6 @@ import { fireEvent, screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter, useNavigate } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { ReachableServer, SelectedServer } from '../../src/servers/data'; import { EditServer as editServerConstruct } from '../../src/servers/EditServer'; import { renderWithEvents } from '../__helpers__/setUpTest'; @@ -11,7 +11,7 @@ describe('', () => { const ServerError = jest.fn(); const editServerMock = jest.fn(); const navigate = jest.fn(); - const defaultSelectedServer = Mock.of({ + const defaultSelectedServer = fromPartial({ id: 'abc123', name: 'the_name', url: 'the_url', @@ -31,7 +31,7 @@ describe('', () => { afterEach(jest.clearAllMocks); it('renders nothing if selected server is not reachable', () => { - setUp(Mock.all()); + setUp(fromPartial({})); expect(screen.queryByText('Edit')).not.toBeInTheDocument(); expect(screen.queryByText('Cancel')).not.toBeInTheDocument(); diff --git a/test/servers/ManageServers.test.tsx b/test/servers/ManageServers.test.tsx index b3c97e8f..ce5c2a08 100644 --- a/test/servers/ManageServers.test.tsx +++ b/test/servers/ManageServers.test.tsx @@ -1,6 +1,6 @@ import { screen, waitFor } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { ServersMap, ServerWithId } from '../../src/servers/data'; import { ManageServers as createManageServers } from '../../src/servers/ManageServers'; import type { ServersExporter } from '../../src/servers/services/ServersExporter'; @@ -8,7 +8,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { const exportServers = jest.fn(); - const serversExporter = Mock.of({ exportServers }); + const serversExporter = fromPartial({ exportServers }); const useTimeoutToggle = jest.fn().mockReturnValue([false, jest.fn()]); const ManageServers = createManageServers( serversExporter, @@ -16,7 +16,7 @@ describe('', () => { useTimeoutToggle, ({ hasAutoConnect }) => ManageServersRow {hasAutoConnect ? '[YES]' : '[NO]'}, ); - const createServerMock = (value: string, autoConnect = false) => Mock.of( + const createServerMock = (value: string, autoConnect = false) => fromPartial( { id: value, name: value, url: value, autoConnect }, ); const setUp = (servers: ServersMap = {}) => renderWithEvents( diff --git a/test/servers/ManageServersRowDropdown.test.tsx b/test/servers/ManageServersRowDropdown.test.tsx index df8c0946..9d1d536b 100644 --- a/test/servers/ManageServersRowDropdown.test.tsx +++ b/test/servers/ManageServersRowDropdown.test.tsx @@ -1,6 +1,6 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { ServerWithId } from '../../src/servers/data'; import { ManageServersRowDropdown as createManageServersRowDropdown } from '../../src/servers/ManageServersRowDropdown'; import { renderWithEvents } from '../__helpers__/setUpTest'; @@ -11,7 +11,7 @@ describe('', () => { ); const setAutoConnect = jest.fn(); const setUp = (autoConnect = false) => { - const server = Mock.of({ id: 'abc123', autoConnect }); + const server = fromPartial({ id: 'abc123', autoConnect }); return renderWithEvents( diff --git a/test/servers/Overview.test.tsx b/test/servers/Overview.test.tsx index 0b4c6b6d..bff2b42d 100644 --- a/test/servers/Overview.test.tsx +++ b/test/servers/Overview.test.tsx @@ -1,14 +1,9 @@ import { screen, waitFor } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { MercureInfo } from '../../src/mercure/reducers/mercureInfo'; -import type { ReachableServer } from '../../src/servers/data'; import { Overview as overviewCreator } from '../../src/servers/Overview'; -import type { Settings } from '../../src/settings/reducers/settings'; -import type { ShortUrlsList as ShortUrlsListState } from '../../src/short-urls/reducers/shortUrlsList'; -import type { TagsList } from '../../src/tags/reducers/tagsList'; import { prettify } from '../../src/utils/helpers/numbers'; -import type { VisitsOverview } from '../../src/visits/reducers/visitsOverview'; import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { @@ -28,18 +23,18 @@ describe('', () => { listShortUrls={listShortUrls} listTags={listTags} loadVisitsOverview={loadVisitsOverview} - shortUrlsList={Mock.of({ loading, shortUrls })} - tagsList={Mock.of({ loading, tags: ['foo', 'bar', 'baz'] })} - visitsOverview={Mock.of({ + shortUrlsList={fromPartial({ loading, shortUrls })} + tagsList={fromPartial({ loading, tags: ['foo', 'bar', 'baz'] })} + visitsOverview={fromPartial({ loading, nonOrphanVisits: { total: 3456, bots: 1000, nonBots: 2456 }, orphanVisits: { total: 28, bots: 15, nonBots: 13 }, })} - selectedServer={Mock.of({ id: serverId })} + selectedServer={fromPartial({ id: serverId })} createNewVisits={jest.fn()} loadMercureInfo={jest.fn()} - mercureInfo={Mock.all()} - settings={Mock.of({ visits: { excludeBots } })} + mercureInfo={fromPartial({})} + settings={fromPartial({ visits: { excludeBots } })} /> , ); diff --git a/test/servers/ServersDropdown.test.tsx b/test/servers/ServersDropdown.test.tsx index b22ceb24..c78ed5f6 100644 --- a/test/servers/ServersDropdown.test.tsx +++ b/test/servers/ServersDropdown.test.tsx @@ -1,16 +1,16 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { values } from 'ramda'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; -import type { ServersMap, ServerWithId } from '../../src/servers/data'; +import type { ServersMap } from '../../src/servers/data'; import { ServersDropdown } from '../../src/servers/ServersDropdown'; import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { const fallbackServers: ServersMap = { - '1a': Mock.of({ name: 'foo', id: '1a' }), - '2b': Mock.of({ name: 'bar', id: '2b' }), - '3c': Mock.of({ name: 'baz', id: '3c' }), + '1a': fromPartial({ name: 'foo', id: '1a' }), + '2b': fromPartial({ name: 'bar', id: '2b' }), + '3c': fromPartial({ name: 'baz', id: '3c' }), }; const setUp = (servers: ServersMap = fallbackServers) => renderWithEvents( , diff --git a/test/servers/ServersListGroup.test.tsx b/test/servers/ServersListGroup.test.tsx index 5c0e45a5..d99f68e0 100644 --- a/test/servers/ServersListGroup.test.tsx +++ b/test/servers/ServersListGroup.test.tsx @@ -1,13 +1,13 @@ import { render, screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { ServerWithId } from '../../src/servers/data'; import { ServersListGroup } from '../../src/servers/ServersListGroup'; describe('', () => { - const servers = [ - Mock.of({ name: 'foo', id: '123' }), - Mock.of({ name: 'bar', id: '456' }), + const servers: ServerWithId[] = [ + fromPartial({ name: 'foo', id: '123' }), + fromPartial({ name: 'bar', id: '456' }), ]; const setUp = (params: { servers?: ServerWithId[]; withChildren?: boolean; embedded?: boolean }) => { const { servers = [], withChildren = true, embedded } = params; diff --git a/test/servers/helpers/DuplicatedServersModal.test.tsx b/test/servers/helpers/DuplicatedServersModal.test.tsx index 81ef52d3..b4918fc4 100644 --- a/test/servers/helpers/DuplicatedServersModal.test.tsx +++ b/test/servers/helpers/DuplicatedServersModal.test.tsx @@ -1,5 +1,5 @@ import { screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ServerData } from '../../../src/servers/data'; import { DuplicatedServersModal } from '../../../src/servers/helpers/DuplicatedServersModal'; import { renderWithEvents } from '../../__helpers__/setUpTest'; @@ -10,15 +10,16 @@ describe('', () => { const setUp = (duplicatedServers: ServerData[] = []) => renderWithEvents( , ); + const mockServer = (data: Partial = {}) => fromPartial(data); beforeEach(jest.clearAllMocks); it.each([ [[], 0], - [[Mock.all()], 2], - [[Mock.all(), Mock.all()], 2], - [[Mock.all(), Mock.all(), Mock.all()], 3], - [[Mock.all(), Mock.all(), Mock.all(), Mock.all()], 4], + [[mockServer()], 2], + [[mockServer(), mockServer()], 2], + [[mockServer(), mockServer(), mockServer()], 3], + [[mockServer(), mockServer(), mockServer(), mockServer()], 4], ])('renders expected amount of items', (duplicatedServers, expectedItems) => { setUp(duplicatedServers); expect(screen.queryAllByRole('listitem')).toHaveLength(expectedItems); @@ -26,7 +27,7 @@ describe('', () => { it.each([ [ - [Mock.all()], + [mockServer()], { header: 'Duplicated server', firstParagraph: 'There is already a server with:', @@ -35,7 +36,7 @@ describe('', () => { }, ], [ - [Mock.all(), Mock.all()], + [mockServer(), mockServer()], { header: 'Duplicated servers', firstParagraph: 'The next servers already exist:', @@ -54,10 +55,10 @@ describe('', () => { it.each([ [[]], - [[Mock.of({ url: 'url', apiKey: 'apiKey' })]], + [[mockServer({ url: 'url', apiKey: 'apiKey' })]], [[ - Mock.of({ url: 'url_1', apiKey: 'apiKey_1' }), - Mock.of({ url: 'url_2', apiKey: 'apiKey_2' }), + mockServer({ url: 'url_1', apiKey: 'apiKey_1' }), + mockServer({ url: 'url_2', apiKey: 'apiKey_2' }), ]], ])('displays provided server data', (duplicatedServers) => { setUp(duplicatedServers); diff --git a/test/servers/helpers/ImportServersBtn.test.tsx b/test/servers/helpers/ImportServersBtn.test.tsx index 2abc105f..a452e094 100644 --- a/test/servers/helpers/ImportServersBtn.test.tsx +++ b/test/servers/helpers/ImportServersBtn.test.tsx @@ -1,5 +1,5 @@ import { fireEvent, screen, waitFor } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ServersMap, ServerWithId } from '../../../src/servers/data'; import type { ImportServersBtnProps } from '../../../src/servers/helpers/ImportServersBtn'; @@ -13,7 +13,7 @@ describe('', () => { const onImportMock = jest.fn(); const createServersMock = jest.fn(); const importServersFromFile = jest.fn().mockResolvedValue([]); - const serversImporterMock = Mock.of({ importServersFromFile }); + const serversImporterMock = fromPartial({ importServersFromFile }); const ImportServersBtn = createImportServersBtn(serversImporterMock); const setUp = (props: Partial = {}, servers: ServersMap = {}) => renderWithEvents( ', () => { ['Save anyway', true], ['Discard', false], ])('creates expected servers depending on selected option in modal', async (btnName, savesDuplicatedServers) => { - const existingServer = Mock.of({ id: 'abc', url: 'existingUrl', apiKey: 'existingApiKey' }); - const newServer = Mock.of({ url: 'newUrl', apiKey: 'newApiKey' }); + const existingServer = fromPartial({ id: 'abc', url: 'existingUrl', apiKey: 'existingApiKey' }); + const newServer = fromPartial({ url: 'newUrl', apiKey: 'newApiKey' }); const { container, user } = setUp({}, { abc: existingServer }); const input = container.querySelector('[type=file]'); importServersFromFile.mockResolvedValue([existingServer, newServer]); diff --git a/test/servers/helpers/ServerError.test.tsx b/test/servers/helpers/ServerError.test.tsx index be428ccf..afad6217 100644 --- a/test/servers/helpers/ServerError.test.tsx +++ b/test/servers/helpers/ServerError.test.tsx @@ -1,6 +1,6 @@ import { render, screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { NonReachableServer, NotFoundServer } from '../../../src/servers/data'; import { ServerError as createServerError } from '../../../src/servers/helpers/ServerError'; @@ -9,7 +9,7 @@ describe('', () => { it.each([ [ - Mock.all(), + fromPartial({}), { found: ['Could not find this Shlink server.'], notFound: [ @@ -20,7 +20,7 @@ describe('', () => { }, ], [ - Mock.of({ id: 'abc123' }), + fromPartial({ id: 'abc123' }), { found: [ 'Oops! Could not connect to this Shlink server.', diff --git a/test/servers/reducers/remoteServers.test.ts b/test/servers/reducers/remoteServers.test.ts index 37b493bb..230488c6 100644 --- a/test/servers/reducers/remoteServers.test.ts +++ b/test/servers/reducers/remoteServers.test.ts @@ -1,4 +1,4 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { HttpClient } from '../../../src/common/services/HttpClient'; import { fetchServers } from '../../../src/servers/reducers/remoteServers'; @@ -8,7 +8,7 @@ describe('remoteServersReducer', () => { describe('fetchServers', () => { const dispatch = jest.fn(); const fetchJson = jest.fn(); - const httpClient = Mock.of({ fetchJson }); + const httpClient = fromPartial({ fetchJson }); it.each([ [ diff --git a/test/servers/reducers/selectedServer.test.ts b/test/servers/reducers/selectedServer.test.ts index 664d69d8..34609864 100644 --- a/test/servers/reducers/selectedServer.test.ts +++ b/test/servers/reducers/selectedServer.test.ts @@ -1,4 +1,4 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import { v4 as uuid } from 'uuid'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkState } from '../../../src/container/types'; @@ -15,7 +15,7 @@ import { describe('selectedServerReducer', () => { const dispatch = jest.fn(); const health = jest.fn(); - const buildApiClient = jest.fn().mockReturnValue(Mock.of({ health })); + const buildApiClient = jest.fn().mockReturnValue(fromPartial({ health })); const selectServer = selectServerCreator(buildApiClient); const { reducer } = selectedServerReducerCreator(selectServer); @@ -26,8 +26,7 @@ describe('selectedServerReducer', () => { expect(reducer(null, resetSelectedServer())).toBeNull()); it('returns selected server when action is SELECT_SERVER', () => { - const payload = Mock.of({ id: 'abc123' }); - + const payload = fromPartial({ id: 'abc123' }); expect(reducer(null, selectServer.fulfilled(payload, '', ''))).toEqual(payload); }); }); @@ -66,7 +65,7 @@ describe('selectedServerReducer', () => { it('dispatches error when health endpoint fails', async () => { const id = uuid(); const getState = createGetStateMock(id); - const expectedSelectedServer = Mock.of({ id, serverNotReachable: true }); + const expectedSelectedServer = fromPartial({ id, serverNotReachable: true }); health.mockRejectedValue({}); @@ -78,7 +77,7 @@ describe('selectedServerReducer', () => { it('dispatches error when server is not found', async () => { const id = uuid(); - const getState = jest.fn(() => Mock.of({ servers: {} })); + const getState = jest.fn(() => fromPartial({ servers: {} })); const expectedSelectedServer: NotFoundServer = { serverNotFound: true }; await selectServer(id)(dispatch, getState, {}); @@ -95,9 +94,9 @@ describe('selectedServerReducer', () => { const { middleware } = selectServerListener(selectServer, loadMercureInfo); it.each([ - [Mock.of({ version: '1.2.3' }), 1], - [Mock.of({ serverNotFound: true }), 0], - [Mock.of({ serverNotReachable: true }), 0], + [fromPartial({ version: '1.2.3' }), 1], + [fromPartial({ serverNotFound: true }), 0], + [fromPartial({ serverNotReachable: true }), 0], ])('dispatches loadMercureInfo when provided server is reachable', (payload, expectedCalls) => { middleware({ dispatch, getState })(jest.fn())({ payload, @@ -110,7 +109,7 @@ describe('selectedServerReducer', () => { it('does not dispatch loadMercureInfo when action is not of the proper type', () => { middleware({ dispatch, getState })(jest.fn())({ - payload: Mock.of({ version: '1.2.3' }), + payload: fromPartial({ version: '1.2.3' }), type: 'something_else', }); diff --git a/test/servers/reducers/servers.test.ts b/test/servers/reducers/servers.test.ts index d385eeaf..17637483 100644 --- a/test/servers/reducers/servers.test.ts +++ b/test/servers/reducers/servers.test.ts @@ -1,6 +1,6 @@ +import { fromPartial } from '@total-typescript/shoehorn'; import { dissoc, values } from 'ramda'; -import { Mock } from 'ts-mockery'; -import type { RegularServer, ServerWithId } from '../../../src/servers/data'; +import type { RegularServer, ServersMap, ServerWithId } from '../../../src/servers/data'; import { createServers, deleteServer, @@ -10,9 +10,9 @@ import { } from '../../../src/servers/reducers/servers'; describe('serversReducer', () => { - const list = { - abc123: Mock.of({ id: 'abc123' }), - def456: Mock.of({ id: 'def456' }), + const list: ServersMap = { + abc123: fromPartial({ id: 'abc123' }), + def456: fromPartial({ id: 'def456' }), }; afterEach(jest.clearAllMocks); @@ -31,12 +31,12 @@ describe('serversReducer', () => { })); it('removes server when action is DELETE_SERVER', () => - expect(serversReducer(list, deleteServer(Mock.of({ id: 'abc123' })))).toEqual({ + expect(serversReducer(list, deleteServer(fromPartial({ id: 'abc123' })))).toEqual({ def456: { id: 'def456' }, })); it('appends server when action is CREATE_SERVERS', () => - expect(serversReducer(list, createServers([Mock.of({ id: 'ghi789' })]))).toEqual({ + expect(serversReducer(list, createServers([fromPartial({ id: 'ghi789' })]))).toEqual({ abc123: { id: 'abc123' }, def456: { id: 'def456' }, ghi789: { id: 'ghi789' }, @@ -46,7 +46,7 @@ describe('serversReducer', () => { [true], [false], ])('returns state as it is when trying to set auto-connect on invalid server', (autoConnect) => - expect(serversReducer(list, setAutoConnect(Mock.of({ id: 'invalid' }), autoConnect))).toEqual({ + expect(serversReducer(list, setAutoConnect(fromPartial({ id: 'invalid' }), autoConnect))).toEqual({ abc123: { id: 'abc123' }, def456: { id: 'def456' }, })); @@ -59,7 +59,7 @@ describe('serversReducer', () => { expect(serversReducer( listWithDisabledAutoConnect, - setAutoConnect(Mock.of({ id: 'abc123' }), false), + setAutoConnect(fromPartial({ id: 'abc123' }), false), )).toEqual({ abc123: { id: 'abc123', autoConnect: false }, def456: { id: 'def456' }, @@ -74,7 +74,7 @@ describe('serversReducer', () => { expect(serversReducer( listWithEnabledAutoConnect, - setAutoConnect(Mock.of({ id: 'def456' }), true), + setAutoConnect(fromPartial({ id: 'def456' }), true), )).toEqual({ abc123: { id: 'abc123', autoConnect: false }, def456: { id: 'def456', autoConnect: true }, @@ -94,7 +94,7 @@ describe('serversReducer', () => { describe('deleteServer', () => { it('returns expected action', () => { - const serverToDelete = Mock.of({ id: 'abc123' }); + const serverToDelete = fromPartial({ id: 'abc123' }); const { payload } = deleteServer(serverToDelete); expect(payload).toEqual({ id: 'abc123' }); @@ -122,7 +122,7 @@ describe('serversReducer', () => { [true], [false], ])('returns expected action', (autoConnect) => { - const serverToEdit = Mock.of({ id: 'abc123' }); + const serverToEdit = fromPartial({ id: 'abc123' }); const { payload } = setAutoConnect(serverToEdit, autoConnect); expect(payload).toEqual({ serverId: 'abc123', autoConnect }); diff --git a/test/servers/services/ServersExporter.test.ts b/test/servers/services/ServersExporter.test.ts index 796ca5d9..a50a5eeb 100644 --- a/test/servers/services/ServersExporter.test.ts +++ b/test/servers/services/ServersExporter.test.ts @@ -1,10 +1,10 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import { ServersExporter } from '../../../src/servers/services/ServersExporter'; import type { LocalStorage } from '../../../src/utils/services/LocalStorage'; import { appendChild, removeChild, windowMock } from '../../__mocks__/Window.mock'; describe('ServersExporter', () => { - const storageMock = Mock.of({ + const storageMock = fromPartial({ get: jest.fn(() => ({ abc123: { id: 'abc123', @@ -16,7 +16,7 @@ describe('ServersExporter', () => { name: 'bar', autoConnect: false, }, - })), + } as any)), }); const erroneousToCsv = jest.fn(() => { throw new Error(''); @@ -31,7 +31,7 @@ describe('ServersExporter', () => { beforeEach(() => { originalConsole = global.console; - global.console = Mock.of({ error }); + global.console = fromPartial({ error }); (global as any).Blob = class Blob {}; (global as any).URL = { createObjectURL: () => '' }; }); diff --git a/test/servers/services/ServersImporter.test.ts b/test/servers/services/ServersImporter.test.ts index be0a12dc..be909a9c 100644 --- a/test/servers/services/ServersImporter.test.ts +++ b/test/servers/services/ServersImporter.test.ts @@ -1,16 +1,16 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { RegularServer } from '../../../src/servers/data'; import { ServersImporter } from '../../../src/servers/services/ServersImporter'; describe('ServersImporter', () => { - const servers: RegularServer[] = [Mock.all(), Mock.all()]; + const servers: RegularServer[] = [fromPartial({}), fromPartial({})]; const csvjsonMock = jest.fn().mockResolvedValue(servers); const readAsText = jest.fn(); - const fileReaderMock = Mock.of({ + const fileReaderMock = fromPartial({ readAsText, - addEventListener: (_eventName: string, listener: (e: ProgressEvent) => void) => listener( - Mock.of>({ target: { result: '' } }), - ), + addEventListener: ((_eventName: string, listener: (e: ProgressEvent) => void) => listener( + fromPartial({ target: { result: '' } }), + )) as any, }); const importer = new ServersImporter(csvjsonMock, () => fileReaderMock); @@ -28,7 +28,7 @@ describe('ServersImporter', () => { csvjsonMock.mockRejectedValue(expectedError); - await expect(importer.importServersFromFile(Mock.of({ type: 'text/html' }))).rejects.toEqual(expectedError); + await expect(importer.importServersFromFile(fromPartial({ type: 'text/html' }))).rejects.toEqual(expectedError); }); it.each([ @@ -57,7 +57,7 @@ describe('ServersImporter', () => { ])('rejects with error if provided file does not parse to valid list of servers', async (parsedObject) => { csvjsonMock.mockResolvedValue(parsedObject); - await expect(importer.importServersFromFile(Mock.of({ type: 'text/html' }))).rejects.toEqual( + await expect(importer.importServersFromFile(fromPartial({ type: 'text/html' }))).rejects.toEqual( new Error('Provided file does not have the right format.'), ); }); @@ -78,7 +78,7 @@ describe('ServersImporter', () => { csvjsonMock.mockResolvedValue(expectedServers); - const result = await importer.importServersFromFile(Mock.all()); + const result = await importer.importServersFromFile(fromPartial({})); expect(result).toEqual(expectedServers); expect(readAsText).toHaveBeenCalledTimes(1); diff --git a/test/settings/RealTimeUpdatesSettings.test.tsx b/test/settings/RealTimeUpdatesSettings.test.tsx index 98586dda..63d2c65c 100644 --- a/test/settings/RealTimeUpdatesSettings.test.tsx +++ b/test/settings/RealTimeUpdatesSettings.test.tsx @@ -1,9 +1,8 @@ import { screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import { RealTimeUpdatesSettings } from '../../src/settings/RealTimeUpdatesSettings'; import type { RealTimeUpdatesSettings as RealTimeUpdatesSettingsOptions, - Settings, } from '../../src/settings/reducers/settings'; import { renderWithEvents } from '../__helpers__/setUpTest'; @@ -12,7 +11,7 @@ describe('', () => { const setRealTimeUpdatesInterval = jest.fn(); const setUp = (realTimeUpdates: Partial = {}) => renderWithEvents( ({ realTimeUpdates })} + settings={fromPartial({ realTimeUpdates })} toggleRealTimeUpdates={toggleRealTimeUpdates} setRealTimeUpdatesInterval={setRealTimeUpdatesInterval} />, diff --git a/test/settings/ShortUrlCreationSettings.test.tsx b/test/settings/ShortUrlCreationSettings.test.tsx index 220ff554..45dcd4b2 100644 --- a/test/settings/ShortUrlCreationSettings.test.tsx +++ b/test/settings/ShortUrlCreationSettings.test.tsx @@ -1,6 +1,6 @@ import { screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; -import type { Settings, ShortUrlCreationSettings as ShortUrlsSettings } from '../../src/settings/reducers/settings'; +import { fromPartial } from '@total-typescript/shoehorn'; +import type { ShortUrlCreationSettings as ShortUrlsSettings } from '../../src/settings/reducers/settings'; import { ShortUrlCreationSettings } from '../../src/settings/ShortUrlCreationSettings'; import { renderWithEvents } from '../__helpers__/setUpTest'; @@ -8,7 +8,7 @@ describe('', () => { const setShortUrlCreationSettings = jest.fn(); const setUp = (shortUrlCreation?: ShortUrlsSettings) => renderWithEvents( ({ shortUrlCreation })} + settings={fromPartial({ shortUrlCreation })} setShortUrlCreationSettings={setShortUrlCreationSettings} />, ); diff --git a/test/settings/ShortUrlsListSettings.test.tsx b/test/settings/ShortUrlsListSettings.test.tsx index c0cd1a4b..889559f4 100644 --- a/test/settings/ShortUrlsListSettings.test.tsx +++ b/test/settings/ShortUrlsListSettings.test.tsx @@ -1,6 +1,6 @@ import { screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; -import type { Settings, ShortUrlsListSettings as ShortUrlsSettings } from '../../src/settings/reducers/settings'; +import { fromPartial } from '@total-typescript/shoehorn'; +import type { ShortUrlsListSettings as ShortUrlsSettings } from '../../src/settings/reducers/settings'; import { ShortUrlsListSettings } from '../../src/settings/ShortUrlsListSettings'; import type { ShortUrlsOrder } from '../../src/short-urls/data'; import { renderWithEvents } from '../__helpers__/setUpTest'; @@ -8,7 +8,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { const setSettings = jest.fn(); const setUp = (shortUrlsList?: ShortUrlsSettings) => renderWithEvents( - ({ shortUrlsList })} setShortUrlsListSettings={setSettings} />, + , ); afterEach(jest.clearAllMocks); diff --git a/test/settings/TagsSettings.test.tsx b/test/settings/TagsSettings.test.tsx index 050e4b1c..c3bf1b20 100644 --- a/test/settings/TagsSettings.test.tsx +++ b/test/settings/TagsSettings.test.tsx @@ -1,6 +1,6 @@ import { screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; -import type { Settings, TagsSettings as TagsSettingsOptions } from '../../src/settings/reducers/settings'; +import { fromPartial } from '@total-typescript/shoehorn'; +import type { TagsSettings as TagsSettingsOptions } from '../../src/settings/reducers/settings'; import { TagsSettings } from '../../src/settings/TagsSettings'; import type { TagsOrder } from '../../src/tags/data/TagsListChildrenProps'; import { renderWithEvents } from '../__helpers__/setUpTest'; @@ -8,7 +8,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { const setTagsSettings = jest.fn(); const setUp = (tags?: TagsSettingsOptions) => renderWithEvents( - ({ tags })} setTagsSettings={setTagsSettings} />, + , ); afterEach(jest.clearAllMocks); diff --git a/test/settings/UserInterfaceSettings.test.tsx b/test/settings/UserInterfaceSettings.test.tsx index 0ca68e86..b0ecf856 100644 --- a/test/settings/UserInterfaceSettings.test.tsx +++ b/test/settings/UserInterfaceSettings.test.tsx @@ -1,6 +1,6 @@ import { screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; -import type { Settings, UiSettings } from '../../src/settings/reducers/settings'; +import { fromPartial } from '@total-typescript/shoehorn'; +import type { UiSettings } from '../../src/settings/reducers/settings'; import { UserInterfaceSettings } from '../../src/settings/UserInterfaceSettings'; import type { Theme } from '../../src/utils/theme'; import { renderWithEvents } from '../__helpers__/setUpTest'; @@ -8,7 +8,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { const setUiSettings = jest.fn(); const setUp = (ui?: UiSettings) => renderWithEvents( - ({ ui })} setUiSettings={setUiSettings} />, + , ); afterEach(jest.clearAllMocks); diff --git a/test/settings/VisitsSettings.test.tsx b/test/settings/VisitsSettings.test.tsx index 3326b75e..1bc729f4 100644 --- a/test/settings/VisitsSettings.test.tsx +++ b/test/settings/VisitsSettings.test.tsx @@ -1,5 +1,5 @@ import { screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { Settings } from '../../src/settings/reducers/settings'; import { VisitsSettings } from '../../src/settings/VisitsSettings'; import { renderWithEvents } from '../__helpers__/setUpTest'; @@ -7,7 +7,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { const setVisitsSettings = jest.fn(); const setUp = (settings: Partial = {}) => renderWithEvents( - (settings)} setVisitsSettings={setVisitsSettings} />, + , ); afterEach(jest.clearAllMocks); @@ -21,10 +21,10 @@ describe('', () => { }); it.each([ - [Mock.all(), 'Last 30 days'], - [Mock.of({ visits: {} }), 'Last 30 days'], + [fromPartial({}), 'Last 30 days'], + [fromPartial({ visits: {} }), 'Last 30 days'], [ - Mock.of({ + fromPartial({ visits: { defaultInterval: 'last7Days', }, @@ -32,7 +32,7 @@ describe('', () => { 'Last 7 days', ], [ - Mock.of({ + fromPartial({ visits: { defaultInterval: 'today', }, @@ -63,17 +63,17 @@ describe('', () => { it.each([ [ - Mock.all(), + fromPartial({}), /The visits coming from potential bots will be included.$/, /The visits coming from potential bots will be excluded.$/, ], [ - Mock.of({ visits: { excludeBots: false } }), + fromPartial({ visits: { excludeBots: false } }), /The visits coming from potential bots will be included.$/, /The visits coming from potential bots will be excluded.$/, ], [ - Mock.of({ visits: { excludeBots: true } }), + fromPartial({ visits: { excludeBots: true } }), /The visits coming from potential bots will be excluded.$/, /The visits coming from potential bots will be included.$/, ], diff --git a/test/settings/helpers/index.test.ts b/test/settings/helpers/index.test.ts index 6b7c188f..e69fb899 100644 --- a/test/settings/helpers/index.test.ts +++ b/test/settings/helpers/index.test.ts @@ -1,4 +1,4 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkState } from '../../../src/container/types'; import { migrateDeprecatedSettings } from '../../../src/settings/helpers'; @@ -9,7 +9,7 @@ describe('settings-helpers', () => { }); it('updates settings as expected', () => { - const state = Mock.of({ + const state = fromPartial({ settings: { visits: { defaultInterval: 'last180days' as any, diff --git a/test/short-urls/CreateShortUrl.test.tsx b/test/short-urls/CreateShortUrl.test.tsx index 68a3dbbc..55a2c3be 100644 --- a/test/short-urls/CreateShortUrl.test.tsx +++ b/test/short-urls/CreateShortUrl.test.tsx @@ -1,6 +1,5 @@ import { render, screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; -import type { Settings } from '../../src/settings/reducers/settings'; +import { fromPartial } from '@total-typescript/shoehorn'; import { CreateShortUrl as createShortUrlsCreator } from '../../src/short-urls/CreateShortUrl'; import type { ShortUrlCreation } from '../../src/short-urls/reducers/shortUrlCreation'; @@ -8,7 +7,7 @@ describe('', () => { const ShortUrlForm = () => ShortUrlForm; const CreateShortUrlResult = () => CreateShortUrlResult; const shortUrlCreation = { validateUrls: true }; - const shortUrlCreationResult = Mock.all(); + const shortUrlCreationResult = fromPartial({}); const createShortUrl = jest.fn(async () => Promise.resolve()); const CreateShortUrl = createShortUrlsCreator(ShortUrlForm, CreateShortUrlResult); const setUp = () => render( @@ -17,7 +16,7 @@ describe('', () => { createShortUrl={createShortUrl} selectedServer={null} resetCreateShortUrl={() => {}} - settings={Mock.of({ shortUrlCreation })} + settings={fromPartial({ shortUrlCreation })} />, ); diff --git a/test/short-urls/EditShortUrl.test.tsx b/test/short-urls/EditShortUrl.test.tsx index 77767c47..f1efdcba 100644 --- a/test/short-urls/EditShortUrl.test.tsx +++ b/test/short-urls/EditShortUrl.test.tsx @@ -1,8 +1,6 @@ import { render, screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; -import type { Settings } from '../../src/settings/reducers/settings'; -import type { ShortUrl } from '../../src/short-urls/data'; import { EditShortUrl as createEditShortUrl } from '../../src/short-urls/EditShortUrl'; import type { ShortUrlDetail } from '../../src/short-urls/reducers/shortUrlDetail'; import type { ShortUrlEdition } from '../../src/short-urls/reducers/shortUrlEdition'; @@ -13,10 +11,10 @@ describe('', () => { const setUp = (detail: Partial = {}, edition: Partial = {}) => render( ({ shortUrlCreation })} + settings={fromPartial({ shortUrlCreation })} selectedServer={null} - shortUrlDetail={Mock.of(detail)} - shortUrlEdition={Mock.of(edition)} + shortUrlDetail={fromPartial(detail)} + shortUrlEdition={fromPartial(edition)} getShortUrlDetail={jest.fn()} editShortUrl={jest.fn(async () => Promise.resolve())} /> @@ -38,7 +36,7 @@ describe('', () => { }); it('renders form when detail properly loads', () => { - setUp({ shortUrl: Mock.of({ meta: {} }) }); + setUp({ shortUrl: fromPartial({ meta: {} }) }); expect(screen.getByText('ShortUrlForm')).toBeInTheDocument(); expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); diff --git a/test/short-urls/Paginator.test.tsx b/test/short-urls/Paginator.test.tsx index 36f215f8..cde9462c 100644 --- a/test/short-urls/Paginator.test.tsx +++ b/test/short-urls/Paginator.test.tsx @@ -1,12 +1,12 @@ import { render, screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { ShlinkPaginator } from '../../src/api/types'; import { Paginator } from '../../src/short-urls/Paginator'; import { ELLIPSIS } from '../../src/utils/helpers/pagination'; describe('', () => { - const buildPaginator = (pagesCount?: number) => Mock.of({ pagesCount, currentPage: 1 }); + const buildPaginator = (pagesCount?: number) => fromPartial({ pagesCount, currentPage: 1 }); const setUp = (paginator?: ShlinkPaginator, currentQueryString?: string) => render( diff --git a/test/short-urls/ShortUrlForm.test.tsx b/test/short-urls/ShortUrlForm.test.tsx index da31944d..7d94b956 100644 --- a/test/short-urls/ShortUrlForm.test.tsx +++ b/test/short-urls/ShortUrlForm.test.tsx @@ -1,7 +1,7 @@ import { screen } from '@testing-library/react'; import type { UserEvent } from '@testing-library/user-event/setup/setup'; +import { fromPartial } from '@total-typescript/shoehorn'; import { formatISO } from 'date-fns'; -import { Mock } from 'ts-mockery'; import type { ReachableServer, SelectedServer } from '../../src/servers/data'; import type { Mode } from '../../src/short-urls/ShortUrlForm'; import { ShortUrlForm as createShortUrlForm } from '../../src/short-urls/ShortUrlForm'; @@ -51,7 +51,7 @@ describe('', () => { ios: 'https://ios.com', }, }, - Mock.of({ version: '3.5.0' }), + fromPartial({ version: '3.5.0' }), ], ])('saves short URL with data set in form controls', async (extraFields, extraExpectedValues, selectedServer) => { const { user } = setUp(selectedServer); @@ -102,7 +102,7 @@ describe('', () => { [undefined, false, undefined], ['old title', false, null], ])('sends expected title based on original and new values', async (originalTitle, withNewTitle, expectedSentTitle) => { - const { user } = setUp(Mock.of({ version: '2.6.0' }), 'create', originalTitle); + const { user } = setUp(fromPartial({ version: '2.6.0' }), 'create', originalTitle); await user.type(screen.getByPlaceholderText('URL to be shortened'), 'https://long-domain.com/foo/bar'); await user.clear(screen.getByPlaceholderText('Title')); @@ -117,10 +117,10 @@ describe('', () => { }); it.each([ - [Mock.of({ version: '3.0.0' }), false], - [Mock.of({ version: '3.4.0' }), false], - [Mock.of({ version: '3.5.0' }), true], - [Mock.of({ version: '3.6.0' }), true], + [fromPartial({ version: '3.0.0' }), false], + [fromPartial({ version: '3.4.0' }), false], + [fromPartial({ version: '3.5.0' }), true], + [fromPartial({ version: '3.6.0' }), true], ])('shows device-specific long URLs only for servers supporting it', (selectedServer, fieldsExist) => { setUp(selectedServer); const placeholders = ['Android-specific redirection', 'iOS-specific redirection', 'Desktop-specific redirection']; diff --git a/test/short-urls/ShortUrlsFilteringBar.test.tsx b/test/short-urls/ShortUrlsFilteringBar.test.tsx index 3c89587f..24f00e63 100644 --- a/test/short-urls/ShortUrlsFilteringBar.test.tsx +++ b/test/short-urls/ShortUrlsFilteringBar.test.tsx @@ -1,9 +1,8 @@ import { screen, waitFor } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { endOfDay, formatISO, startOfDay } from 'date-fns'; import { MemoryRouter, useLocation, useNavigate } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { ReachableServer, SelectedServer } from '../../src/servers/data'; -import type { Settings } from '../../src/settings/reducers/settings'; import { ShortUrlsFilteringBar as filteringBarCreator } from '../../src/short-urls/ShortUrlsFilteringBar'; import { formatDate } from '../../src/utils/helpers/date'; import type { DateRange } from '../../src/utils/helpers/dateIntervals'; @@ -28,10 +27,10 @@ describe('', () => { return renderWithEvents( ()} + selectedServer={selectedServer ?? fromPartial({})} order={{}} handleOrderBy={handleOrderBy} - settings={Mock.of({ visits: {} })} + settings={fromPartial({ visits: {} })} /> , ); @@ -74,12 +73,12 @@ describe('', () => { }); it.each([ - ['tags=foo,bar,baz', Mock.of({ version: '3.0.0' }), true], - ['tags=foo,bar', Mock.of({ version: '3.1.0' }), true], - ['tags=foo', Mock.of({ version: '3.0.0' }), false], - ['', Mock.of({ version: '3.0.0' }), false], - ['tags=foo,bar,baz', Mock.of({ version: '2.10.0' }), false], - ['', Mock.of({ version: '2.10.0' }), false], + ['tags=foo,bar,baz', fromPartial({ version: '3.0.0' }), true], + ['tags=foo,bar', fromPartial({ version: '3.1.0' }), true], + ['tags=foo', fromPartial({ version: '3.0.0' }), false], + ['', fromPartial({ version: '3.0.0' }), false], + ['tags=foo,bar,baz', fromPartial({ version: '2.10.0' }), false], + ['', fromPartial({ version: '2.10.0' }), false], ])( 'renders tags mode toggle if the server supports it and there is more than one tag selected', (search, selectedServer, shouldHaveComponent) => { @@ -98,7 +97,7 @@ describe('', () => { ['&tagsMode=all', 'With all the tags.'], ['&tagsMode=any', 'With any of the tags.'], ])('expected tags mode tooltip title', async (initialTagsMode, expectedToggleText) => { - const { user } = setUp(`tags=foo,bar${initialTagsMode}`, Mock.of({ version: '3.0.0' })); + const { user } = setUp(`tags=foo,bar${initialTagsMode}`, fromPartial({ version: '3.0.0' })); await user.hover(screen.getByLabelText('Change tags mode')); expect(await screen.findByRole('tooltip')).toHaveTextContent(expectedToggleText); @@ -109,7 +108,7 @@ describe('', () => { ['&tagsMode=all', 'tagsMode=any'], ['&tagsMode=any', 'tagsMode=all'], ])('redirects to first page when tags mode changes', async (initialTagsMode, expectedRedirectTagsMode) => { - const { user } = setUp(`tags=foo,bar${initialTagsMode}`, Mock.of({ version: '3.0.0' })); + const { user } = setUp(`tags=foo,bar${initialTagsMode}`, fromPartial({ version: '3.0.0' })); expect(navigate).not.toHaveBeenCalled(); await user.click(screen.getByLabelText('Change tags mode')); @@ -127,7 +126,7 @@ describe('', () => { ['excludePastValidUntil=false', /Exclude enabled in the past/, 'excludePastValidUntil=true'], ['excludePastValidUntil=true', /Exclude enabled in the past/, 'excludePastValidUntil=false'], ])('allows to toggle filters through filtering dropdown', async (search, menuItemName, expectedQuery) => { - const { user } = setUp(search, Mock.of({ version: '3.4.0' })); + const { user } = setUp(search, fromPartial({ version: '3.4.0' })); const toggleFilter = async (name: RegExp) => { await user.click(screen.getByRole('button', { name: 'Filters' })); await waitFor(() => screen.findByRole('menu')); diff --git a/test/short-urls/ShortUrlsList.test.tsx b/test/short-urls/ShortUrlsList.test.tsx index 38ddef0e..09b40042 100644 --- a/test/short-urls/ShortUrlsList.test.tsx +++ b/test/short-urls/ShortUrlsList.test.tsx @@ -1,10 +1,9 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter, useNavigate } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub'; -import type { ReachableServer } from '../../src/servers/data'; import type { Settings } from '../../src/settings/reducers/settings'; -import type { ShortUrl, ShortUrlsOrder } from '../../src/short-urls/data'; +import type { ShortUrlsOrder } from '../../src/short-urls/data'; import type { ShortUrlsList as ShortUrlsListModel } from '../../src/short-urls/reducers/shortUrlsList'; import { ShortUrlsList as createShortUrlsList } from '../../src/short-urls/ShortUrlsList'; import type { ShortUrlsTableType } from '../../src/short-urls/ShortUrlsTable'; @@ -22,15 +21,15 @@ describe('', () => { const ShortUrlsFilteringBar = () => ShortUrlsFilteringBar; const listShortUrlsMock = jest.fn(); const navigate = jest.fn(); - const shortUrlsList = Mock.of({ + const shortUrlsList = fromPartial({ shortUrls: { data: [ - Mock.of({ + { shortCode: 'testShortCode', shortUrl: 'https://www.example.com/testShortUrl', longUrl: 'https://www.example.com/testLongUrl', tags: ['test tag'], - }), + }, ], pagination: { pagesCount: 3 }, }, @@ -39,11 +38,11 @@ describe('', () => { const setUp = (settings: Partial = {}, version: SemVer = '3.0.0') => renderWithEvents( ({ mercureInfo: { loading: true } })} + {...fromPartial({ mercureInfo: { loading: true } })} listShortUrls={listShortUrlsMock} shortUrlsList={shortUrlsList} - selectedServer={Mock.of({ id: '1', version })} - settings={Mock.of(settings)} + selectedServer={fromPartial({ id: '1', version })} + settings={fromPartial(settings)} /> , ); @@ -81,9 +80,9 @@ describe('', () => { }); it.each([ - [Mock.of({ field: 'visits', dir: 'ASC' }), 'visits', 'ASC'], - [Mock.of({ field: 'title', dir: 'DESC' }), 'title', 'DESC'], - [Mock.all(), undefined, undefined], + [fromPartial({ field: 'visits', dir: 'ASC' }), 'visits', 'ASC'], + [fromPartial({ field: 'title', dir: 'DESC' }), 'title', 'DESC'], + [fromPartial({}), undefined, undefined], ])('has expected initial ordering based on settings', (defaultOrdering, field, dir) => { setUp({ shortUrlsList: { defaultOrdering } }); expect(listShortUrlsMock).toHaveBeenCalledWith(expect.objectContaining({ @@ -92,23 +91,23 @@ describe('', () => { }); it.each([ - [Mock.of({ + [fromPartial({ shortUrlsList: { defaultOrdering: { field: 'visits', dir: 'ASC' }, }, }), '3.3.0' as SemVer, { field: 'visits', dir: 'ASC' }], - [Mock.of({ + [fromPartial({ shortUrlsList: { defaultOrdering: { field: 'visits', dir: 'ASC' }, }, visits: { excludeBots: true }, }), '3.3.0' as SemVer, { field: 'visits', dir: 'ASC' }], - [Mock.of({ + [fromPartial({ shortUrlsList: { defaultOrdering: { field: 'visits', dir: 'ASC' }, }, }), '3.4.0' as SemVer, { field: 'visits', dir: 'ASC' }], - [Mock.of({ + [fromPartial({ shortUrlsList: { defaultOrdering: { field: 'visits', dir: 'ASC' }, }, diff --git a/test/short-urls/ShortUrlsTable.test.tsx b/test/short-urls/ShortUrlsTable.test.tsx index e083d71a..23d07a57 100644 --- a/test/short-urls/ShortUrlsTable.test.tsx +++ b/test/short-urls/ShortUrlsTable.test.tsx @@ -1,6 +1,6 @@ import { fireEvent, screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; -import type { ReachableServer, SelectedServer } from '../../src/servers/data'; +import { fromPartial } from '@total-typescript/shoehorn'; +import type { SelectedServer } from '../../src/servers/data'; import type { ShortUrlsOrderableFields } from '../../src/short-urls/data'; import { SHORT_URLS_ORDERABLE_FIELDS } from '../../src/short-urls/data'; import type { ShortUrlsList } from '../../src/short-urls/reducers/shortUrlsList'; @@ -8,7 +8,7 @@ import { ShortUrlsTable as shortUrlsTableCreator } from '../../src/short-urls/Sh import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { - const shortUrlsList = Mock.all(); + const shortUrlsList = fromPartial({}); const orderByColumn = jest.fn(); const ShortUrlsTable = shortUrlsTableCreator(() => ShortUrlsRow); const setUp = (server: SelectedServer = null) => renderWithEvents( @@ -56,7 +56,7 @@ describe('', () => { }); it('should render composed title column', () => { - setUp(Mock.of({ version: '2.0.0' })); + setUp(fromPartial({ version: '2.0.0' })); const { innerHTML } = screen.getAllByRole('columnheader')[2]; diff --git a/test/short-urls/helpers/CreateShortUrlResult.test.tsx b/test/short-urls/helpers/CreateShortUrlResult.test.tsx index 0c07b109..3293f822 100644 --- a/test/short-urls/helpers/CreateShortUrlResult.test.tsx +++ b/test/short-urls/helpers/CreateShortUrlResult.test.tsx @@ -1,6 +1,5 @@ import { screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; -import type { ShortUrl } from '../../../src/short-urls/data'; +import { fromPartial } from '@total-typescript/shoehorn'; import { CreateShortUrlResult as createResult } from '../../../src/short-urls/helpers/CreateShortUrlResult'; import type { ShortUrlCreation } from '../../../src/short-urls/reducers/shortUrlCreation'; import type { TimeoutToggle } from '../../../src/utils/helpers/hooks'; @@ -28,14 +27,14 @@ describe('', () => { it('renders a result message when result is provided', () => { setUp( - { result: Mock.of({ shortUrl: 'https://s.test/abc123' }), saving: false, saved: true, error: false }, + { result: fromPartial({ shortUrl: 'https://s.test/abc123' }), saving: false, saved: true, error: false }, ); expect(screen.getByText(/The short URL is/)).toHaveTextContent('Great! The short URL is https://s.test/abc123'); }); it('Invokes tooltip timeout when copy to clipboard button is clicked', async () => { const { user } = setUp( - { result: Mock.of({ shortUrl: 'https://s.test/abc123' }), saving: false, saved: true, error: false }, + { result: fromPartial({ shortUrl: 'https://s.test/abc123' }), saving: false, saved: true, error: false }, ); expect(copyToClipboard).not.toHaveBeenCalled(); diff --git a/test/short-urls/helpers/DeleteShortUrlModal.test.tsx b/test/short-urls/helpers/DeleteShortUrlModal.test.tsx index fbff806c..35671459 100644 --- a/test/short-urls/helpers/DeleteShortUrlModal.test.tsx +++ b/test/short-urls/helpers/DeleteShortUrlModal.test.tsx @@ -1,6 +1,6 @@ import { screen, waitFor } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; -import type { InvalidShortUrlDeletion, ProblemDetailsError } from '../../../src/api/types/errors'; +import { fromPartial } from '@total-typescript/shoehorn'; +import type { InvalidShortUrlDeletion } from '../../../src/api/types/errors'; import { ErrorTypeV2, ErrorTypeV3 } from '../../../src/api/types/errors'; import type { ShortUrl } from '../../../src/short-urls/data'; import { DeleteShortUrlModal } from '../../../src/short-urls/helpers/DeleteShortUrlModal'; @@ -9,7 +9,7 @@ import { renderWithEvents } from '../../__helpers__/setUpTest'; import { TestModalWrapper } from '../../__helpers__/TestModalWrapper'; describe('', () => { - const shortUrl = Mock.of({ + const shortUrl = fromPartial({ tags: [], shortCode: 'abc123', longUrl: 'https://long-domain.com/foo/bar', @@ -22,7 +22,7 @@ describe('', () => { (shortUrlDeletion)} + shortUrlDeletion={fromPartial(shortUrlDeletion)} deleteShortUrl={deleteShortUrl} shortUrlDeleted={shortUrlDeleted} resetDeleteShortUrl={jest.fn()} @@ -38,7 +38,7 @@ describe('', () => { loading: false, error: true, shortCode: 'abc123', - errorData: Mock.of({ type: 'OTHER_ERROR' }), + errorData: fromPartial({ type: 'OTHER_ERROR' }), }); expect(screen.getByText('Something went wrong while deleting the URL :(').parentElement).not.toHaveClass( 'bg-warning', @@ -46,8 +46,8 @@ describe('', () => { }); it.each([ - [Mock.of({ type: ErrorTypeV3.INVALID_SHORT_URL_DELETION })], - [Mock.of({ type: ErrorTypeV2.INVALID_SHORT_URL_DELETION })], + [fromPartial({ type: ErrorTypeV3.INVALID_SHORT_URL_DELETION })], + [fromPartial({ type: ErrorTypeV2.INVALID_SHORT_URL_DELETION })], ])('shows specific error when threshold error occurs', (errorData) => { setUp({ loading: false, error: true, shortCode: 'abc123', errorData }); expect(screen.getByText('Something went wrong while deleting the URL :(').parentElement).toHaveClass('bg-warning'); diff --git a/test/short-urls/helpers/ExportShortUrlsBtn.test.tsx b/test/short-urls/helpers/ExportShortUrlsBtn.test.tsx index 6f335c62..2e8fb718 100644 --- a/test/short-urls/helpers/ExportShortUrlsBtn.test.tsx +++ b/test/short-urls/helpers/ExportShortUrlsBtn.test.tsx @@ -1,8 +1,9 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { ReportExporter } from '../../../src/common/services/ReportExporter'; -import type { NotFoundServer, ReachableServer, SelectedServer } from '../../../src/servers/data'; +import type { NotFoundServer, SelectedServer } from '../../../src/servers/data'; +import type { ShortUrl } from '../../../src/short-urls/data'; import { ExportShortUrlsBtn as createExportShortUrlsBtn } from '../../../src/short-urls/helpers/ExportShortUrlsBtn'; import { renderWithEvents } from '../../__helpers__/setUpTest'; @@ -10,11 +11,11 @@ describe('', () => { const listShortUrls = jest.fn(); const buildShlinkApiClient = jest.fn().mockReturnValue({ listShortUrls }); const exportShortUrls = jest.fn(); - const reportExporter = Mock.of({ exportShortUrls }); + const reportExporter = fromPartial({ exportShortUrls }); const ExportShortUrlsBtn = createExportShortUrlsBtn(buildShlinkApiClient, reportExporter); const setUp = (amount?: number, selectedServer?: SelectedServer) => renderWithEvents( - ()} amount={amount} /> + , ); @@ -31,7 +32,7 @@ describe('', () => { it.each([ [null], - [Mock.of()], + [fromPartial({})], ])('does nothing on click if selected server is not reachable', async (selectedServer) => { const { user } = setUp(0, selectedServer); @@ -49,11 +50,29 @@ describe('', () => { [385, 20], ])('loads proper amount of pages based on the amount of results', async (amount, expectedPageLoads) => { listShortUrls.mockResolvedValue({ data: [] }); - const { user } = setUp(amount, Mock.of({ id: '123' })); + const { user } = setUp(amount, fromPartial({ id: '123' })); await user.click(screen.getByRole('button')); expect(listShortUrls).toHaveBeenCalledTimes(expectedPageLoads); expect(exportShortUrls).toHaveBeenCalled(); }); + + it('maps short URLs for exporting', async () => { + listShortUrls.mockResolvedValue({ + data: [fromPartial({ + shortUrl: 'https://s.test/short-code', + tags: [], + })], + }); + const { user } = setUp(undefined, fromPartial({ id: '123' })); + + await user.click(screen.getByRole('button')); + + expect(exportShortUrls).toHaveBeenCalledWith([expect.objectContaining({ + shortUrl: 'https://s.test/short-code', + domain: 's.test', + shortCode: 'short-code', + })]); + }); }); diff --git a/test/short-urls/helpers/QrCodeModal.test.tsx b/test/short-urls/helpers/QrCodeModal.test.tsx index 9dc25726..2a43b638 100644 --- a/test/short-urls/helpers/QrCodeModal.test.tsx +++ b/test/short-urls/helpers/QrCodeModal.test.tsx @@ -1,21 +1,18 @@ import { fireEvent, screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; -import type { ImageDownloader } from '../../../src/common/services/ImageDownloader'; -import type { ReachableServer } from '../../../src/servers/data'; -import type { ShortUrl } from '../../../src/short-urls/data'; +import { fromPartial } from '@total-typescript/shoehorn'; import { QrCodeModal as createQrCodeModal } from '../../../src/short-urls/helpers/QrCodeModal'; import type { SemVer } from '../../../src/utils/helpers/version'; import { renderWithEvents } from '../../__helpers__/setUpTest'; describe('', () => { const saveImage = jest.fn().mockReturnValue(Promise.resolve()); - const QrCodeModal = createQrCodeModal(Mock.of({ saveImage })); + const QrCodeModal = createQrCodeModal(fromPartial({ saveImage })); const shortUrl = 'https://s.test/abc123'; const setUp = (version: SemVer = '2.8.0') => renderWithEvents( ({ shortUrl })} - selectedServer={Mock.of({ version })} + shortUrl={fromPartial({ shortUrl })} + selectedServer={fromPartial({ version })} toggle={() => {}} />, ); diff --git a/test/short-urls/helpers/ShortUrlDetailLink.test.tsx b/test/short-urls/helpers/ShortUrlDetailLink.test.tsx index 04187148..5a8bb352 100644 --- a/test/short-urls/helpers/ShortUrlDetailLink.test.tsx +++ b/test/short-urls/helpers/ShortUrlDetailLink.test.tsx @@ -1,6 +1,6 @@ import { render, screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { NotFoundServer, ReachableServer } from '../../../src/servers/data'; import type { ShortUrl } from '../../../src/short-urls/data'; import type { LinkSuffix } from '../../../src/short-urls/helpers/ShortUrlDetailLink'; @@ -10,11 +10,11 @@ describe('', () => { it.each([ [undefined, undefined], [null, null], - [Mock.of({ id: '1' }), null], - [Mock.of({ id: '1' }), undefined], - [Mock.of(), Mock.all()], - [null, Mock.all()], - [undefined, Mock.all()], + [fromPartial({ id: '1' }), null], + [fromPartial({ id: '1' }), undefined], + [fromPartial({}), fromPartial({})], + [null, fromPartial({})], + [undefined, fromPartial({})], ])('only renders a plain span when either server or short URL are not set', (selectedServer, shortUrl) => { render( @@ -28,26 +28,26 @@ describe('', () => { it.each([ [ - Mock.of({ id: '1' }), - Mock.of({ shortCode: 'abc123' }), + fromPartial({ id: '1' }), + fromPartial({ shortCode: 'abc123' }), 'visits' as LinkSuffix, '/server/1/short-code/abc123/visits', ], [ - Mock.of({ id: '3' }), - Mock.of({ shortCode: 'def456', domain: 'example.com' }), + fromPartial({ id: '3' }), + fromPartial({ shortCode: 'def456', domain: 'example.com' }), 'visits' as LinkSuffix, '/server/3/short-code/def456/visits?domain=example.com', ], [ - Mock.of({ id: '1' }), - Mock.of({ shortCode: 'abc123' }), + fromPartial({ id: '1' }), + fromPartial({ shortCode: 'abc123' }), 'edit' as LinkSuffix, '/server/1/short-code/abc123/edit', ], [ - Mock.of({ id: '3' }), - Mock.of({ shortCode: 'def456', domain: 'example.com' }), + fromPartial({ id: '3' }), + fromPartial({ shortCode: 'def456', domain: 'example.com' }), 'edit' as LinkSuffix, '/server/3/short-code/def456/edit?domain=example.com', ], diff --git a/test/short-urls/helpers/ShortUrlStatus.test.tsx b/test/short-urls/helpers/ShortUrlStatus.test.tsx index 1c5ea483..7755bfc8 100644 --- a/test/short-urls/helpers/ShortUrlStatus.test.tsx +++ b/test/short-urls/helpers/ShortUrlStatus.test.tsx @@ -1,6 +1,6 @@ import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkVisitsSummary } from '../../../src/api/types'; import type { ShortUrl, ShortUrlMeta } from '../../../src/short-urls/data'; import { ShortUrlStatus } from '../../../src/short-urls/helpers/ShortUrlStatus'; @@ -13,35 +13,35 @@ describe('', () => { it.each([ [ - Mock.of({ validSince: '2099-01-01T10:30:15' }), + fromPartial({ validSince: '2099-01-01T10:30:15' }), {}, 'This short URL will start working on 2099-01-01 10:30.', ], [ - Mock.of({ validUntil: '2020-01-01T10:30:15' }), + fromPartial({ validUntil: '2020-01-01T10:30:15' }), {}, 'This short URL cannot be visited since 2020-01-01 10:30.', ], [ - Mock.of({ maxVisits: 10 }), - Mock.of({ total: 10 }), + fromPartial({ maxVisits: 10 }), + fromPartial({ total: 10 }), 'This short URL cannot be currently visited because it has reached the maximum amount of 10 visits.', ], [ - Mock.of({ maxVisits: 1 }), - Mock.of({ total: 1 }), + fromPartial({ maxVisits: 1 }), + fromPartial({ total: 1 }), 'This short URL cannot be currently visited because it has reached the maximum amount of 1 visit.', ], [{}, {}, 'This short URL can be visited normally.'], - [Mock.of({ validUntil: '2099-01-01T10:30:15' }), {}, 'This short URL can be visited normally.'], - [Mock.of({ validSince: '2020-01-01T10:30:15' }), {}, 'This short URL can be visited normally.'], + [fromPartial({ validUntil: '2099-01-01T10:30:15' }), {}, 'This short URL can be visited normally.'], + [fromPartial({ validSince: '2020-01-01T10:30:15' }), {}, 'This short URL can be visited normally.'], [ - Mock.of({ maxVisits: 10 }), - Mock.of({ total: 1 }), + fromPartial({ maxVisits: 10 }), + fromPartial({ total: 1 }), 'This short URL can be visited normally.', ], ])('shows expected tooltip', async (meta, visitsSummary, expectedTooltip) => { - const { user } = setUp(Mock.of({ meta, visitsSummary })); + const { user } = setUp(fromPartial({ meta, visitsSummary })); await user.hover(screen.getByRole('img', { hidden: true })); await waitFor(() => expect(screen.getByRole('tooltip')).toHaveTextContent(expectedTooltip)); diff --git a/test/short-urls/helpers/ShortUrlVisitsCount.test.tsx b/test/short-urls/helpers/ShortUrlVisitsCount.test.tsx index 8fa8141c..b810fa6e 100644 --- a/test/short-urls/helpers/ShortUrlVisitsCount.test.tsx +++ b/test/short-urls/helpers/ShortUrlVisitsCount.test.tsx @@ -1,6 +1,6 @@ import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShortUrl } from '../../../src/short-urls/data'; import { ShortUrlVisitsCount } from '../../../src/short-urls/helpers/ShortUrlVisitsCount'; @@ -14,7 +14,7 @@ describe('', () => { it.each([undefined, {}])('just returns visits when no limits are provided', (meta) => { const visitsCount = 45; - const { container } = setUp(visitsCount, Mock.of({ meta })); + const { container } = setUp(visitsCount, fromPartial({ meta })); expect(container.firstChild).toHaveTextContent(`${visitsCount}`); expect(container.querySelector('.short-urls-visits-count__max-visits-control')).not.toBeInTheDocument(); @@ -24,7 +24,7 @@ describe('', () => { const visitsCount = 45; const maxVisits = 500; const meta = { maxVisits }; - const { container } = setUp(visitsCount, Mock.of({ meta })); + const { container } = setUp(visitsCount, fromPartial({ meta })); expect(container.firstChild).toHaveTextContent(`/ ${maxVisits}`); }); @@ -44,7 +44,7 @@ describe('', () => { 'This short URL will not accept visits after 2023-05-05 15:30', ], { validSince: '2023-01-01T10:00:00', validUntil: '2023-05-05T15:30:30', maxVisits: 100 }], ])('displays proper amount of tooltip list items', async (expectedListItems, meta) => { - const { user } = setUp(100, Mock.of({ meta })); + const { user } = setUp(100, fromPartial({ meta })); await user.hover(screen.getByRole('img', { hidden: true })); await waitFor(() => expect(screen.getByRole('list'))); diff --git a/test/short-urls/helpers/ShortUrlsRow.test.tsx b/test/short-urls/helpers/ShortUrlsRow.test.tsx index f4482422..1d2cd884 100644 --- a/test/short-urls/helpers/ShortUrlsRow.test.tsx +++ b/test/short-urls/helpers/ShortUrlsRow.test.tsx @@ -1,8 +1,8 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { addDays, formatISO, subDays } from 'date-fns'; import { last } from 'ramda'; import { MemoryRouter, useLocation } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { ReachableServer } from '../../../src/servers/data'; import type { Settings } from '../../../src/settings/reducers/settings'; import type { ShortUrl, ShortUrlMeta } from '../../../src/short-urls/data'; @@ -28,7 +28,7 @@ jest.mock('react-router-dom', () => ({ describe('', () => { const timeoutToggle = jest.fn(() => true); const useTimeoutToggle = jest.fn(() => [false, timeoutToggle]) as TimeoutToggle; - const server = Mock.of({ url: 'https://s.test' }); + const server = fromPartial({ url: 'https://s.test' }); const shortUrl: ShortUrl = { shortCode: 'abc123', shortUrl: 'https://s.test/abc123', @@ -60,7 +60,7 @@ describe('', () => { selectedServer={server} shortUrl={{ ...shortUrl, title, tags, meta: { ...shortUrl.meta, ...meta } }} onTagClick={() => null} - settings={Mock.of(settings)} + settings={fromPartial(settings)} /> @@ -118,13 +118,13 @@ describe('', () => { it.each([ [{}, '', shortUrl.visitsSummary?.total], - [Mock.of({ visits: { excludeBots: false } }), '', shortUrl.visitsSummary?.total], - [Mock.of({ visits: { excludeBots: true } }), '', shortUrl.visitsSummary?.nonBots], - [Mock.of({ visits: { excludeBots: false } }), 'excludeBots=true', shortUrl.visitsSummary?.nonBots], - [Mock.of({ visits: { excludeBots: true } }), 'excludeBots=true', shortUrl.visitsSummary?.nonBots], + [fromPartial({ visits: { excludeBots: false } }), '', shortUrl.visitsSummary?.total], + [fromPartial({ visits: { excludeBots: true } }), '', shortUrl.visitsSummary?.nonBots], + [fromPartial({ visits: { excludeBots: false } }), 'excludeBots=true', shortUrl.visitsSummary?.nonBots], + [fromPartial({ visits: { excludeBots: true } }), 'excludeBots=true', shortUrl.visitsSummary?.nonBots], [{}, 'excludeBots=true', shortUrl.visitsSummary?.nonBots], - [Mock.of({ visits: { excludeBots: true } }), 'excludeBots=false', shortUrl.visitsSummary?.total], - [Mock.of({ visits: { excludeBots: false } }), 'excludeBots=false', shortUrl.visitsSummary?.total], + [fromPartial({ visits: { excludeBots: true } }), 'excludeBots=false', shortUrl.visitsSummary?.total], + [fromPartial({ visits: { excludeBots: false } }), 'excludeBots=false', shortUrl.visitsSummary?.total], [{}, 'excludeBots=false', shortUrl.visitsSummary?.total], ])('renders visits count in fifth row', (settings, search, expectedAmount) => { setUp({ settings }, search); diff --git a/test/short-urls/helpers/ShortUrlsRowMenu.test.tsx b/test/short-urls/helpers/ShortUrlsRowMenu.test.tsx index ba64ff51..c78ec61b 100644 --- a/test/short-urls/helpers/ShortUrlsRowMenu.test.tsx +++ b/test/short-urls/helpers/ShortUrlsRowMenu.test.tsx @@ -1,6 +1,6 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; import type { ReachableServer } from '../../../src/servers/data'; import type { ShortUrl } from '../../../src/short-urls/data'; import { ShortUrlsRowMenu as createShortUrlsRowMenu } from '../../../src/short-urls/helpers/ShortUrlsRowMenu'; @@ -8,8 +8,8 @@ import { renderWithEvents } from '../../__helpers__/setUpTest'; describe('', () => { const ShortUrlsRowMenu = createShortUrlsRowMenu(() => DeleteShortUrlModal, () => QrCodeModal); - const selectedServer = Mock.of({ id: 'abc123' }); - const shortUrl = Mock.of({ + const selectedServer = fromPartial({ id: 'abc123' }); + const shortUrl = fromPartial({ shortCode: 'abc123', shortUrl: 'https://s.test/abc123', }); diff --git a/test/short-urls/helpers/index.test.ts b/test/short-urls/helpers/index.test.ts index bc33c1d5..6f252950 100644 --- a/test/short-urls/helpers/index.test.ts +++ b/test/short-urls/helpers/index.test.ts @@ -1,4 +1,4 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShortUrl } from '../../../src/short-urls/data'; import { shortUrlDataFromShortUrl, urlDecodeShortCode, urlEncodeShortCode } from '../../../src/short-urls/helpers'; @@ -8,7 +8,7 @@ describe('helpers', () => { [undefined, { validateUrls: true }, { longUrl: '', validateUrl: true }], [undefined, undefined, { longUrl: '', validateUrl: false }], [ - Mock.of({ meta: {} }), + fromPartial({ meta: {} }), { validateUrls: false }, { longUrl: undefined, diff --git a/test/short-urls/reducers/shortUrlCreation.test.ts b/test/short-urls/reducers/shortUrlCreation.test.ts index deeda1fe..e1e14a9e 100644 --- a/test/short-urls/reducers/shortUrlCreation.test.ts +++ b/test/short-urls/reducers/shortUrlCreation.test.ts @@ -1,16 +1,16 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkState } from '../../../src/container/types'; -import type { ShortUrl, ShortUrlData } from '../../../src/short-urls/data'; +import type { ShortUrl } from '../../../src/short-urls/data'; import { createShortUrl as createShortUrlCreator, shortUrlCreationReducerCreator, } from '../../../src/short-urls/reducers/shortUrlCreation'; describe('shortUrlCreationReducer', () => { - const shortUrl = Mock.of(); + const shortUrl = fromPartial({}); const createShortUrlCall = jest.fn(); - const buildShlinkApiClient = () => Mock.of({ createShortUrl: createShortUrlCall }); + const buildShlinkApiClient = () => fromPartial({ createShortUrl: createShortUrlCall }); const createShortUrl = createShortUrlCreator(buildShlinkApiClient); const { reducer, resetCreateShortUrl } = shortUrlCreationReducerCreator(createShortUrl); @@ -18,7 +18,7 @@ describe('shortUrlCreationReducer', () => { describe('reducer', () => { it('returns loading on CREATE_SHORT_URL_START', () => { - expect(reducer(undefined, createShortUrl.pending('', Mock.all()))).toEqual({ + expect(reducer(undefined, createShortUrl.pending('', fromPartial({})))).toEqual({ saving: true, saved: false, error: false, @@ -26,7 +26,7 @@ describe('shortUrlCreationReducer', () => { }); it('returns error on CREATE_SHORT_URL_ERROR', () => { - expect(reducer(undefined, createShortUrl.rejected(null, '', Mock.all()))).toEqual({ + expect(reducer(undefined, createShortUrl.rejected(null, '', fromPartial({})))).toEqual({ saving: false, saved: false, error: true, @@ -34,7 +34,7 @@ describe('shortUrlCreationReducer', () => { }); it('returns result on CREATE_SHORT_URL', () => { - expect(reducer(undefined, createShortUrl.fulfilled(shortUrl, '', Mock.all()))).toEqual({ + expect(reducer(undefined, createShortUrl.fulfilled(shortUrl, '', fromPartial({})))).toEqual({ result: shortUrl, saving: false, saved: true, @@ -53,7 +53,7 @@ describe('shortUrlCreationReducer', () => { describe('createShortUrl', () => { const dispatch = jest.fn(); - const getState = () => Mock.all(); + const getState = () => fromPartial({}); it('calls API on success', async () => { createShortUrlCall.mockResolvedValue(shortUrl); diff --git a/test/short-urls/reducers/shortUrlDeletion.test.ts b/test/short-urls/reducers/shortUrlDeletion.test.ts index 1db369a6..74f7017b 100644 --- a/test/short-urls/reducers/shortUrlDeletion.test.ts +++ b/test/short-urls/reducers/shortUrlDeletion.test.ts @@ -1,15 +1,15 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ProblemDetailsError } from '../../../src/api/types/errors'; import { - deleteShortUrl as deleteShortUrlCretor, + deleteShortUrl as deleteShortUrlCreator, shortUrlDeletionReducerCreator, } from '../../../src/short-urls/reducers/shortUrlDeletion'; describe('shortUrlDeletionReducer', () => { const deleteShortUrlCall = jest.fn(); - const buildShlinkApiClient = () => Mock.of({ deleteShortUrl: deleteShortUrlCall }); - const deleteShortUrl = deleteShortUrlCretor(buildShlinkApiClient); + const buildShlinkApiClient = () => fromPartial({ deleteShortUrl: deleteShortUrlCall }); + const deleteShortUrl = deleteShortUrlCreator(buildShlinkApiClient); const { reducer, resetDeleteShortUrl } = shortUrlDeletionReducerCreator(deleteShortUrl); beforeEach(jest.clearAllMocks); @@ -40,7 +40,9 @@ describe('shortUrlDeletionReducer', () => { })); it('returns errorData on DELETE_SHORT_URL_ERROR', () => { - const errorData = Mock.of({ type: 'bar', detail: 'detail', title: 'title', status: 400 }); + const errorData = fromPartial( + { type: 'bar', detail: 'detail', title: 'title', status: 400 }, + ); const error = errorData as unknown as Error; expect(reducer(undefined, deleteShortUrl.rejected(error, '', { shortCode: '' }))).toEqual({ diff --git a/test/short-urls/reducers/shortUrlDetail.test.ts b/test/short-urls/reducers/shortUrlDetail.test.ts index 52ffa603..5aee45b2 100644 --- a/test/short-urls/reducers/shortUrlDetail.test.ts +++ b/test/short-urls/reducers/shortUrlDetail.test.ts @@ -1,4 +1,4 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkState } from '../../../src/container/types'; import type { ShortUrl } from '../../../src/short-urls/data'; @@ -7,7 +7,7 @@ import type { ShortUrlsList } from '../../../src/short-urls/reducers/shortUrlsLi describe('shortUrlDetailReducer', () => { const getShortUrlCall = jest.fn(); - const buildShlinkApiClient = () => Mock.of({ getShortUrl: getShortUrlCall }); + const buildShlinkApiClient = () => fromPartial({ getShortUrl: getShortUrlCall }); const { reducer, getShortUrlDetail } = shortUrlDetailReducerCreator(buildShlinkApiClient); beforeEach(jest.clearAllMocks); @@ -27,7 +27,7 @@ describe('shortUrlDetailReducer', () => { }); it('return short URL on GET_SHORT_URL_DETAIL', () => { - const actionShortUrl = Mock.of({ longUrl: 'foo', shortCode: 'bar' }); + const actionShortUrl = fromPartial({ longUrl: 'foo', shortCode: 'bar' }); const state = reducer( { loading: true, error: false }, getShortUrlDetail.fulfilled(actionShortUrl, '', { shortCode: '' }), @@ -42,25 +42,25 @@ describe('shortUrlDetailReducer', () => { describe('getShortUrlDetail', () => { const dispatchMock = jest.fn(); - const buildGetState = (shortUrlsList?: ShortUrlsList) => () => Mock.of({ shortUrlsList }); + const buildGetState = (shortUrlsList?: ShortUrlsList) => () => fromPartial({ shortUrlsList }); it.each([ [undefined], - [Mock.all()], + [fromPartial({})], [ - Mock.of({ + fromPartial({ shortUrls: { data: [] }, }), ], [ - Mock.of({ + fromPartial({ shortUrls: { - data: [Mock.of({ shortCode: 'this_will_not_match' })], + data: [{ shortCode: 'this_will_not_match' }], }, }), ], ])('performs API call when short URL is not found in local state', async (shortUrlsList?: ShortUrlsList) => { - const resolvedShortUrl = Mock.of({ longUrl: 'foo', shortCode: 'abc123' }); + const resolvedShortUrl = fromPartial({ longUrl: 'foo', shortCode: 'abc123' }); getShortUrlCall.mockResolvedValue(resolvedShortUrl); await getShortUrlDetail({ shortCode: 'abc123', domain: '' })(dispatchMock, buildGetState(shortUrlsList), {}); @@ -71,12 +71,12 @@ describe('shortUrlDetailReducer', () => { }); it('avoids API calls when short URL is found in local state', async () => { - const foundShortUrl = Mock.of({ longUrl: 'foo', shortCode: 'abc123' }); - getShortUrlCall.mockResolvedValue(Mock.all()); + const foundShortUrl = fromPartial({ longUrl: 'foo', shortCode: 'abc123' }); + getShortUrlCall.mockResolvedValue(fromPartial({})); await getShortUrlDetail(foundShortUrl)( dispatchMock, - buildGetState(Mock.of({ + buildGetState(fromPartial({ shortUrls: { data: [foundShortUrl], }, diff --git a/test/short-urls/reducers/shortUrlEdition.test.ts b/test/short-urls/reducers/shortUrlEdition.test.ts index c5ef958b..e1f143f2 100644 --- a/test/short-urls/reducers/shortUrlEdition.test.ts +++ b/test/short-urls/reducers/shortUrlEdition.test.ts @@ -1,8 +1,7 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkState } from '../../../src/container/types'; import type { SelectedServer } from '../../../src/servers/data'; import type { ShortUrl } from '../../../src/short-urls/data'; -import type { EditShortUrl } from '../../../src/short-urls/reducers/shortUrlEdition'; import { editShortUrl as editShortUrlCreator, shortUrlEditionReducerCreator, @@ -11,7 +10,7 @@ import { describe('shortUrlEditionReducer', () => { const longUrl = 'https://shlink.io'; const shortCode = 'abc123'; - const shortUrl = Mock.of({ longUrl, shortCode }); + const shortUrl = fromPartial({ longUrl, shortCode }); const updateShortUrl = jest.fn().mockResolvedValue(shortUrl); const buildShlinkApiClient = jest.fn().mockReturnValue({ updateShortUrl }); const editShortUrl = editShortUrlCreator(buildShlinkApiClient); @@ -21,7 +20,7 @@ describe('shortUrlEditionReducer', () => { describe('reducer', () => { it('returns loading on EDIT_SHORT_URL_START', () => { - expect(reducer(undefined, editShortUrl.pending('', Mock.all()))).toEqual({ + expect(reducer(undefined, editShortUrl.pending('', fromPartial({})))).toEqual({ saving: true, saved: false, error: false, @@ -29,7 +28,7 @@ describe('shortUrlEditionReducer', () => { }); it('returns error on EDIT_SHORT_URL_ERROR', () => { - expect(reducer(undefined, editShortUrl.rejected(null, '', Mock.all()))).toEqual({ + expect(reducer(undefined, editShortUrl.rejected(null, '', fromPartial({})))).toEqual({ saving: false, saved: false, error: true, @@ -37,7 +36,7 @@ describe('shortUrlEditionReducer', () => { }); it('returns provided tags and shortCode on SHORT_URL_EDITED', () => { - expect(reducer(undefined, editShortUrl.fulfilled(shortUrl, '', Mock.all()))).toEqual({ + expect(reducer(undefined, editShortUrl.fulfilled(shortUrl, '', fromPartial({})))).toEqual({ shortUrl, saving: false, saved: true, @@ -48,7 +47,9 @@ describe('shortUrlEditionReducer', () => { describe('editShortUrl', () => { const dispatch = jest.fn(); - const createGetState = (selectedServer: SelectedServer = null) => () => Mock.of({ selectedServer }); + const createGetState = (selectedServer: SelectedServer = null) => () => fromPartial({ + selectedServer, + }); afterEach(jest.clearAllMocks); diff --git a/test/short-urls/reducers/shortUrlsList.test.ts b/test/short-urls/reducers/shortUrlsList.test.ts index f03aea60..2954ac8f 100644 --- a/test/short-urls/reducers/shortUrlsList.test.ts +++ b/test/short-urls/reducers/shortUrlsList.test.ts @@ -1,10 +1,9 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; -import type { ShlinkPaginator, ShlinkShortUrlsResponse } from '../../../src/api/types'; -import type { ShortUrl, ShortUrlData } from '../../../src/short-urls/data'; +import type { ShlinkShortUrlsResponse } from '../../../src/api/types'; +import type { ShortUrl } from '../../../src/short-urls/data'; import { createShortUrl as createShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlCreation'; import { shortUrlDeleted } from '../../../src/short-urls/reducers/shortUrlDeletion'; -import type { EditShortUrl } from '../../../src/short-urls/reducers/shortUrlEdition'; import { editShortUrl as editShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlEdition'; import { listShortUrls as listShortUrlsCreator, @@ -16,7 +15,7 @@ import type { CreateVisit } from '../../../src/visits/types'; describe('shortUrlsListReducer', () => { const shortCode = 'abc123'; const listShortUrlsMock = jest.fn(); - const buildShlinkApiClient = () => Mock.of({ listShortUrls: listShortUrlsMock }); + const buildShlinkApiClient = () => fromPartial({ listShortUrls: listShortUrlsMock }); const listShortUrls = listShortUrlsCreator(buildShlinkApiClient); const editShortUrl = editShortUrlCreator(buildShlinkApiClient); const createShortUrl = createShortUrlCreator(buildShlinkApiClient); @@ -32,7 +31,7 @@ describe('shortUrlsListReducer', () => { })); it('returns short URLs on LIST_SHORT_URLS', () => - expect(reducer(undefined, listShortUrls.fulfilled(Mock.of({ data: [] }), ''))).toEqual({ + expect(reducer(undefined, listShortUrls.fulfilled(fromPartial({ data: [] }), ''))).toEqual({ shortUrls: { data: [] }, loading: false, error: false, @@ -46,21 +45,19 @@ describe('shortUrlsListReducer', () => { it('removes matching URL and reduces total on SHORT_URL_DELETED', () => { const state = { - shortUrls: Mock.of({ + shortUrls: fromPartial({ data: [ - Mock.of({ shortCode }), - Mock.of({ shortCode, domain: 'example.com' }), - Mock.of({ shortCode: 'foo' }), + { shortCode }, + { shortCode, domain: 'example.com' }, + { shortCode: 'foo' }, ], - pagination: Mock.of({ - totalItems: 10, - }), + pagination: { totalItems: 10 }, }), loading: false, error: false, }; - expect(reducer(state, shortUrlDeleted(Mock.of({ shortCode })))).toEqual({ + expect(reducer(state, shortUrlDeleted(fromPartial({ shortCode })))).toEqual({ shortUrls: { data: [{ shortCode, domain: 'example.com' }, { shortCode: 'foo' }], pagination: { totalItems: 9 }, @@ -70,7 +67,7 @@ describe('shortUrlsListReducer', () => { }); }); - const createNewShortUrlVisit = (visitsCount: number) => Mock.of({ + const createNewShortUrlVisit = (visitsCount: number) => fromPartial({ shortUrl: { shortCode: 'abc123', visitsCount }, }); @@ -81,11 +78,11 @@ describe('shortUrlsListReducer', () => { [[], 10], ])('updates visits count on CREATE_VISITS', (createdVisits, expectedCount) => { const state = { - shortUrls: Mock.of({ + shortUrls: fromPartial({ data: [ - Mock.of({ shortCode, domain: 'example.com', visitsCount: 5 }), - Mock.of({ shortCode, visitsCount: 10 }), - Mock.of({ shortCode: 'foo', visitsCount: 8 }), + { shortCode, domain: 'example.com', visitsCount: 5 }, + { shortCode, visitsCount: 10 }, + { shortCode: 'foo', visitsCount: 8 }, ], }), loading: false, @@ -108,48 +105,46 @@ describe('shortUrlsListReducer', () => { it.each([ [ [ - Mock.of({ shortCode }), - Mock.of({ shortCode, domain: 'example.com' }), - Mock.of({ shortCode: 'foo' }), + fromPartial({ shortCode }), + fromPartial({ shortCode, domain: 'example.com' }), + fromPartial({ shortCode: 'foo' }), ], [{ shortCode: 'newOne' }, { shortCode }, { shortCode, domain: 'example.com' }, { shortCode: 'foo' }], ], [ [ - Mock.of({ shortCode }), - Mock.of({ shortCode: 'code' }), - Mock.of({ shortCode: 'foo' }), - Mock.of({ shortCode: 'bar' }), - Mock.of({ shortCode: 'baz' }), + fromPartial({ shortCode }), + fromPartial({ shortCode: 'code' }), + fromPartial({ shortCode: 'foo' }), + fromPartial({ shortCode: 'bar' }), + fromPartial({ shortCode: 'baz' }), ], [{ shortCode: 'newOne' }, { shortCode }, { shortCode: 'code' }, { shortCode: 'foo' }, { shortCode: 'bar' }], ], [ [ - Mock.of({ shortCode }), - Mock.of({ shortCode: 'code' }), - Mock.of({ shortCode: 'foo' }), - Mock.of({ shortCode: 'bar' }), - Mock.of({ shortCode: 'baz1' }), - Mock.of({ shortCode: 'baz2' }), - Mock.of({ shortCode: 'baz3' }), + fromPartial({ shortCode }), + fromPartial({ shortCode: 'code' }), + fromPartial({ shortCode: 'foo' }), + fromPartial({ shortCode: 'bar' }), + fromPartial({ shortCode: 'baz1' }), + fromPartial({ shortCode: 'baz2' }), + fromPartial({ shortCode: 'baz3' }), ], [{ shortCode: 'newOne' }, { shortCode }, { shortCode: 'code' }, { shortCode: 'foo' }, { shortCode: 'bar' }], ], ])('prepends new short URL and increases total on CREATE_SHORT_URL', (data, expectedData) => { - const newShortUrl = Mock.of({ shortCode: 'newOne' }); + const newShortUrl = fromPartial({ shortCode: 'newOne' }); const state = { - shortUrls: Mock.of({ + shortUrls: fromPartial({ data, - pagination: Mock.of({ - totalItems: 15, - }), + pagination: { totalItems: 15 }, }), loading: false, error: false, }; - expect(reducer(state, createShortUrl.fulfilled(newShortUrl, '', Mock.all()))).toEqual({ + expect(reducer(state, createShortUrl.fulfilled(newShortUrl, '', fromPartial({})))).toEqual({ shortUrls: { data: expectedData, pagination: { totalItems: 16 }, @@ -161,16 +156,16 @@ describe('shortUrlsListReducer', () => { it.each([ ((): [ShortUrl, ShortUrl[], ShortUrl[]] => { - const editedShortUrl = Mock.of({ shortCode: 'notMatching' }); - const list = [Mock.of({ shortCode: 'foo' }), Mock.of({ shortCode: 'bar' })]; + const editedShortUrl = fromPartial({ shortCode: 'notMatching' }); + const list: ShortUrl[] = [fromPartial({ shortCode: 'foo' }), fromPartial({ shortCode: 'bar' })]; return [editedShortUrl, list, list]; })(), ((): [ShortUrl, ShortUrl[], ShortUrl[]] => { - const editedShortUrl = Mock.of({ shortCode: 'matching', longUrl: 'new_one' }); - const list = [ - Mock.of({ shortCode: 'matching', longUrl: 'old_one' }), - Mock.of({ shortCode: 'bar' }), + const editedShortUrl = fromPartial({ shortCode: 'matching', longUrl: 'new_one' }); + const list: ShortUrl[] = [ + fromPartial({ shortCode: 'matching', longUrl: 'old_one' }), + fromPartial({ shortCode: 'bar' }), ]; const expectedList = [editedShortUrl, list[1]]; @@ -178,17 +173,15 @@ describe('shortUrlsListReducer', () => { })(), ])('updates matching short URL on SHORT_URL_EDITED', (editedShortUrl, initialList, expectedList) => { const state = { - shortUrls: Mock.of({ + shortUrls: fromPartial({ data: initialList, - pagination: Mock.of({ - totalItems: 15, - }), + pagination: { totalItems: 15 }, }), loading: false, error: false, }; - const result = reducer(state, editShortUrl.fulfilled(editedShortUrl, '', Mock.of())); + const result = reducer(state, editShortUrl.fulfilled(editedShortUrl, '', fromPartial({}))); expect(result.shortUrls?.data).toEqual(expectedList); }); diff --git a/test/tags/TagsList.test.tsx b/test/tags/TagsList.test.tsx index 19f59b25..f486054b 100644 --- a/test/tags/TagsList.test.tsx +++ b/test/tags/TagsList.test.tsx @@ -1,8 +1,7 @@ import { screen, waitFor } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { identity } from 'ramda'; -import { Mock } from 'ts-mockery'; import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub'; -import type { Settings } from '../../src/settings/reducers/settings'; import type { TagsList } from '../../src/tags/reducers/tagsList'; import type { TagsListProps } from '../../src/tags/TagsList'; import { TagsList as createTagsList } from '../../src/tags/TagsList'; @@ -13,12 +12,12 @@ describe('', () => { const TagsListComp = createTagsList(({ sortedTags }) => <>TagsTable ({sortedTags.map((t) => t.visits).join(',')})); const setUp = (tagsList: Partial, excludeBots = false) => renderWithEvents( ()} - {...Mock.of({ mercureInfo: {} })} + {...fromPartial({})} + {...fromPartial({ mercureInfo: {} })} forceListTags={identity} filterTags={filterTags} - tagsList={Mock.of(tagsList)} - settings={Mock.of({ visits: { excludeBots } })} + tagsList={fromPartial(tagsList)} + settings={fromPartial({ visits: { excludeBots } })} />, ); diff --git a/test/tags/TagsTable.test.tsx b/test/tags/TagsTable.test.tsx index da187a6a..ad41c4ce 100644 --- a/test/tags/TagsTable.test.tsx +++ b/test/tags/TagsTable.test.tsx @@ -1,8 +1,6 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { useLocation } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; -import type { SelectedServer } from '../../src/servers/data'; -import type { SimplifiedTag } from '../../src/tags/data'; import { TagsTable as createTagsTable } from '../../src/tags/TagsTable'; import { rangeOf } from '../../src/utils/utils'; import { renderWithEvents } from '../__helpers__/setUpTest'; @@ -17,8 +15,8 @@ describe('', () => { (useLocation as any).mockReturnValue({ search }); return renderWithEvents( Mock.of({ tag }))} - selectedServer={Mock.all()} + sortedTags={sortedTags.map((tag) => fromPartial({ tag }))} + selectedServer={fromPartial({})} currentOrder={{}} orderByColumn={() => orderByColumn} />, diff --git a/test/tags/TagsTableRow.test.tsx b/test/tags/TagsTableRow.test.tsx index 4f3a133a..ec2c4e8a 100644 --- a/test/tags/TagsTableRow.test.tsx +++ b/test/tags/TagsTableRow.test.tsx @@ -1,7 +1,6 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; -import type { ReachableServer } from '../../src/servers/data'; import { TagsTableRow as createTagsTableRow } from '../../src/tags/TagsTableRow'; import { renderWithEvents } from '../__helpers__/setUpTest'; import { colorGeneratorMock } from '../utils/services/__mocks__/ColorGenerator.mock'; @@ -18,7 +17,7 @@ describe('', () => { ({ id: 'abc123' })} + selectedServer={fromPartial({ id: 'abc123' })} /> diff --git a/test/tags/helpers/EditTagModal.test.tsx b/test/tags/helpers/EditTagModal.test.tsx index 0b6a96b7..674f4fd5 100644 --- a/test/tags/helpers/EditTagModal.test.tsx +++ b/test/tags/helpers/EditTagModal.test.tsx @@ -1,17 +1,15 @@ import { screen, waitFor } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; -import type { ProblemDetailsError } from '../../../src/api/types/errors'; +import { fromPartial } from '@total-typescript/shoehorn'; import { EditTagModal as createEditTagModal } from '../../../src/tags/helpers/EditTagModal'; import type { TagEdition } from '../../../src/tags/reducers/tagEdit'; -import type { ColorGenerator } from '../../../src/utils/services/ColorGenerator'; import { renderWithEvents } from '../../__helpers__/setUpTest'; describe('', () => { - const EditTagModal = createEditTagModal(Mock.of({ getColorForKey: jest.fn(() => 'green') })); + const EditTagModal = createEditTagModal(fromPartial({ getColorForKey: jest.fn(() => 'green') })); const editTag = jest.fn().mockReturnValue(Promise.resolve()); const toggle = jest.fn(); const setUp = (tagEdit: Partial = {}) => { - const edition = Mock.of(tagEdit); + const edition = fromPartial(tagEdit); return renderWithEvents( , ); @@ -43,7 +41,7 @@ describe('', () => { [true, 1], [false, 0], ])('displays error result in case of error', (error, expectedResultCount) => { - setUp({ error, errorData: Mock.all() }); + setUp({ error, errorData: fromPartial({}) }); expect(screen.queryAllByText('Something went wrong while editing the tag :(')).toHaveLength(expectedResultCount); }); diff --git a/test/tags/helpers/Tag.test.tsx b/test/tags/helpers/Tag.test.tsx index 46f224e7..d754aebd 100644 --- a/test/tags/helpers/Tag.test.tsx +++ b/test/tags/helpers/Tag.test.tsx @@ -1,6 +1,6 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ReactNode } from 'react'; -import { Mock } from 'ts-mockery'; import { Tag } from '../../../src/tags/helpers/Tag'; import type { ColorGenerator } from '../../../src/utils/services/ColorGenerator'; import { MAIN_COLOR } from '../../../src/utils/theme'; @@ -24,7 +24,7 @@ describe('', () => { const onClose = jest.fn(); const isColorLightForKey = jest.fn(() => false); const getColorForKey = jest.fn(() => MAIN_COLOR); - const colorGenerator = Mock.of({ getColorForKey, isColorLightForKey }); + const colorGenerator = fromPartial({ getColorForKey, isColorLightForKey }); const setUp = (text: string, clearable?: boolean, children?: ReactNode) => renderWithEvents( {children} diff --git a/test/tags/helpers/TagsSelector.test.tsx b/test/tags/helpers/TagsSelector.test.tsx index 398a0e93..f0a6fd3a 100644 --- a/test/tags/helpers/TagsSelector.test.tsx +++ b/test/tags/helpers/TagsSelector.test.tsx @@ -1,6 +1,5 @@ import { screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; -import type { Settings } from '../../../src/settings/reducers/settings'; +import { fromPartial } from '@total-typescript/shoehorn'; import { TagsSelector as createTagsSelector } from '../../../src/tags/helpers/TagsSelector'; import type { TagsList } from '../../../src/tags/reducers/tagsList'; import { renderWithEvents } from '../../__helpers__/setUpTest'; @@ -10,12 +9,12 @@ describe('', () => { const onChange = jest.fn(); const TagsSelector = createTagsSelector(colorGeneratorMock); const tags = ['foo', 'bar']; - const tagsList = Mock.of({ tags: [...tags, 'baz'] }); + const tagsList = fromPartial({ tags: [...tags, 'baz'] }); const setUp = () => renderWithEvents( ()} + settings={fromPartial({})} listTags={jest.fn()} onChange={onChange} />, diff --git a/test/tags/reducers/tagDelete.test.ts b/test/tags/reducers/tagDelete.test.ts index e07b964d..640cd88c 100644 --- a/test/tags/reducers/tagDelete.test.ts +++ b/test/tags/reducers/tagDelete.test.ts @@ -1,11 +1,11 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkState } from '../../../src/container/types'; import { tagDeleted, tagDeleteReducerCreator } from '../../../src/tags/reducers/tagDelete'; describe('tagDeleteReducer', () => { const deleteTagsCall = jest.fn(); - const buildShlinkApiClient = () => Mock.of({ deleteTags: deleteTagsCall }); + const buildShlinkApiClient = () => fromPartial({ deleteTags: deleteTagsCall }); const { reducer, deleteTag } = tagDeleteReducerCreator(buildShlinkApiClient); beforeEach(jest.clearAllMocks); @@ -44,7 +44,7 @@ describe('tagDeleteReducer', () => { describe('deleteTag', () => { const dispatch = jest.fn(); - const getState = () => Mock.all(); + const getState = () => fromPartial({}); it('calls API on success', async () => { const tag = 'foo'; diff --git a/test/tags/reducers/tagEdit.test.ts b/test/tags/reducers/tagEdit.test.ts index 8e3f0ba2..f5b4426c 100644 --- a/test/tags/reducers/tagEdit.test.ts +++ b/test/tags/reducers/tagEdit.test.ts @@ -1,7 +1,6 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkState } from '../../../src/container/types'; -import type { EditTag } from '../../../src/tags/reducers/tagEdit'; import { editTag as editTagCreator, tagEdited, tagEditReducerCreator } from '../../../src/tags/reducers/tagEdit'; import type { ColorGenerator } from '../../../src/utils/services/ColorGenerator'; @@ -10,14 +9,14 @@ describe('tagEditReducer', () => { const newName = 'bar'; const color = '#ff0000'; const editTagCall = jest.fn(); - const buildShlinkApiClient = () => Mock.of({ editTag: editTagCall }); - const colorGenerator = Mock.of({ setColorForKey: jest.fn() }); + const buildShlinkApiClient = () => fromPartial({ editTag: editTagCall }); + const colorGenerator = fromPartial({ setColorForKey: jest.fn() }); const editTag = editTagCreator(buildShlinkApiClient, colorGenerator); const { reducer } = tagEditReducerCreator(editTag); describe('reducer', () => { it('returns loading on EDIT_TAG_START', () => { - expect(reducer(undefined, editTag.pending('', Mock.all()))).toEqual({ + expect(reducer(undefined, editTag.pending('', fromPartial({})))).toEqual({ editing: true, edited: false, error: false, @@ -25,7 +24,7 @@ describe('tagEditReducer', () => { }); it('returns error on EDIT_TAG_ERROR', () => { - expect(reducer(undefined, editTag.rejected(null, '', Mock.all()))).toEqual({ + expect(reducer(undefined, editTag.rejected(null, '', fromPartial({})))).toEqual({ editing: false, edited: false, error: true, @@ -33,7 +32,7 @@ describe('tagEditReducer', () => { }); it('returns tag names on EDIT_TAG', () => { - expect(reducer(undefined, editTag.fulfilled({ oldName, newName, color }, '', Mock.all()))).toEqual({ + expect(reducer(undefined, editTag.fulfilled({ oldName, newName, color }, '', fromPartial({})))).toEqual({ editing: false, edited: true, error: false, @@ -52,7 +51,7 @@ describe('tagEditReducer', () => { describe('editTag', () => { const dispatch = jest.fn(); - const getState = () => Mock.of(); + const getState = () => fromPartial({}); afterEach(jest.clearAllMocks); diff --git a/test/tags/reducers/tagsList.test.ts b/test/tags/reducers/tagsList.test.ts index d8f9cfe1..09936db2 100644 --- a/test/tags/reducers/tagsList.test.ts +++ b/test/tags/reducers/tagsList.test.ts @@ -1,6 +1,6 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkState } from '../../../src/container/types'; -import type { ShortUrl, ShortUrlData } from '../../../src/short-urls/data'; +import type { ShortUrl } from '../../../src/short-urls/data'; import { createShortUrl as createShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlCreation'; import { tagDeleted } from '../../../src/tags/reducers/tagDelete'; import { tagEdited } from '../../../src/tags/reducers/tagEdit'; @@ -12,10 +12,10 @@ import { tagsListReducerCreator, } from '../../../src/tags/reducers/tagsList'; import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; -import type { CreateVisit, Visit } from '../../../src/visits/types'; +import type { CreateVisit } from '../../../src/visits/types'; describe('tagsListReducer', () => { - const state = (props: Partial) => Mock.of(props); + const state = (props: Partial) => fromPartial(props); const buildShlinkApiClient = jest.fn(); const listTags = listTagsCreator(buildShlinkApiClient, true); const createShortUrl = createShortUrlCreator(buildShlinkApiClient); @@ -41,7 +41,7 @@ describe('tagsListReducer', () => { it('returns provided tags as filtered and regular tags on LIST_TAGS', () => { const tags = ['foo', 'bar', 'baz']; - expect(reducer(undefined, listTags.fulfilled(Mock.of({ tags }), ''))).toEqual({ + expect(reducer(undefined, listTags.fulfilled(fromPartial({ tags }), ''))).toEqual({ tags, filteredTags: tags, loading: false, @@ -114,30 +114,30 @@ describe('tagsListReducer', () => { [['new', 'tag'], ['foo', 'bar', 'baz', 'foo2', 'fo', 'new', 'tag']], ])('appends new short URL\'s tags to the list of tags on CREATE_SHORT_URL', (shortUrlTags, expectedTags) => { const tags = ['foo', 'bar', 'baz', 'foo2', 'fo']; - const payload = Mock.of({ tags: shortUrlTags }); + const payload = fromPartial({ tags: shortUrlTags }); - expect(reducer(state({ tags }), createShortUrl.fulfilled(payload, '', Mock.of()))).toEqual({ + expect(reducer(state({ tags }), createShortUrl.fulfilled(payload, '', fromPartial({})))).toEqual({ tags: expectedTags, }); }); it('increases amounts when visits are created', () => { - const createdVisits = [ - Mock.of({ - shortUrl: Mock.of({ tags: ['foo', 'bar'] }), - visit: Mock.of({ potentialBot: true }), + const createdVisits: CreateVisit[] = [ + fromPartial({ + shortUrl: { tags: ['foo', 'bar'] }, + visit: { potentialBot: true }, }), - Mock.of({ - shortUrl: Mock.of({ tags: ['foo', 'bar'] }), - visit: Mock.all(), + fromPartial({ + shortUrl: { tags: ['foo', 'bar'] }, + visit: {}, }), - Mock.of({ - shortUrl: Mock.of({ tags: ['bar'] }), - visit: Mock.all(), + fromPartial({ + shortUrl: { tags: ['bar'] }, + visit: {}, }), - Mock.of({ - shortUrl: Mock.of({ tags: ['baz'] }), - visit: Mock.of({ potentialBot: true }), + fromPartial({ + shortUrl: { tags: ['baz'] }, + visit: { potentialBot: true }, }), ]; const tagStats = (total: number) => ({ @@ -197,11 +197,11 @@ describe('tagsListReducer', () => { describe('listTags', () => { const dispatch = jest.fn(); - const getState = jest.fn(() => Mock.all()); + const getState = jest.fn(() => fromPartial({})); const listTagsMock = jest.fn(); const assertNoAction = async (tagsList: TagsList) => { - getState.mockReturnValue(Mock.of({ tagsList })); + getState.mockReturnValue(fromPartial({ tagsList })); await listTagsCreator(buildShlinkApiClient, false)()(dispatch, getState, {}); diff --git a/test/utils/DropdownBtnMenu.test.tsx b/test/utils/DropdownBtnMenu.test.tsx index c38d0c7d..22741fde 100644 --- a/test/utils/DropdownBtnMenu.test.tsx +++ b/test/utils/DropdownBtnMenu.test.tsx @@ -1,12 +1,14 @@ import { screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { DropdownBtnMenuProps } from '../../src/utils/DropdownBtnMenu'; import { DropdownBtnMenu } from '../../src/utils/DropdownBtnMenu'; import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { const setUp = (props: Partial = {}) => renderWithEvents( - ({ toggle: jest.fn(), ...props })}>the children, + ({ toggle: jest.fn(), ...props })}> + the children + , ); it('renders expected components', () => { diff --git a/test/utils/dates/DateInput.test.tsx b/test/utils/dates/DateInput.test.tsx index 1e648089..b37e3409 100644 --- a/test/utils/dates/DateInput.test.tsx +++ b/test/utils/dates/DateInput.test.tsx @@ -1,13 +1,13 @@ import { screen, waitFor } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { parseISO } from 'date-fns'; -import { Mock } from 'ts-mockery'; import type { DateInputProps } from '../../../src/utils/dates/DateInput'; import { DateInput } from '../../../src/utils/dates/DateInput'; import { renderWithEvents } from '../../__helpers__/setUpTest'; describe('', () => { const setUp = (props: Partial = {}) => renderWithEvents( - (props)} />, + (props)} />, ); it('shows calendar icon when input is not clearable', () => { diff --git a/test/utils/dates/DateRangeSelector.test.tsx b/test/utils/dates/DateRangeSelector.test.tsx index ed4429fa..08047483 100644 --- a/test/utils/dates/DateRangeSelector.test.tsx +++ b/test/utils/dates/DateRangeSelector.test.tsx @@ -1,5 +1,5 @@ import { screen, waitFor } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { DateRangeSelectorProps } from '../../../src/utils/dates/DateRangeSelector'; import { DateRangeSelector } from '../../../src/utils/dates/DateRangeSelector'; import type { DateInterval } from '../../../src/utils/helpers/dateIntervals'; @@ -10,7 +10,7 @@ describe('', () => { const setUp = async (props: Partial = {}) => { const result = renderWithEvents( (props)} + {...fromPartial(props)} defaultText="Default text" onDatesChange={onDatesChange} />, diff --git a/test/utils/helpers/version.test.ts b/test/utils/helpers/version.test.ts index a0f8ce21..44888723 100644 --- a/test/utils/helpers/version.test.ts +++ b/test/utils/helpers/version.test.ts @@ -1,4 +1,4 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { SemVer, Versions } from '../../../src/utils/helpers/version'; import { versionMatch } from '../../../src/utils/helpers/version'; import type { Empty } from '../../../src/utils/utils'; @@ -6,19 +6,19 @@ import type { Empty } from '../../../src/utils/utils'; describe('version', () => { describe('versionMatch', () => { it.each([ - [undefined, Mock.all(), false], - [null, Mock.all(), false], - ['' as Empty, Mock.all(), false], - [[], Mock.all(), false], - ['2.8.3' as SemVer, Mock.all(), true], - ['2.8.3' as SemVer, Mock.of({ minVersion: '2.0.0' }), true], - ['2.0.0' as SemVer, Mock.of({ minVersion: '2.0.0' }), true], - ['1.8.0' as SemVer, Mock.of({ maxVersion: '1.8.0' }), true], - ['1.7.1' as SemVer, Mock.of({ maxVersion: '1.8.0' }), true], - ['1.7.3' as SemVer, Mock.of({ minVersion: '1.7.0', maxVersion: '1.8.0' }), true], - ['1.8.3' as SemVer, Mock.of({ minVersion: '2.0.0' }), false], - ['1.8.3' as SemVer, Mock.of({ maxVersion: '1.8.0' }), false], - ['1.8.3' as SemVer, Mock.of({ minVersion: '1.7.0', maxVersion: '1.8.0' }), false], + [undefined, fromPartial({}), false], + [null, fromPartial({}), false], + ['' as Empty, fromPartial({}), false], + [[], fromPartial({}), false], + ['2.8.3' as SemVer, fromPartial({}), true], + ['2.8.3' as SemVer, fromPartial({ minVersion: '2.0.0' }), true], + ['2.0.0' as SemVer, fromPartial({ minVersion: '2.0.0' }), true], + ['1.8.0' as SemVer, fromPartial({ maxVersion: '1.8.0' }), true], + ['1.7.1' as SemVer, fromPartial({ maxVersion: '1.8.0' }), true], + ['1.7.3' as SemVer, fromPartial({ minVersion: '1.7.0', maxVersion: '1.8.0' }), true], + ['1.8.3' as SemVer, fromPartial({ minVersion: '2.0.0' }), false], + ['1.8.3' as SemVer, fromPartial({ maxVersion: '1.8.0' }), false], + ['1.8.3' as SemVer, fromPartial({ minVersion: '1.7.0', maxVersion: '1.8.0' }), false], ])('properly matches versions based on what is provided', (version, versionConstraints, expected) => { expect(versionMatch(version, versionConstraints)).toEqual(expected); }); diff --git a/test/utils/services/ColorGenerator.test.ts b/test/utils/services/ColorGenerator.test.ts index c6a04084..50c85b0c 100644 --- a/test/utils/services/ColorGenerator.test.ts +++ b/test/utils/services/ColorGenerator.test.ts @@ -1,11 +1,11 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import { ColorGenerator } from '../../../src/utils/services/ColorGenerator'; import type { LocalStorage } from '../../../src/utils/services/LocalStorage'; import { MAIN_COLOR } from '../../../src/utils/theme'; describe('ColorGenerator', () => { let colorGenerator: ColorGenerator; - const storageMock = Mock.of({ + const storageMock = fromPartial({ set: jest.fn(), get: jest.fn(), }); diff --git a/test/utils/services/LocalStorage.test.ts b/test/utils/services/LocalStorage.test.ts index 4f59cc1d..dd866efa 100644 --- a/test/utils/services/LocalStorage.test.ts +++ b/test/utils/services/LocalStorage.test.ts @@ -1,10 +1,10 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import { LocalStorage } from '../../../src/utils/services/LocalStorage'; describe('LocalStorage', () => { const getItem = jest.fn((key) => (key === 'shlink.foo' ? JSON.stringify({ foo: 'bar' }) : null)); const setItem = jest.fn(); - const localStorageMock = Mock.of({ getItem, setItem }); + const localStorageMock = fromPartial({ getItem, setItem }); let storage: LocalStorage; beforeEach(() => { diff --git a/test/utils/services/__mocks__/ColorGenerator.mock.ts b/test/utils/services/__mocks__/ColorGenerator.mock.ts index 19cde63c..2c68c4d6 100644 --- a/test/utils/services/__mocks__/ColorGenerator.mock.ts +++ b/test/utils/services/__mocks__/ColorGenerator.mock.ts @@ -1,7 +1,7 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ColorGenerator } from '../../../../src/utils/services/ColorGenerator'; -export const colorGeneratorMock = Mock.of({ +export const colorGeneratorMock = fromPartial({ getColorForKey: jest.fn(() => 'red'), setColorForKey: jest.fn(), isColorLightForKey: jest.fn(() => false), diff --git a/test/visits/DomainVisits.test.tsx b/test/visits/DomainVisits.test.tsx index 7cfa5b6d..7323a76f 100644 --- a/test/visits/DomainVisits.test.tsx +++ b/test/visits/DomainVisits.test.tsx @@ -1,13 +1,10 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { formatISO } from 'date-fns'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; -import type { ReportExporter } from '../../src/common/services/ReportExporter'; import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub'; -import type { Settings } from '../../src/settings/reducers/settings'; import { DomainVisits as createDomainVisits } from '../../src/visits/DomainVisits'; import type { DomainVisits } from '../../src/visits/reducers/domainVisits'; -import type { Visit } from '../../src/visits/types'; import { renderWithEvents } from '../__helpers__/setUpTest'; jest.mock('react-router-dom', () => ({ @@ -19,16 +16,16 @@ describe('', () => { const exportVisits = jest.fn(); const getDomainVisits = jest.fn(); const cancelGetDomainVisits = jest.fn(); - const domainVisits = Mock.of({ visits: [Mock.of({ date: formatISO(new Date()) })] }); - const DomainVisits = createDomainVisits(Mock.of({ exportVisits })); + const domainVisits = fromPartial({ visits: [{ date: formatISO(new Date()) }] }); + const DomainVisits = createDomainVisits(fromPartial({ exportVisits })); const setUp = () => renderWithEvents( ({ mercureInfo: {} })} + {...fromPartial({ mercureInfo: {} })} getDomainVisits={getDomainVisits} cancelGetDomainVisits={cancelGetDomainVisits} domainVisits={domainVisits} - settings={Mock.all()} + settings={fromPartial({})} /> , ); diff --git a/test/visits/NonOrphanVisits.test.tsx b/test/visits/NonOrphanVisits.test.tsx index 413ea32f..c60160ff 100644 --- a/test/visits/NonOrphanVisits.test.tsx +++ b/test/visits/NonOrphanVisits.test.tsx @@ -1,29 +1,26 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { formatISO } from 'date-fns'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; -import type { ReportExporter } from '../../src/common/services/ReportExporter'; import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub'; -import type { Settings } from '../../src/settings/reducers/settings'; import { NonOrphanVisits as createNonOrphanVisits } from '../../src/visits/NonOrphanVisits'; import type { VisitsInfo } from '../../src/visits/reducers/types'; -import type { Visit } from '../../src/visits/types'; import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { const exportVisits = jest.fn(); const getNonOrphanVisits = jest.fn(); const cancelGetNonOrphanVisits = jest.fn(); - const nonOrphanVisits = Mock.of({ visits: [Mock.of({ date: formatISO(new Date()) })] }); - const NonOrphanVisits = createNonOrphanVisits(Mock.of({ exportVisits })); + const nonOrphanVisits = fromPartial({ visits: [{ date: formatISO(new Date()) }] }); + const NonOrphanVisits = createNonOrphanVisits(fromPartial({ exportVisits })); const setUp = () => renderWithEvents( ({ mercureInfo: {} })} + {...fromPartial({ mercureInfo: {} })} getNonOrphanVisits={getNonOrphanVisits} cancelGetNonOrphanVisits={cancelGetNonOrphanVisits} nonOrphanVisits={nonOrphanVisits} - settings={Mock.all()} + settings={fromPartial({})} /> , ); diff --git a/test/visits/OrphanVisits.test.tsx b/test/visits/OrphanVisits.test.tsx index a8a76cf7..87f46f72 100644 --- a/test/visits/OrphanVisits.test.tsx +++ b/test/visits/OrphanVisits.test.tsx @@ -1,28 +1,25 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { formatISO } from 'date-fns'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; -import type { ReportExporter } from '../../src/common/services/ReportExporter'; import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub'; -import type { Settings } from '../../src/settings/reducers/settings'; import { OrphanVisits as createOrphanVisits } from '../../src/visits/OrphanVisits'; import type { VisitsInfo } from '../../src/visits/reducers/types'; -import type { Visit } from '../../src/visits/types'; import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { const getOrphanVisits = jest.fn(); const exportVisits = jest.fn(); - const orphanVisits = Mock.of({ visits: [Mock.of({ date: formatISO(new Date()) })] }); - const OrphanVisits = createOrphanVisits(Mock.of({ exportVisits })); + const orphanVisits = fromPartial({ visits: [{ date: formatISO(new Date()) }] }); + const OrphanVisits = createOrphanVisits(fromPartial({ exportVisits })); const setUp = () => renderWithEvents( ({ mercureInfo: {} })} + {...fromPartial({ mercureInfo: {} })} getOrphanVisits={getOrphanVisits} orphanVisits={orphanVisits} cancelGetOrphanVisits={jest.fn()} - settings={Mock.all()} + settings={fromPartial({})} /> , ); diff --git a/test/visits/ShortUrlVisits.test.tsx b/test/visits/ShortUrlVisits.test.tsx index 8b34d951..b36dadbe 100644 --- a/test/visits/ShortUrlVisits.test.tsx +++ b/test/visits/ShortUrlVisits.test.tsx @@ -1,33 +1,29 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { formatISO } from 'date-fns'; import { identity } from 'ramda'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; -import type { ReportExporter } from '../../src/common/services/ReportExporter'; import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub'; -import type { Settings } from '../../src/settings/reducers/settings'; -import type { ShortUrlDetail } from '../../src/short-urls/reducers/shortUrlDetail'; import type { ShortUrlVisits as ShortUrlVisitsState } from '../../src/visits/reducers/shortUrlVisits'; import type { ShortUrlVisitsProps } from '../../src/visits/ShortUrlVisits'; import { ShortUrlVisits as createShortUrlVisits } from '../../src/visits/ShortUrlVisits'; -import type { Visit } from '../../src/visits/types'; import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { const getShortUrlVisitsMock = jest.fn(); const exportVisits = jest.fn(); - const shortUrlVisits = Mock.of({ visits: [Mock.of({ date: formatISO(new Date()) })] }); - const ShortUrlVisits = createShortUrlVisits(Mock.of({ exportVisits })); + const shortUrlVisits = fromPartial({ visits: [{ date: formatISO(new Date()) }] }); + const ShortUrlVisits = createShortUrlVisits(fromPartial({ exportVisits })); const setUp = () => renderWithEvents( ()} - {...Mock.of({ mercureInfo: {} })} + {...fromPartial({})} + {...fromPartial({ mercureInfo: {} })} getShortUrlDetail={identity} getShortUrlVisits={getShortUrlVisitsMock} shortUrlVisits={shortUrlVisits} - shortUrlDetail={Mock.all()} - settings={Mock.all()} + shortUrlDetail={fromPartial({})} + settings={fromPartial({})} cancelGetShortUrlVisits={() => {}} /> , diff --git a/test/visits/ShortUrlVisitsHeader.test.tsx b/test/visits/ShortUrlVisitsHeader.test.tsx index ff4cea75..a9ec7756 100644 --- a/test/visits/ShortUrlVisitsHeader.test.tsx +++ b/test/visits/ShortUrlVisitsHeader.test.tsx @@ -1,6 +1,6 @@ import { screen, waitFor } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { formatDistance, parseISO } from 'date-fns'; -import { Mock } from 'ts-mockery'; import type { ShortUrlDetail } from '../../src/short-urls/reducers/shortUrlDetail'; import type { ShortUrlVisits } from '../../src/visits/reducers/shortUrlVisits'; import { ShortUrlVisitsHeader } from '../../src/visits/ShortUrlVisitsHeader'; @@ -9,12 +9,12 @@ import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { const dateCreated = '2018-01-01T10:00:00+00:00'; const longUrl = 'https://foo.bar/bar/foo'; - const shortUrlVisits = Mock.of({ + const shortUrlVisits = fromPartial({ visits: [{}, {}, {}], }); const goBack = jest.fn(); const setUp = (title?: string | null) => { - const shortUrlDetail = Mock.of({ + const shortUrlDetail = fromPartial({ shortUrl: { shortUrl: 'https://s.test/abc123', longUrl, diff --git a/test/visits/TagVisits.test.tsx b/test/visits/TagVisits.test.tsx index d08ce2c5..492fb577 100644 --- a/test/visits/TagVisits.test.tsx +++ b/test/visits/TagVisits.test.tsx @@ -1,15 +1,11 @@ import { screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { formatISO } from 'date-fns'; import { MemoryRouter } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; -import type { ReportExporter } from '../../src/common/services/ReportExporter'; import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub'; -import type { Settings } from '../../src/settings/reducers/settings'; -import type { ColorGenerator } from '../../src/utils/services/ColorGenerator'; import type { TagVisits as TagVisitsStats } from '../../src/visits/reducers/tagVisits'; import type { TagVisitsProps } from '../../src/visits/TagVisits'; import { TagVisits as createTagVisits } from '../../src/visits/TagVisits'; -import type { Visit } from '../../src/visits/types'; import { renderWithEvents } from '../__helpers__/setUpTest'; jest.mock('react-router-dom', () => ({ @@ -20,19 +16,19 @@ jest.mock('react-router-dom', () => ({ describe('', () => { const getTagVisitsMock = jest.fn(); const exportVisits = jest.fn(); - const tagVisits = Mock.of({ visits: [Mock.of({ date: formatISO(new Date()) })] }); + const tagVisits = fromPartial({ visits: [{ date: formatISO(new Date()) }] }); const TagVisits = createTagVisits( - Mock.of({ isColorLightForKey: () => false, getColorForKey: () => 'red' }), - Mock.of({ exportVisits }), + fromPartial({ isColorLightForKey: () => false, getColorForKey: () => 'red' }), + fromPartial({ exportVisits }), ); const setUp = () => renderWithEvents( ()} - {...Mock.of({ mercureInfo: {} })} + {...fromPartial({})} + {...fromPartial({ mercureInfo: {} })} getTagVisits={getTagVisitsMock} tagVisits={tagVisits} - settings={Mock.all()} + settings={fromPartial({})} cancelGetTagVisits={() => {}} /> , diff --git a/test/visits/TagVisitsHeader.test.tsx b/test/visits/TagVisitsHeader.test.tsx index 1040dc50..1905d121 100644 --- a/test/visits/TagVisitsHeader.test.tsx +++ b/test/visits/TagVisitsHeader.test.tsx @@ -1,16 +1,16 @@ import { render, screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ColorGenerator } from '../../src/utils/services/ColorGenerator'; import type { TagVisits } from '../../src/visits/reducers/tagVisits'; import { TagVisitsHeader } from '../../src/visits/TagVisitsHeader'; describe('', () => { - const tagVisits = Mock.of({ + const tagVisits = fromPartial({ tag: 'foo', visits: [{}, {}, {}, {}], }); const goBack = jest.fn(); - const colorGenerator = Mock.of({ isColorLightForKey: () => false, getColorForKey: () => 'red' }); + const colorGenerator = fromPartial({ isColorLightForKey: () => false, getColorForKey: () => 'red' }); const setUp = () => render(); it('shows expected visits', () => { diff --git a/test/visits/VisitsHeader.test.tsx b/test/visits/VisitsHeader.test.tsx index 66da11c9..64887d20 100644 --- a/test/visits/VisitsHeader.test.tsx +++ b/test/visits/VisitsHeader.test.tsx @@ -1,10 +1,10 @@ import { render, screen } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { Visit } from '../../src/visits/types'; import { VisitsHeader } from '../../src/visits/VisitsHeader'; describe('', () => { - const visits = [Mock.all(), Mock.all(), Mock.all()]; + const visits: Visit[] = [fromPartial({}), fromPartial({}), fromPartial({})]; const title = 'My header title'; const goBack = jest.fn(); const setUp = () => render(); diff --git a/test/visits/VisitsStats.test.tsx b/test/visits/VisitsStats.test.tsx index 8afde4e9..eb8cc1b8 100644 --- a/test/visits/VisitsStats.test.tsx +++ b/test/visits/VisitsStats.test.tsx @@ -1,8 +1,7 @@ import { screen, waitFor } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import { createMemoryHistory } from 'history'; import { Router } from 'react-router-dom'; -import { Mock } from 'ts-mockery'; -import type { Settings } from '../../src/settings/reducers/settings'; import { rangeOf } from '../../src/utils/utils'; import type { VisitsInfo } from '../../src/visits/reducers/types'; import type { Visit } from '../../src/visits/types'; @@ -10,7 +9,7 @@ import { VisitsStats } from '../../src/visits/VisitsStats'; import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { - const visits = rangeOf(3, () => Mock.of({ date: '2020-01-01' })); + const visits = rangeOf(3, () => fromPartial({ date: '2020-01-01' })); const getVisitsMock = jest.fn(); const exportCsv = jest.fn(); const setUp = (visitsInfo: Partial, activeRoute = '/by-time') => { @@ -23,9 +22,9 @@ describe('', () => { (visitsInfo)} + visitsInfo={fromPartial(visitsInfo)} cancelGetVisits={() => {}} - settings={Mock.all()} + settings={fromPartial({})} exportCsv={exportCsv} /> , diff --git a/test/visits/VisitsTable.test.tsx b/test/visits/VisitsTable.test.tsx index e62da685..eb59deda 100644 --- a/test/visits/VisitsTable.test.tsx +++ b/test/visits/VisitsTable.test.tsx @@ -1,5 +1,5 @@ import { screen, waitFor } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import { rangeOf } from '../../src/utils/utils'; import type { NormalizedVisit } from '../../src/visits/types'; import type { VisitsTableProps } from '../../src/visits/VisitsTable'; @@ -7,7 +7,7 @@ import { VisitsTable } from '../../src/visits/VisitsTable'; import { renderWithEvents } from '../__helpers__/setUpTest'; describe('', () => { - const matchMedia = () => Mock.of({ matches: false }); + const matchMedia = () => fromPartial({ matches: false }); const setSelectedVisits = jest.fn(); const setUpFactory = (props: Partial = {}) => renderWithEvents( ', () => { const setUpForOrphanVisits = (isOrphanVisits: boolean) => setUpFactory({ isOrphanVisits }); const setUpWithBots = () => setUpFactory({ visits: [ - Mock.of({ potentialBot: false, date: '2022-05-05' }), - Mock.of({ potentialBot: true, date: '2022-05-05' }), + fromPartial({ potentialBot: false, date: '2022-05-05' }), + fromPartial({ potentialBot: true, date: '2022-05-05' }), ], }); @@ -48,7 +48,7 @@ describe('', () => { [115, 7, 2], // This one will have ellipsis ])('renders the expected amount of pages', (visitsCount, expectedAmountOfPageItems, expectedDisabledItems) => { const { container } = setUp( - rangeOf(visitsCount, () => Mock.of({ browser: '', date: '2022-01-01', referer: '' })), + rangeOf(visitsCount, () => fromPartial({ browser: '', date: '2022-01-01', referer: '' })), ); expect(container.querySelectorAll('.page-item')).toHaveLength(expectedAmountOfPageItems); expect(container.querySelectorAll('.disabled')).toHaveLength(expectedDisabledItems); @@ -58,7 +58,7 @@ describe('', () => { rangeOf(20, (value) => [value]), )('does not render footer when there is only one page to render', (visitsCount) => { const { container } = setUp( - rangeOf(visitsCount, () => Mock.of({ browser: '', date: '2022-01-01', referer: '' })), + rangeOf(visitsCount, () => fromPartial({ browser: '', date: '2022-01-01', referer: '' })), ); expect(container.querySelector('tfoot')).not.toBeInTheDocument(); @@ -66,7 +66,7 @@ describe('', () => { }); it('selected rows are highlighted', async () => { - const visits = rangeOf(10, () => Mock.of({ browser: '', date: '2022-01-01', referer: '' })); + const visits = rangeOf(10, () => fromPartial({ browser: '', date: '2022-01-01', referer: '' })); const { container, user } = setUp(visits, [visits[1], visits[2]]); // Initial situation @@ -86,7 +86,7 @@ describe('', () => { }); it('orders visits when column is clicked', async () => { - const { user } = setUp(rangeOf(9, (index) => Mock.of({ + const { user } = setUp(rangeOf(9, (index) => fromPartial({ browser: '', date: `2022-01-0${10 - index}`, referer: `${index}`, @@ -108,8 +108,8 @@ describe('', () => { it('filters list when writing in search box', async () => { const { user } = setUp([ - ...rangeOf(7, () => Mock.of({ browser: 'aaa', date: '2022-01-01', referer: 'aaa' })), - ...rangeOf(2, () => Mock.of({ browser: 'bbb', date: '2022-01-01', referer: 'bbb' })), + ...rangeOf(7, () => fromPartial({ browser: 'aaa', date: '2022-01-01', referer: 'aaa' })), + ...rangeOf(2, () => fromPartial({ browser: 'bbb', date: '2022-01-01', referer: 'bbb' })), ]); const searchField = screen.getByPlaceholderText('Search...'); const searchText = async (text: string) => { diff --git a/test/visits/charts/DoughnutChartLegend.test.tsx b/test/visits/charts/DoughnutChartLegend.test.tsx index 093bc161..27cac205 100644 --- a/test/visits/charts/DoughnutChartLegend.test.tsx +++ b/test/visits/charts/DoughnutChartLegend.test.tsx @@ -1,14 +1,14 @@ import { render, screen } from '@testing-library/react'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { Chart, ChartDataset } from 'chart.js'; -import { Mock } from 'ts-mockery'; import { DoughnutChartLegend } from '../../../src/visits/charts/DoughnutChartLegend'; describe('', () => { const labels = ['foo', 'bar', 'baz', 'foo2', 'bar2']; const colors = ['green', 'blue', 'yellow']; const defaultColor = 'red'; - const datasets = [Mock.of({ backgroundColor: colors })]; - const chart = Mock.of({ + const datasets = [fromPartial({ backgroundColor: colors })]; + const chart = fromPartial({ config: { data: { labels, datasets }, options: { defaultColor } as any, diff --git a/test/visits/charts/LineChartCard.test.tsx b/test/visits/charts/LineChartCard.test.tsx index 622eece2..64f3af52 100644 --- a/test/visits/charts/LineChartCard.test.tsx +++ b/test/visits/charts/LineChartCard.test.tsx @@ -1,7 +1,7 @@ import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import { fromPartial } from '@total-typescript/shoehorn'; import { formatISO, subDays, subMonths, subYears } from 'date-fns'; -import { Mock } from 'ts-mockery'; import { LineChartCard } from '../../../src/visits/charts/LineChartCard'; import type { NormalizedVisit } from '../../../src/visits/types'; import { setUpCanvas } from '../../__helpers__/setUpTest'; @@ -29,7 +29,7 @@ describe('', () => { visits, expectedActiveIndex, ) => { - const { user } = setUp(visits.map((visit) => Mock.of(visit))); + const { user } = setUp(visits.map((visit) => fromPartial(visit))); await user.click(screen.getByRole('button', { name: /Group by/ })); @@ -46,8 +46,8 @@ describe('', () => { it.each([ [undefined, undefined], [[], []], - [[Mock.of({ date: '2016-04-01' })], []], - [[Mock.of({ date: '2016-04-01' })], [Mock.of({ date: '2016-04-01' })]], + [[fromPartial({ date: '2016-04-01' })], []], + [[fromPartial({ date: '2016-04-01' })], [fromPartial({ date: '2016-04-01' })]], ])('renders chart with expected data', (visits, highlightedVisits) => { const { events } = setUp(visits, highlightedVisits); @@ -57,8 +57,8 @@ describe('', () => { it('includes stats for visits with no dates if selected', async () => { const { getEvents, user } = setUp([ - Mock.of({ date: '2016-04-01' }), - Mock.of({ date: '2016-01-01' }), + fromPartial({ date: '2016-04-01' }), + fromPartial({ date: '2016-01-01' }), ]); const eventsBefore = getEvents(); diff --git a/test/visits/helpers/OpenMapModalBtn.test.tsx b/test/visits/helpers/OpenMapModalBtn.test.tsx index e80cee16..91a69f7b 100644 --- a/test/visits/helpers/OpenMapModalBtn.test.tsx +++ b/test/visits/helpers/OpenMapModalBtn.test.tsx @@ -1,14 +1,14 @@ import { screen, waitFor } from '@testing-library/react'; -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import { OpenMapModalBtn } from '../../../src/visits/helpers/OpenMapModalBtn'; import type { CityStats } from '../../../src/visits/types'; import { renderWithEvents } from '../../__helpers__/setUpTest'; describe('', () => { const title = 'Foo'; - const locations = [ - Mock.of({ cityName: 'foo', count: 30, latLong: [5, 5] }), - Mock.of({ cityName: 'bar', count: 45, latLong: [88, 88] }), + const locations: CityStats[] = [ + fromPartial({ cityName: 'foo', count: 30, latLong: [5, 5] }), + fromPartial({ cityName: 'bar', count: 45, latLong: [88, 88] }), ]; const setUp = (activeCities?: string[]) => renderWithEvents( , diff --git a/test/visits/reducers/domainVisits.test.ts b/test/visits/reducers/domainVisits.test.ts index 0135eb65..c8a5bec4 100644 --- a/test/visits/reducers/domainVisits.test.ts +++ b/test/visits/reducers/domainVisits.test.ts @@ -1,5 +1,5 @@ +import { fromPartial } from '@total-typescript/shoehorn'; import { addDays, formatISO, subDays } from 'date-fns'; -import { Mock } from 'ts-mockery'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkVisits } from '../../../src/api/types'; import type { ShlinkState } from '../../../src/container/types'; @@ -16,25 +16,25 @@ import { getDomainVisits as getDomainVisitsCreator, } from '../../../src/visits/reducers/domainVisits'; import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; -import type { CreateVisit, Visit } from '../../../src/visits/types'; +import type { Visit } from '../../../src/visits/types'; describe('domainVisitsReducer', () => { const now = new Date(); - const visitsMocks = rangeOf(2, () => Mock.all()); + const visitsMocks = rangeOf(2, () => fromPartial({})); const getDomainVisitsCall = jest.fn(); - const buildApiClientMock = () => Mock.of({ getDomainVisits: getDomainVisitsCall }); + const buildApiClientMock = () => fromPartial({ getDomainVisits: getDomainVisitsCall }); const getDomainVisits = getDomainVisitsCreator(buildApiClientMock); const { reducer, cancelGetVisits: cancelGetDomainVisits } = domainVisitsReducerCreator(getDomainVisits); beforeEach(jest.clearAllMocks); describe('reducer', () => { - const buildState = (data: Partial) => Mock.of(data); + const buildState = (data: Partial) => fromPartial(data); it('returns loading on GET_DOMAIN_VISITS_START', () => { const { loading } = reducer( buildState({ loading: false }), - getDomainVisits.pending('', Mock.all()), + getDomainVisits.pending('', fromPartial({})), ); expect(loading).toEqual(true); }); @@ -52,7 +52,7 @@ describe('domainVisitsReducer', () => { it('stops loading and returns error on GET_DOMAIN_VISITS_ERROR', () => { const state = reducer( buildState({ loading: true, error: false }), - getDomainVisits.rejected(null, '', Mock.all()), + getDomainVisits.rejected(null, '', fromPartial({})), ); const { loading, error } = state; @@ -61,10 +61,10 @@ describe('domainVisitsReducer', () => { }); it('return visits on GET_DOMAIN_VISITS', () => { - const actionVisits = [Mock.all(), Mock.all()]; + const actionVisits: Visit[] = [fromPartial({}), fromPartial({})]; const { loading, error, visits } = reducer( buildState({ loading: true, error: false }), - getDomainVisits.fulfilled({ visits: actionVisits }, '', Mock.all()), + getDomainVisits.fulfilled({ visits: actionVisits }, '', fromPartial({})), ); expect(loading).toEqual(false); @@ -75,10 +75,10 @@ describe('domainVisitsReducer', () => { it.each([ [{ domain: 'foo.com' }, 'foo.com', visitsMocks.length + 1], [{ domain: 'bar.com' }, 'foo.com', visitsMocks.length], - [Mock.of({ domain: 'foo.com' }), 'foo.com', visitsMocks.length + 1], - [Mock.of({ domain: DEFAULT_DOMAIN }), null, visitsMocks.length + 1], + [fromPartial({ domain: 'foo.com' }), 'foo.com', visitsMocks.length + 1], + [fromPartial({ domain: DEFAULT_DOMAIN }), null, visitsMocks.length + 1], [ - Mock.of({ + fromPartial({ domain: 'foo.com', query: { endDate: formatIsoDate(subDays(now, 1)) ?? undefined }, }), @@ -86,7 +86,7 @@ describe('domainVisitsReducer', () => { visitsMocks.length, ], [ - Mock.of({ + fromPartial({ domain: 'foo.com', query: { startDate: formatIsoDate(addDays(now, 1)) ?? undefined }, }), @@ -94,7 +94,7 @@ describe('domainVisitsReducer', () => { visitsMocks.length, ], [ - Mock.of({ + fromPartial({ domain: 'foo.com', query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, @@ -105,7 +105,7 @@ describe('domainVisitsReducer', () => { visitsMocks.length, ], [ - Mock.of({ + fromPartial({ domain: 'foo.com', query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, @@ -116,7 +116,7 @@ describe('domainVisitsReducer', () => { visitsMocks.length + 1, ], [ - Mock.of({ + fromPartial({ domain: 'bar.com', query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, @@ -127,9 +127,9 @@ describe('domainVisitsReducer', () => { visitsMocks.length, ], ])('prepends new visits on CREATE_VISIT', (state, shortUrlDomain, expectedVisits) => { - const shortUrl = Mock.of({ domain: shortUrlDomain }); + const shortUrl = fromPartial({ domain: shortUrlDomain }); const { visits } = reducer(buildState({ ...state, visits: visitsMocks }), createNewVisits([ - Mock.of({ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } }), + fromPartial({ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } }), ])); expect(visits).toHaveLength(expectedVisits); @@ -153,7 +153,7 @@ describe('domainVisitsReducer', () => { describe('getDomainVisits', () => { const dispatchMock = jest.fn(); - const getState = () => Mock.of({ + const getState = () => fromPartial({ domainVisits: { cancelLoad: false }, }); const domain = 'foo.com'; @@ -183,12 +183,12 @@ describe('domainVisitsReducer', () => { it.each([ [ - [Mock.of({ date: formatISO(subDays(now, 20)) })], + [fromPartial({ date: formatISO(subDays(now, 20)) })], getDomainVisits.fallbackToInterval('last30Days'), 3, ], [ - [Mock.of({ date: formatISO(subDays(now, 100)) })], + [fromPartial({ date: formatISO(subDays(now, 100)) })], getDomainVisits.fallbackToInterval('last180Days'), 3, ], diff --git a/test/visits/reducers/nonOrphanVisits.test.ts b/test/visits/reducers/nonOrphanVisits.test.ts index 98b1037e..da3da921 100644 --- a/test/visits/reducers/nonOrphanVisits.test.ts +++ b/test/visits/reducers/nonOrphanVisits.test.ts @@ -1,5 +1,5 @@ +import { fromPartial } from '@total-typescript/shoehorn'; import { addDays, formatISO, subDays } from 'date-fns'; -import { Mock } from 'ts-mockery'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkVisits } from '../../../src/api/types'; import type { ShlinkState } from '../../../src/container/types'; @@ -16,16 +16,16 @@ import type { Visit } from '../../../src/visits/types'; describe('nonOrphanVisitsReducer', () => { const now = new Date(); - const visitsMocks = rangeOf(2, () => Mock.all()); + const visitsMocks = rangeOf(2, () => fromPartial({})); const getNonOrphanVisitsCall = jest.fn(); - const buildShlinkApiClient = () => Mock.of({ getNonOrphanVisits: getNonOrphanVisitsCall }); + const buildShlinkApiClient = () => fromPartial({ getNonOrphanVisits: getNonOrphanVisitsCall }); const getNonOrphanVisits = getNonOrphanVisitsCreator(buildShlinkApiClient); const { reducer, cancelGetVisits: cancelGetNonOrphanVisits } = nonOrphanVisitsReducerCreator(getNonOrphanVisits); beforeEach(jest.clearAllMocks); describe('reducer', () => { - const buildState = (data: Partial) => Mock.of(data); + const buildState = (data: Partial) => fromPartial(data); it('returns loading on GET_NON_ORPHAN_VISITS_START', () => { const { loading } = reducer(buildState({ loading: false }), getNonOrphanVisits.pending('', {})); @@ -53,7 +53,7 @@ describe('nonOrphanVisitsReducer', () => { }); it('return visits on GET_NON_ORPHAN_VISITS', () => { - const actionVisits = [Mock.all(), Mock.all()]; + const actionVisits: Visit[] = [fromPartial({}), fromPartial({})]; const { loading, error, visits } = reducer( buildState({ loading: true, error: false }), getNonOrphanVisits.fulfilled({ visits: actionVisits }, '', {}), @@ -67,19 +67,19 @@ describe('nonOrphanVisitsReducer', () => { it.each([ [{}, visitsMocks.length + 2], [ - Mock.of({ + fromPartial({ query: { endDate: formatIsoDate(subDays(now, 1)) ?? undefined }, }), visitsMocks.length, ], [ - Mock.of({ + fromPartial({ query: { startDate: formatIsoDate(addDays(now, 1)) ?? undefined }, }), visitsMocks.length, ], [ - Mock.of({ + fromPartial({ query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, endDate: formatIsoDate(subDays(now, 2)) ?? undefined, @@ -88,7 +88,7 @@ describe('nonOrphanVisitsReducer', () => { visitsMocks.length, ], [ - Mock.of({ + fromPartial({ query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, endDate: formatIsoDate(addDays(now, 3)) ?? undefined, @@ -98,7 +98,7 @@ describe('nonOrphanVisitsReducer', () => { ], ])('prepends new visits on CREATE_VISIT', (state, expectedVisits) => { const prevState = buildState({ ...state, visits: visitsMocks }); - const visit = Mock.of({ date: formatIsoDate(now) ?? undefined }); + const visit = fromPartial({ date: formatIsoDate(now) ?? undefined }); const { visits } = reducer(prevState, createNewVisits([{ visit }, { visit }])); @@ -120,7 +120,7 @@ describe('nonOrphanVisitsReducer', () => { describe('getNonOrphanVisits', () => { const dispatchMock = jest.fn(); - const getState = () => Mock.of({ + const getState = () => fromPartial({ orphanVisits: { cancelLoad: false }, }); @@ -151,12 +151,12 @@ describe('nonOrphanVisitsReducer', () => { it.each([ [ - [Mock.of({ date: formatISO(subDays(now, 5)) })], + [fromPartial({ date: formatISO(subDays(now, 5)) })], getNonOrphanVisits.fallbackToInterval('last7Days'), 3, ], [ - [Mock.of({ date: formatISO(subDays(now, 200)) })], + [fromPartial({ date: formatISO(subDays(now, 200)) })], getNonOrphanVisits.fallbackToInterval('last365Days'), 3, ], diff --git a/test/visits/reducers/orphanVisits.test.ts b/test/visits/reducers/orphanVisits.test.ts index 1071321f..62851f8d 100644 --- a/test/visits/reducers/orphanVisits.test.ts +++ b/test/visits/reducers/orphanVisits.test.ts @@ -1,5 +1,5 @@ +import { fromPartial } from '@total-typescript/shoehorn'; import { addDays, formatISO, subDays } from 'date-fns'; -import { Mock } from 'ts-mockery'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkVisits } from '../../../src/api/types'; import type { ShlinkState } from '../../../src/container/types'; @@ -16,16 +16,16 @@ import type { Visit } from '../../../src/visits/types'; describe('orphanVisitsReducer', () => { const now = new Date(); - const visitsMocks = rangeOf(2, () => Mock.all()); + const visitsMocks = rangeOf(2, () => fromPartial({})); const getOrphanVisitsCall = jest.fn(); - const buildShlinkApiClientMock = () => Mock.of({ getOrphanVisits: getOrphanVisitsCall }); + const buildShlinkApiClientMock = () => fromPartial({ getOrphanVisits: getOrphanVisitsCall }); const getOrphanVisits = getOrphanVisitsCreator(buildShlinkApiClientMock); const { reducer, cancelGetVisits: cancelGetOrphanVisits } = orphanVisitsReducerCreator(getOrphanVisits); beforeEach(jest.clearAllMocks); describe('reducer', () => { - const buildState = (data: Partial) => Mock.of(data); + const buildState = (data: Partial) => fromPartial(data); it('returns loading on GET_ORPHAN_VISITS_START', () => { const { loading } = reducer(buildState({ loading: false }), getOrphanVisits.pending('', {})); @@ -53,7 +53,7 @@ describe('orphanVisitsReducer', () => { }); it('return visits on GET_ORPHAN_VISITS', () => { - const actionVisits = [Mock.all(), Mock.all()]; + const actionVisits: Visit[] = [fromPartial({}), fromPartial({})]; const { loading, error, visits } = reducer( buildState({ loading: true, error: false }), getOrphanVisits.fulfilled({ visits: actionVisits }, '', {}), @@ -67,19 +67,19 @@ describe('orphanVisitsReducer', () => { it.each([ [{}, visitsMocks.length + 2], [ - Mock.of({ + fromPartial({ query: { endDate: formatIsoDate(subDays(now, 1)) ?? undefined }, }), visitsMocks.length, ], [ - Mock.of({ + fromPartial({ query: { startDate: formatIsoDate(addDays(now, 1)) ?? undefined }, }), visitsMocks.length, ], [ - Mock.of({ + fromPartial({ query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, endDate: formatIsoDate(subDays(now, 2)) ?? undefined, @@ -88,7 +88,7 @@ describe('orphanVisitsReducer', () => { visitsMocks.length, ], [ - Mock.of({ + fromPartial({ query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, endDate: formatIsoDate(addDays(now, 3)) ?? undefined, @@ -98,7 +98,7 @@ describe('orphanVisitsReducer', () => { ], ])('prepends new visits on CREATE_VISIT', (state, expectedVisits) => { const prevState = buildState({ ...state, visits: visitsMocks }); - const visit = Mock.of({ date: formatIsoDate(now) ?? undefined }); + const visit = fromPartial({ date: formatIsoDate(now) ?? undefined }); const { visits } = reducer(prevState, createNewVisits([{ visit }, { visit }])); @@ -120,7 +120,7 @@ describe('orphanVisitsReducer', () => { describe('getOrphanVisits', () => { const dispatchMock = jest.fn(); - const getState = () => Mock.of({ + const getState = () => fromPartial({ orphanVisits: { cancelLoad: false }, }); @@ -149,12 +149,12 @@ describe('orphanVisitsReducer', () => { it.each([ [ - [Mock.of({ date: formatISO(subDays(now, 5)) })], + [fromPartial({ date: formatISO(subDays(now, 5)) })], getOrphanVisits.fallbackToInterval('last7Days'), 3, ], [ - [Mock.of({ date: formatISO(subDays(now, 200)) })], + [fromPartial({ date: formatISO(subDays(now, 200)) })], getOrphanVisits.fallbackToInterval('last365Days'), 3, ], diff --git a/test/visits/reducers/shortUrlVisits.test.ts b/test/visits/reducers/shortUrlVisits.test.ts index e5523e0d..a7ce8cb3 100644 --- a/test/visits/reducers/shortUrlVisits.test.ts +++ b/test/visits/reducers/shortUrlVisits.test.ts @@ -1,5 +1,5 @@ +import { fromPartial } from '@total-typescript/shoehorn'; import { addDays, formatISO, subDays } from 'date-fns'; -import { Mock } from 'ts-mockery'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkVisits } from '../../../src/api/types'; import type { ShlinkState } from '../../../src/container/types'; @@ -13,20 +13,20 @@ import { shortUrlVisitsReducerCreator, } from '../../../src/visits/reducers/shortUrlVisits'; import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; -import type { CreateVisit, Visit } from '../../../src/visits/types'; +import type { Visit } from '../../../src/visits/types'; describe('shortUrlVisitsReducer', () => { const now = new Date(); - const visitsMocks = rangeOf(2, () => Mock.all()); + const visitsMocks = rangeOf(2, () => fromPartial({})); const getShortUrlVisitsCall = jest.fn(); - const buildApiClientMock = () => Mock.of({ getShortUrlVisits: getShortUrlVisitsCall }); + const buildApiClientMock = () => fromPartial({ getShortUrlVisits: getShortUrlVisitsCall }); const getShortUrlVisits = getShortUrlVisitsCreator(buildApiClientMock); const { reducer, cancelGetVisits: cancelGetShortUrlVisits } = shortUrlVisitsReducerCreator(getShortUrlVisits); beforeEach(jest.clearAllMocks); describe('reducer', () => { - const buildState = (data: Partial) => Mock.of(data); + const buildState = (data: Partial) => fromPartial(data); it('returns loading on GET_SHORT_URL_VISITS_START', () => { const { loading } = reducer(buildState({ loading: false }), getShortUrlVisits.pending('', { shortCode: '' })); @@ -54,7 +54,7 @@ describe('shortUrlVisitsReducer', () => { }); it('return visits on GET_SHORT_URL_VISITS', () => { - const actionVisits = [Mock.all(), Mock.all()]; + const actionVisits: Visit[] = [fromPartial({}), fromPartial({})]; const { loading, error, visits } = reducer( buildState({ loading: true, error: false }), getShortUrlVisits.fulfilled({ visits: actionVisits }, '', { shortCode: '' }), @@ -69,21 +69,21 @@ describe('shortUrlVisitsReducer', () => { [{ shortCode: 'abc123' }, visitsMocks.length + 1], [{ shortCode: 'def456' }, visitsMocks.length], [ - Mock.of({ + fromPartial({ shortCode: 'abc123', query: { endDate: formatIsoDate(subDays(now, 1)) ?? undefined }, }), visitsMocks.length, ], [ - Mock.of({ + fromPartial({ shortCode: 'abc123', query: { startDate: formatIsoDate(addDays(now, 1)) ?? undefined }, }), visitsMocks.length, ], [ - Mock.of({ + fromPartial({ shortCode: 'abc123', query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, @@ -93,7 +93,7 @@ describe('shortUrlVisitsReducer', () => { visitsMocks.length, ], [ - Mock.of({ + fromPartial({ shortCode: 'abc123', query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, @@ -103,7 +103,7 @@ describe('shortUrlVisitsReducer', () => { visitsMocks.length + 1, ], [ - Mock.of({ + fromPartial({ shortCode: 'def456', query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, @@ -123,7 +123,7 @@ describe('shortUrlVisitsReducer', () => { const { visits } = reducer( prevState, - createNewVisits([Mock.of({ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } })]), + createNewVisits([fromPartial({ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } })]), ); expect(visits).toHaveLength(expectedVisits); @@ -144,8 +144,8 @@ describe('shortUrlVisitsReducer', () => { describe('getShortUrlVisits', () => { const dispatchMock = jest.fn(); - const getState = () => Mock.of({ - shortUrlVisits: Mock.of({ cancelLoad: false }), + const getState = () => fromPartial({ + shortUrlVisits: { cancelLoad: false }, }); it.each([ @@ -197,12 +197,12 @@ describe('shortUrlVisitsReducer', () => { it.each([ [ - [Mock.of({ date: formatISO(subDays(now, 5)) })], + [fromPartial({ date: formatISO(subDays(now, 5)) })], getShortUrlVisits.fallbackToInterval('last7Days'), 3, ], [ - [Mock.of({ date: formatISO(subDays(now, 200)) })], + [fromPartial({ date: formatISO(subDays(now, 200)) })], getShortUrlVisits.fallbackToInterval('last365Days'), 3, ], diff --git a/test/visits/reducers/tagVisits.test.ts b/test/visits/reducers/tagVisits.test.ts index f62d068b..8fd1df0b 100644 --- a/test/visits/reducers/tagVisits.test.ts +++ b/test/visits/reducers/tagVisits.test.ts @@ -1,5 +1,5 @@ +import { fromPartial } from '@total-typescript/shoehorn'; import { addDays, formatISO, subDays } from 'date-fns'; -import { Mock } from 'ts-mockery'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkVisits } from '../../../src/api/types'; import type { ShlinkState } from '../../../src/container/types'; @@ -13,20 +13,20 @@ import { tagVisitsReducerCreator, } from '../../../src/visits/reducers/tagVisits'; import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; -import type { CreateVisit, Visit } from '../../../src/visits/types'; +import type { Visit } from '../../../src/visits/types'; describe('tagVisitsReducer', () => { const now = new Date(); - const visitsMocks = rangeOf(2, () => Mock.all()); + const visitsMocks = rangeOf(2, () => fromPartial({})); const getTagVisitsCall = jest.fn(); - const buildShlinkApiClientMock = () => Mock.of({ getTagVisits: getTagVisitsCall }); + const buildShlinkApiClientMock = () => fromPartial({ getTagVisits: getTagVisitsCall }); const getTagVisits = getTagVisitsCreator(buildShlinkApiClientMock); const { reducer, cancelGetVisits: cancelGetTagVisits } = tagVisitsReducerCreator(getTagVisits); beforeEach(jest.clearAllMocks); describe('reducer', () => { - const buildState = (data: Partial) => Mock.of(data); + const buildState = (data: Partial) => fromPartial(data); it('returns loading on GET_TAG_VISITS_START', () => { const { loading } = reducer(buildState({ loading: false }), getTagVisits.pending('', { tag: '' })); @@ -54,7 +54,7 @@ describe('tagVisitsReducer', () => { }); it('return visits on GET_TAG_VISITS', () => { - const actionVisits = [Mock.all(), Mock.all()]; + const actionVisits: Visit[] = [fromPartial({}), fromPartial({})]; const { loading, error, visits } = reducer( buildState({ loading: true, error: false }), getTagVisits.fulfilled({ visits: actionVisits }, '', { tag: '' }), @@ -69,21 +69,21 @@ describe('tagVisitsReducer', () => { [{ tag: 'foo' }, visitsMocks.length + 1], [{ tag: 'bar' }, visitsMocks.length], [ - Mock.of({ + fromPartial({ tag: 'foo', query: { endDate: formatIsoDate(subDays(now, 1)) ?? undefined }, }), visitsMocks.length, ], [ - Mock.of({ + fromPartial({ tag: 'foo', query: { startDate: formatIsoDate(addDays(now, 1)) ?? undefined }, }), visitsMocks.length, ], [ - Mock.of({ + fromPartial({ tag: 'foo', query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, @@ -93,7 +93,7 @@ describe('tagVisitsReducer', () => { visitsMocks.length, ], [ - Mock.of({ + fromPartial({ tag: 'foo', query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, @@ -103,7 +103,7 @@ describe('tagVisitsReducer', () => { visitsMocks.length + 1, ], [ - Mock.of({ + fromPartial({ tag: 'bar', query: { startDate: formatIsoDate(subDays(now, 5)) ?? undefined, @@ -123,7 +123,7 @@ describe('tagVisitsReducer', () => { const { visits } = reducer( prevState, - createNewVisits([Mock.of({ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } })]), + createNewVisits([fromPartial({ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } })]), ); expect(visits).toHaveLength(expectedVisits); @@ -144,7 +144,7 @@ describe('tagVisitsReducer', () => { describe('getTagVisits', () => { const dispatchMock = jest.fn(); - const getState = () => Mock.of({ + const getState = () => fromPartial({ tagVisits: { cancelLoad: false }, }); const tag = 'foo'; @@ -174,12 +174,12 @@ describe('tagVisitsReducer', () => { it.each([ [ - [Mock.of({ date: formatISO(subDays(now, 20)) })], + [fromPartial({ date: formatISO(subDays(now, 20)) })], getTagVisits.fallbackToInterval('last30Days'), 3, ], [ - [Mock.of({ date: formatISO(subDays(now, 100)) })], + [fromPartial({ date: formatISO(subDays(now, 100)) })], getTagVisits.fallbackToInterval('last180Days'), 3, ], diff --git a/test/visits/reducers/visitCreation.test.ts b/test/visits/reducers/visitCreation.test.ts index 7c9a35ed..30dbf7e7 100644 --- a/test/visits/reducers/visitCreation.test.ts +++ b/test/visits/reducers/visitCreation.test.ts @@ -1,12 +1,12 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShortUrl } from '../../../src/short-urls/data'; import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; import type { Visit } from '../../../src/visits/types'; describe('visitCreationReducer', () => { describe('createNewVisits', () => { - const shortUrl = Mock.all(); - const visit = Mock.all(); + const shortUrl = fromPartial({}); + const visit = fromPartial({}); it('just returns the action with proper type', () => { const { payload } = createNewVisits([{ shortUrl, visit }]); diff --git a/test/visits/reducers/visitsOverview.test.ts b/test/visits/reducers/visitsOverview.test.ts index a46f9561..5b9af30d 100644 --- a/test/visits/reducers/visitsOverview.test.ts +++ b/test/visits/reducers/visitsOverview.test.ts @@ -1,10 +1,9 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import type { ShlinkVisitsOverview } from '../../../src/api/types'; import type { ShlinkState } from '../../../src/container/types'; import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; import type { - ParsedVisitsOverview, PartialVisitsSummary, VisitsOverview, } from '../../../src/visits/reducers/visitsOverview'; @@ -12,18 +11,18 @@ import { loadVisitsOverview as loadVisitsOverviewCreator, visitsOverviewReducerCreator, } from '../../../src/visits/reducers/visitsOverview'; -import type { CreateVisit, OrphanVisit, Visit } from '../../../src/visits/types'; +import type { OrphanVisit } from '../../../src/visits/types'; describe('visitsOverviewReducer', () => { const getVisitsOverview = jest.fn(); - const buildApiClientMock = () => Mock.of({ getVisitsOverview }); + const buildApiClientMock = () => fromPartial({ getVisitsOverview }); const loadVisitsOverview = loadVisitsOverviewCreator(buildApiClientMock); const { reducer } = visitsOverviewReducerCreator(loadVisitsOverview); beforeEach(jest.clearAllMocks); describe('reducer', () => { - const state = (payload: Partial = {}) => Mock.of(payload); + const state = (payload: Partial = {}) => fromPartial(payload); it('returns loading on GET_OVERVIEW_START', () => { const { loading } = reducer( @@ -45,7 +44,7 @@ describe('visitsOverviewReducer', () => { }); it('return visits overview on GET_OVERVIEW', () => { - const action = loadVisitsOverview.fulfilled(Mock.of({ + const action = loadVisitsOverview.fulfilled(fromPartial({ nonOrphanVisits: { total: 100 }, }), 'requestId'); const { loading, error, nonOrphanVisits } = reducer(state({ loading: true, error: false }), action); @@ -65,17 +64,11 @@ describe('visitsOverviewReducer', () => { orphanVisits: { total: providedOrphanVisitsCount }, }), createNewVisits([ - Mock.of({ visit: Mock.all() }), - Mock.of({ visit: Mock.all() }), - Mock.of({ - visit: Mock.of({ visitedUrl: '' }), - }), - Mock.of({ - visit: Mock.of({ visitedUrl: '' }), - }), - Mock.of({ - visit: Mock.of({ visitedUrl: '' }), - }), + fromPartial({ visit: {} }), + fromPartial({ visit: {} }), + fromPartial({ visit: fromPartial({ visitedUrl: '' }) }), + fromPartial({ visit: fromPartial({ visitedUrl: '' }) }), + fromPartial({ visit: fromPartial({ visitedUrl: '' }) }), ]), ); @@ -120,18 +113,12 @@ describe('visitsOverviewReducer', () => { orphanVisits: { total: 200, ...initialOrphanVisits }, }), createNewVisits([ - Mock.of({ visit: Mock.all() }), - Mock.of({ visit: Mock.of({ potentialBot: true }) }), - Mock.of({ visit: Mock.of({ potentialBot: true }) }), - Mock.of({ - visit: Mock.of({ visitedUrl: '' }), - }), - Mock.of({ - visit: Mock.of({ visitedUrl: '' }), - }), - Mock.of({ - visit: Mock.of({ visitedUrl: '', potentialBot: true }), - }), + fromPartial({ visit: {} }), + fromPartial({ visit: { potentialBot: true } }), + fromPartial({ visit: { potentialBot: true } }), + fromPartial({ visit: fromPartial({ visitedUrl: '' }) }), + fromPartial({ visit: fromPartial({ visitedUrl: '' }) }), + fromPartial({ visit: fromPartial({ visitedUrl: '', potentialBot: true }) }), ]), ); @@ -142,7 +129,7 @@ describe('visitsOverviewReducer', () => { describe('loadVisitsOverview', () => { const dispatchMock = jest.fn(); - const getState = () => Mock.of(); + const getState = () => fromPartial({}); it.each([ [ @@ -167,7 +154,7 @@ describe('visitsOverviewReducer', () => { }, ], ])('dispatches start and success when promise is resolved', async (serverResult, dispatchedPayload) => { - const resolvedOverview = Mock.of(serverResult); + const resolvedOverview = fromPartial(serverResult); getVisitsOverview.mockResolvedValue(resolvedOverview); await loadVisitsOverview()(dispatchMock, getState, {}); diff --git a/test/visits/services/VisitsParser.test.ts b/test/visits/services/VisitsParser.test.ts index 25cd5d39..6797601f 100644 --- a/test/visits/services/VisitsParser.test.ts +++ b/test/visits/services/VisitsParser.test.ts @@ -1,10 +1,10 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import { normalizeVisits, processStatsFromVisits } from '../../../src/visits/services/VisitsParser'; import type { OrphanVisit, Visit, VisitsStats } from '../../../src/visits/types'; describe('VisitsParser', () => { const visits: Visit[] = [ - Mock.of({ + fromPartial({ userAgent: 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0', referer: 'https://google.com', potentialBot: false, @@ -15,7 +15,7 @@ describe('VisitsParser', () => { longitude: -543.21, }, }), - Mock.of({ + fromPartial({ userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0', referer: 'https://google.com', potentialBot: false, @@ -26,7 +26,7 @@ describe('VisitsParser', () => { longitude: 6758, }, }), - Mock.of({ + fromPartial({ userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36', potentialBot: false, visitLocation: { @@ -34,7 +34,7 @@ describe('VisitsParser', () => { cityName: '', }, }), - Mock.of({ + fromPartial({ userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36', referer: 'https://m.facebook.com', potentialBot: false, @@ -45,13 +45,13 @@ describe('VisitsParser', () => { longitude: -543.21, }, }), - Mock.of({ + fromPartial({ userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36 OPR/38.0.2220.41', potentialBot: true, }), ]; const orphanVisits: OrphanVisit[] = [ - Mock.of({ + fromPartial({ type: 'base_url', visitedUrl: 'foo', userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0', @@ -64,12 +64,12 @@ describe('VisitsParser', () => { longitude: 6758, }, }), - Mock.of({ + fromPartial({ type: 'regular_404', visitedUrl: 'bar', potentialBot: true, }), - Mock.of({ + fromPartial({ type: 'invalid_short_url', visitedUrl: 'bar', userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36', diff --git a/test/visits/types/helpers.test.ts b/test/visits/types/helpers.test.ts index 75f915c3..9d9aaf94 100644 --- a/test/visits/types/helpers.test.ts +++ b/test/visits/types/helpers.test.ts @@ -1,7 +1,7 @@ -import { Mock } from 'ts-mockery'; +import { fromPartial } from '@total-typescript/shoehorn'; import type { ShlinkVisitsParams } from '../../../src/api/types'; import { formatIsoDate, parseDate } from '../../../src/utils/helpers/date'; -import type { CreateVisit, OrphanVisit, Visit, VisitsParams } from '../../../src/visits/types'; +import type { CreateVisit, OrphanVisit, VisitsParams } from '../../../src/visits/types'; import type { GroupedNewVisits } from '../../../src/visits/types/helpers'; import { groupNewVisitsByType, toApiParams } from '../../../src/visits/types/helpers'; @@ -11,19 +11,15 @@ describe('visitsTypeHelpers', () => { [[], { orphanVisits: [], nonOrphanVisits: [] }], ((): [CreateVisit[], GroupedNewVisits] => { const orphanVisits: CreateVisit[] = [ - Mock.of({ - visit: Mock.of({ visitedUrl: '' }), - }), - Mock.of({ - visit: Mock.of({ visitedUrl: '' }), - }), + fromPartial({ visit: fromPartial({ visitedUrl: '' }) }), + fromPartial({ visit: fromPartial({ visitedUrl: '' }) }), ]; const nonOrphanVisits: CreateVisit[] = [ - Mock.of({ visit: Mock.all() }), - Mock.of({ visit: Mock.all() }), - Mock.of({ visit: Mock.all() }), - Mock.of({ visit: Mock.all() }), - Mock.of({ visit: Mock.all() }), + fromPartial({ visit: {} }), + fromPartial({ visit: {} }), + fromPartial({ visit: {} }), + fromPartial({ visit: {} }), + fromPartial({ visit: {} }), ]; return [ @@ -33,24 +29,18 @@ describe('visitsTypeHelpers', () => { })(), ((): [CreateVisit[], GroupedNewVisits] => { const orphanVisits: CreateVisit[] = [ - Mock.of({ - visit: Mock.of({ visitedUrl: '' }), - }), - Mock.of({ - visit: Mock.of({ visitedUrl: '' }), - }), - Mock.of({ - visit: Mock.of({ visitedUrl: '' }), - }), + fromPartial({ visit: fromPartial({ visitedUrl: '' }) }), + fromPartial({ visit: fromPartial({ visitedUrl: '' }) }), + fromPartial({ visit: fromPartial({ visitedUrl: '' }) }), ]; return [orphanVisits, { orphanVisits, nonOrphanVisits: [] }]; })(), ((): [CreateVisit[], GroupedNewVisits] => { const nonOrphanVisits: CreateVisit[] = [ - Mock.of({ visit: Mock.all() }), - Mock.of({ visit: Mock.all() }), - Mock.of({ visit: Mock.all() }), + fromPartial({ visit: {} }), + fromPartial({ visit: {} }), + fromPartial({ visit: {} }), ]; return [nonOrphanVisits, { orphanVisits: [], nonOrphanVisits }];