From 8f63cf775e368eda865b0690b78ca5aceffe9bcd Mon Sep 17 00:00:00 2001 From: Oleg Shur Date: Sat, 20 Feb 2021 00:10:50 +0300 Subject: [PATCH] [CHORE] Specs. Improvements (#202) * [CHORE] Improve types * [CHORE] Example of actions & thunks specs * [CHORE] Example of reducer & selectors specs * [CHORE] Update dependencies --- kafka-ui-react-app/package-lock.json | 498 +++++++++++------- kafka-ui-react-app/package.json | 34 +- .../src/components/Topics/Edit/Edit.tsx | 6 +- .../src/components/Topics/New/New.tsx | 6 +- .../Form/CustomParams/CustomParamSelect.tsx | 9 +- .../Form/CustomParams/CustomParamValue.tsx | 6 +- .../Topics/shared/Form/TimeToRetain.tsx | 4 +- .../Topics/shared/Form/TopicForm.tsx | 3 +- .../redux/actions/__test__/actions.spec.ts | 28 + .../src/redux/actions/__test__/fixtures.ts | 13 + .../src/redux/actions/__test__/thunks.spec.ts | 52 ++ .../src/redux/actions/thunks.ts | 28 +- .../src/redux/interfaces/index.ts | 11 +- .../reducers/clusters/__test__/fixtures.ts | 27 + .../clusters/__test__/reducer.spec.ts | 15 + .../clusters/__test__/selectors.spec.ts | 58 ++ .../src/redux/store/configureStore/dev.ts | 8 +- .../src/redux/store/configureStore/prod.ts | 2 +- 18 files changed, 580 insertions(+), 228 deletions(-) create mode 100644 kafka-ui-react-app/src/redux/actions/__test__/actions.spec.ts create mode 100644 kafka-ui-react-app/src/redux/actions/__test__/fixtures.ts create mode 100644 kafka-ui-react-app/src/redux/actions/__test__/thunks.spec.ts create mode 100644 kafka-ui-react-app/src/redux/reducers/clusters/__test__/fixtures.ts create mode 100644 kafka-ui-react-app/src/redux/reducers/clusters/__test__/reducer.spec.ts create mode 100644 kafka-ui-react-app/src/redux/reducers/clusters/__test__/selectors.spec.ts diff --git a/kafka-ui-react-app/package-lock.json b/kafka-ui-react-app/package-lock.json index 8f40ba383b..d3eaafb6db 100644 --- a/kafka-ui-react-app/package-lock.json +++ b/kafka-ui-react-app/package-lock.json @@ -1573,6 +1573,11 @@ "@hapi/hoek": "^8.3.0" } }, + "@hookform/error-message": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@hookform/error-message/-/error-message-0.0.5.tgz", + "integrity": "sha512-es7eLLFA3SXNYAT8aUjvf7Gok1eMHK+9DMILtJA7ZEwYZlCCCPifhpoZmY+5SOopEtF7e+qxFOjX+MJnI3jOcg==" + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -2718,10 +2723,30 @@ "dev": true }, "@types/node": { - "version": "12.19.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.15.tgz", - "integrity": "sha512-lowukE3GUI+VSYSu6VcBXl14d61Rp5hA1D+61r16qnwC0lYNSqdxcvRh0pswejorHfS+HgwBasM8jLXz0/aOsw==", - "dev": true + "version": "12.20.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.2.tgz", + "integrity": "sha512-djoyN0pvTje9Lpu25ZwZwlLQICPiuv42omiydLhl7om+og1RhQboGmar12KaKls8soTUQ893TuWCrlyt8B1pVg==" + }, + "@types/node-fetch": { + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz", + "integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==", + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } }, "@types/normalize-package-data": { "version": "2.4.0", @@ -2753,9 +2778,9 @@ "dev": true }, "@types/react": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.0.tgz", - "integrity": "sha512-aj/L7RIMsRlWML3YB6KZiXB3fV2t41+5RBGYF8z+tAKU43Px8C3cYUZsDvf1/+Bm4FK21QWBrDutu8ZJ/70qOw==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.2.tgz", + "integrity": "sha512-Xt40xQsrkdvjn1EyWe1Bc0dJLcil/9x2vAuW7ya+PuQip4UYUaXyhzWmAbwRsdMgwOFHpfp7/FFZebDU6Y8VHA==", "dev": true, "requires": { "@types/prop-types": "*", @@ -2774,9 +2799,9 @@ } }, "@types/react-dom": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.0.tgz", - "integrity": "sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g==", + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.1.tgz", + "integrity": "sha512-yIVyopxQb8IDZ7SOHeTovurFq+fXiPICa+GV3gp0Xedsl+MwQlMLKmvrnEjFbQxjliH5YVAEWFh975eVNmKj7Q==", "dev": true, "requires": { "@types/react": "*" @@ -2824,6 +2849,15 @@ "redux": "*" } }, + "@types/redux-mock-store": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/redux-mock-store/-/redux-mock-store-1.0.2.tgz", + "integrity": "sha512-6LBtAQBN34i7SI5X+Qs4zpTEZO1tTDZ6sZ9fzFjYwTl3nLQXaBtwYdoV44CzNnyKu438xJ1lSIYyw0YMvunESw==", + "dev": true, + "requires": { + "redux": "^4.0.5" + } + }, "@types/redux-thunk": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/redux-thunk/-/redux-thunk-2.1.0.tgz", @@ -3101,13 +3135,13 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.1.tgz", - "integrity": "sha512-5JriGbYhtqMS1kRcZTQxndz1lKMwwEXKbwZbkUZNnp6MJX0+OVXnG0kOlBZP4LUAxEyzu3cs+EXd/97MJXsGfw==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.1.tgz", + "integrity": "sha512-yW2epMYZSpNJXZy22Biu+fLdTG8Mn6b22kR3TqblVk50HGNV8Zya15WAXuQCr8tKw4Qf1BL4QtI6kv6PCkLoJw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.14.1", - "@typescript-eslint/scope-manager": "4.14.1", + "@typescript-eslint/experimental-utils": "4.15.1", + "@typescript-eslint/scope-manager": "4.15.1", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "lodash": "^4.17.15", @@ -3116,6 +3150,61 @@ "tsutils": "^3.17.1" }, "dependencies": { + "@typescript-eslint/experimental-utils": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.1.tgz", + "integrity": "sha512-9LQRmOzBRI1iOdJorr4jEnQhadxK4c9R2aEAsm7WE/7dq8wkKD1suaV0S/JucTL8QlYUPU1y2yjqg+aGC0IQBQ==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.15.1", + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/typescript-estree": "4.15.1", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.1.tgz", + "integrity": "sha512-ibQrTFcAm7yG4C1iwpIYK7vDnFg+fKaZVfvyOm3sNsGAerKfwPVFtYft5EbjzByDJ4dj1WD8/34REJfw/9wdVA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/visitor-keys": "4.15.1" + } + }, + "@typescript-eslint/types": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.1.tgz", + "integrity": "sha512-iGsaUyWFyLz0mHfXhX4zO6P7O3sExQpBJ2dgXB0G5g/8PRVfBBsmQIc3r83ranEQTALLR3Vko/fnCIVqmH+mPw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.1.tgz", + "integrity": "sha512-z8MN3CicTEumrWAEB2e2CcoZa3KP9+SMYLIA2aM49XW3cWIaiVSOAGq30ffR5XHxRirqE90fgLw3e6WmNx5uNw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/visitor-keys": "4.15.1", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.1.tgz", + "integrity": "sha512-tYzaTP9plooRJY8eNlpAewTOqtWW/4ff/5wBjNVaJ0S0wC4Gpq/zDVRTJa5bq2v1pCNQ08xxMCndcvR+h7lMww==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.15.1", + "eslint-visitor-keys": "^2.0.0" + } + }, "debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -3148,17 +3237,58 @@ } }, "@typescript-eslint/parser": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.14.1.tgz", - "integrity": "sha512-mL3+gU18g9JPsHZuKMZ8Z0Ss9YP1S5xYZ7n68Z98GnPq02pYNQuRXL85b9GYhl6jpdvUc45Km7hAl71vybjUmw==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.1.tgz", + "integrity": "sha512-V8eXYxNJ9QmXi5ETDguB7O9diAXlIyS+e3xzLoP/oVE4WCAjssxLIa0mqCLsCGXulYJUfT+GV70Jv1vHsdKwtA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.14.1", - "@typescript-eslint/types": "4.14.1", - "@typescript-eslint/typescript-estree": "4.14.1", + "@typescript-eslint/scope-manager": "4.15.1", + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/typescript-estree": "4.15.1", "debug": "^4.1.1" }, "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.1.tgz", + "integrity": "sha512-ibQrTFcAm7yG4C1iwpIYK7vDnFg+fKaZVfvyOm3sNsGAerKfwPVFtYft5EbjzByDJ4dj1WD8/34REJfw/9wdVA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/visitor-keys": "4.15.1" + } + }, + "@typescript-eslint/types": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.1.tgz", + "integrity": "sha512-iGsaUyWFyLz0mHfXhX4zO6P7O3sExQpBJ2dgXB0G5g/8PRVfBBsmQIc3r83ranEQTALLR3Vko/fnCIVqmH+mPw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.1.tgz", + "integrity": "sha512-z8MN3CicTEumrWAEB2e2CcoZa3KP9+SMYLIA2aM49XW3cWIaiVSOAGq30ffR5XHxRirqE90fgLw3e6WmNx5uNw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/visitor-keys": "4.15.1", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.1.tgz", + "integrity": "sha512-tYzaTP9plooRJY8eNlpAewTOqtWW/4ff/5wBjNVaJ0S0wC4Gpq/zDVRTJa5bq2v1pCNQ08xxMCndcvR+h7lMww==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.15.1", + "eslint-visitor-keys": "^2.0.0" + } + }, "debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -4084,8 +4214,7 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "at-least-node": { "version": "1.0.0", @@ -5039,6 +5168,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -5563,7 +5693,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -6321,9 +6450,9 @@ } }, "date-fns": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz", - "integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ==" + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.17.0.tgz", + "integrity": "sha512-ZEhqxUtEZeGgg9eHNSOAJ8O9xqSgiJdrL0lzSSfMF54x6KXWJiOH/xntSJ9YomJPrYH/p08t6gWjGWq1SDJlSA==" }, "debug": { "version": "2.6.9", @@ -6361,6 +6490,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, "requires": { "is-arguments": "^1.0.4", "is-date-object": "^1.0.1", @@ -6396,6 +6526,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -6512,8 +6643,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "delegates": { "version": "1.0.0", @@ -7186,12 +7316,12 @@ } }, "eslint": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.18.0.tgz", - "integrity": "sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.20.0.tgz", + "integrity": "sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", + "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.3.0", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -7203,7 +7333,7 @@ "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", "espree": "^7.3.1", - "esquery": "^1.2.0", + "esquery": "^1.4.0", "esutils": "^2.0.2", "file-entry-cache": "^6.0.0", "functional-red-black-tree": "^1.0.1", @@ -7276,107 +7406,14 @@ } }, "eslint-config-airbnb-typescript": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-12.0.0.tgz", - "integrity": "sha512-TUCVru1Z09eKnVAX5i3XoNzjcCOU3nDQz2/jQGkg1jVYm+25fKClveziSl16celfCq+npU0MBPW/ZnXdGFZ9lw==", + "version": "12.3.1", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-12.3.1.tgz", + "integrity": "sha512-ql/Pe6/hppYuRp4m3iPaHJqkBB7dgeEmGPQ6X0UNmrQOfTF+dXw29/ZjU2kQ6RDoLxaxOA+Xqv07Vbef6oVTWw==", "dev": true, "requires": { - "@typescript-eslint/parser": "4.4.1", - "eslint-config-airbnb": "18.2.0", - "eslint-config-airbnb-base": "14.2.0" - }, - "dependencies": { - "@typescript-eslint/parser": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.4.1.tgz", - "integrity": "sha512-S0fuX5lDku28Au9REYUsV+hdJpW/rNW0gWlc4SXzF/kdrRaAVX9YCxKpziH7djeWT/HFAjLZcnY7NJD8xTeUEg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "4.4.1", - "@typescript-eslint/types": "4.4.1", - "@typescript-eslint/typescript-estree": "4.4.1", - "debug": "^4.1.1" - } - }, - "@typescript-eslint/scope-manager": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.4.1.tgz", - "integrity": "sha512-2oD/ZqD4Gj41UdFeWZxegH3cVEEH/Z6Bhr/XvwTtGv66737XkR4C9IqEkebCuqArqBJQSj4AgNHHiN1okzD/wQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.4.1", - "@typescript-eslint/visitor-keys": "4.4.1" - } - }, - "@typescript-eslint/types": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.4.1.tgz", - "integrity": "sha512-KNDfH2bCyax5db+KKIZT4rfA8rEk5N0EJ8P0T5AJjo5xrV26UAzaiqoJCxeaibqc0c/IvZxp7v2g3difn2Pn3w==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.4.1.tgz", - "integrity": "sha512-wP/V7ScKzgSdtcY1a0pZYBoCxrCstLrgRQ2O9MmCUZDtmgxCO/TCqOTGRVwpP4/2hVfqMz/Vw1ZYrG8cVxvN3g==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.4.1", - "@typescript-eslint/visitor-keys": "4.4.1", - "debug": "^4.1.1", - "globby": "^11.0.1", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.4.1.tgz", - "integrity": "sha512-H2JMWhLaJNeaylSnMSQFEhT/S/FsJbebQALmoJxMPMxLtlVAMy2uJP/Z543n9IizhjRayLSqoInehCeNW9rWcw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.4.1", - "eslint-visitor-keys": "^2.0.0" - } - }, - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "eslint-config-airbnb": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-18.2.0.tgz", - "integrity": "sha512-Fz4JIUKkrhO0du2cg5opdyPKQXOI2MvF8KUvN2710nJMT6jaRUpRE2swrJftAjVGL7T1otLM5ieo5RqS1v9Udg==", - "dev": true, - "requires": { - "eslint-config-airbnb-base": "^14.2.0", - "object.assign": "^4.1.0", - "object.entries": "^1.1.2" - } - }, - "eslint-config-airbnb-base": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz", - "integrity": "sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q==", - "dev": true, - "requires": { - "confusing-browser-globals": "^1.0.9", - "object.assign": "^4.1.0", - "object.entries": "^1.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } + "@typescript-eslint/parser": "^4.4.1", + "eslint-config-airbnb": "^18.2.0", + "eslint-config-airbnb-base": "^14.2.0" } }, "eslint-config-prettier": { @@ -7407,9 +7444,9 @@ } }, "eslint-import-resolver-typescript": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.3.0.tgz", - "integrity": "sha512-MHSXvmj5e0SGOOBhBbt7C+fWj1bJbtSYFAD85Xeg8nvUtuooTod2HQb8bfhE9f5QyyNxEfgzqOYFCvmdDIcCuw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.4.0.tgz", + "integrity": "sha512-useJKURidCcldRLCNKWemr1fFQL1SzB3G4a0li6lFGvlc5xGe1hY343bvG07cbpCzPuM/lK19FIJB3XGFSkplA==", "requires": { "debug": "^4.1.1", "glob": "^7.1.6", @@ -7748,9 +7785,9 @@ } }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -8201,6 +8238,82 @@ "bser": "2.1.1" } }, + "fetch-mock": { + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-9.11.0.tgz", + "integrity": "sha512-PG1XUv+x7iag5p/iNHD4/jdpxL9FtVSqRMUQhPab4hVDt80T1MH5ehzVrL2IdXO9Q2iBggArFvPqjUbHFuI58Q==", + "dev": true, + "requires": { + "@babel/core": "^7.0.0", + "@babel/runtime": "^7.0.0", + "core-js": "^3.0.0", + "debug": "^4.1.1", + "glob-to-regexp": "^0.4.0", + "is-subset": "^0.1.1", + "lodash.isequal": "^4.5.0", + "path-to-regexp": "^2.2.1", + "querystring": "^0.2.0", + "whatwg-url": "^6.5.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "path-to-regexp": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.4.0.tgz", + "integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==", + "dev": true + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "fetch-mock-jest": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/fetch-mock-jest/-/fetch-mock-jest-1.5.1.tgz", + "integrity": "sha512-+utwzP8C+Pax1GSka3nFXILWMY3Er2L+s090FOgqVNrNCPp0fDqgXnAHAJf12PLHi0z4PhcTaZNTz8e7K3fjqQ==", + "dev": true, + "requires": { + "fetch-mock": "^9.11.0" + } + }, "figgy-pudding": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", @@ -8844,6 +8957,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.0.tgz", "integrity": "sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg==", + "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -8931,6 +9045,12 @@ "is-glob": "^4.0.1" } }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, "global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", @@ -9099,7 +9219,8 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true }, "has-unicode": { "version": "2.0.1", @@ -9923,6 +10044,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, "requires": { "call-bind": "^1.0.0" } @@ -10017,7 +10139,8 @@ "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true }, "is-descriptor": { "version": "0.1.6", @@ -10166,6 +10289,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -11857,9 +11981,9 @@ "dev": true }, "lint-staged": { - "version": "10.5.3", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.5.3.tgz", - "integrity": "sha512-TanwFfuqUBLufxCc3RUtFEkFraSPNR3WzWcGF39R3f2J7S9+iF9W0KTVLfSy09lYGmZS5NDCxjNvhGMSJyFCWg==", + "version": "10.5.4", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.5.4.tgz", + "integrity": "sha512-EechC3DdFic/TdOPgj/RB3FicqE6932LTHCUm0Y2fsD9KGlLB+RwJl2q1IYBIvEsKzDOgn0D4gll+YxG5RsrKg==", "dev": true, "requires": { "chalk": "^4.1.0", @@ -11950,9 +12074,9 @@ } }, "listr2": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.3.0.tgz", - "integrity": "sha512-G9IFI/m65icgVlifS0wMQnvn35/8VJGzEb3crpE4NnaegQYQOn/wP7yqi9TTJQ/eoxme4UaPbffBK1XqKP/DOg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.3.1.tgz", + "integrity": "sha512-8Zoxe7s/8nNr4bJ8bdAduHD8uJce+exmMmUWTXlq0WuUdffnH3muisHPHPFtW2vvOfohIsq7FGCaguUxN/h3Iw==", "dev": true, "requires": { "chalk": "^4.1.0", @@ -12063,6 +12187,12 @@ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", "dev": true }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -12446,14 +12576,12 @@ "mime-db": { "version": "1.45.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", - "dev": true + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" }, "mime-types": { "version": "2.1.28", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", - "dev": true, "requires": { "mime-db": "1.45.0" } @@ -12799,6 +12927,11 @@ "dev": true, "optional": true }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, "node-forge": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", @@ -13213,6 +13346,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.4.tgz", "integrity": "sha512-1ZvAZ4wlF7IyPVOcE1Omikt7UpaFlOQq0HlSti+ZvDH3UiD2brwGMwDbyV43jao2bKJ+4+WdPJHSd7kgzKYVqg==", + "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" @@ -13221,7 +13355,8 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, "object-visit": { "version": "1.0.1", @@ -15454,9 +15589,9 @@ } }, "react-datepicker": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-3.4.1.tgz", - "integrity": "sha512-ASyVb7UmVx1vzeITidD7Cr/EXRXhKyjjbSkBndPc1MipYq4rqQ3eMFgvRQzpsXc3JmIMFgICm7nmN6Otc1GE/Q==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-3.5.0.tgz", + "integrity": "sha512-iTRz15aG9lEF7tJVjPcGWvfALb2/RjqHVTvQO7J0DEvGSGZnTJpHlkTrBGBjJ9+i5zM4zcRGoStpjhaezS9p1g==", "requires": { "classnames": "^2.2.6", "date-fns": "^2.0.1", @@ -15670,9 +15805,9 @@ "dev": true }, "react-hook-form": { - "version": "4.10.2", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-4.10.2.tgz", - "integrity": "sha512-Ule/KqHBwUvuubqGC4WDvOARS6VjlULSS+WHspgQ5FhFKR4ytHDc4AMpjVfnv+Wbz2TEbMp9/ZHmuZsUksPCiA==" + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-6.15.1.tgz", + "integrity": "sha512-bL0LQuQ3OlM3JYfbacKtBPLOHhmgYz8Lj6ivMrvu2M6e1wnt4sbGRtPEPYCc/8z3WDbjrMwfAfLX92OsB65pFA==" }, "react-is": { "version": "17.0.1", @@ -15705,13 +15840,12 @@ "integrity": "sha512-7i2L3ef+0ILXpL6P+Hg304eCQswh4jl3ynwR71BSlMU49PE2uk31k8B2GkP6yE9s2D4jTGKnzuSpzWxu4YxfQQ==" }, "react-popper": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.7.tgz", - "integrity": "sha512-nmqYTx7QVjCm3WUZLeuOomna138R1luC4EqkW3hxJUrAe+3eNz3oFCLYdnPwILfn0mX1Ew2c3wctrjlUMYYUww==", + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.9.tgz", + "integrity": "sha512-xKQMQmUMOHAtURz2hj1a0f+M2hyMVWC20hJ09l8UNO2aSCK48kWfdwAuwdCauER0Vo8gV4Qr9G0GobP6KG9AIQ==", "requires": { "@babel/runtime": "^7.1.2", "create-react-context": "^0.3.0", - "deep-equal": "^1.1.1", "popper.js": "^1.14.4", "prop-types": "^15.6.1", "typed-styles": "^0.0.7", @@ -16004,6 +16138,15 @@ "symbol-observable": "^1.2.0" } }, + "redux-mock-store": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/redux-mock-store/-/redux-mock-store-1.5.4.tgz", + "integrity": "sha512-xmcA0O/tjCLXhh9Fuiq6pMrJCwFRaouA8436zcikdIpYWWCjU76CRk+i2bHx8EeiSiMGnB85/lZdU3wIJVXHTA==", + "dev": true, + "requires": { + "lodash.isplainobject": "^4.0.6" + } + }, "redux-thunk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", @@ -16064,6 +16207,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3" @@ -18273,9 +18417,9 @@ }, "dependencies": { "ajv": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz", - "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.1.1.tgz", + "integrity": "sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -18695,9 +18839,9 @@ "dev": true }, "ts-jest": { - "version": "26.4.4", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.4.4.tgz", - "integrity": "sha512-3lFWKbLxJm34QxyVNNCgXX1u4o/RV0myvA2y2Bxm46iGIjKlaY0own9gIckbjZJPn+WaJEnfPPJ20HHGpoq4yg==", + "version": "26.5.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.1.tgz", + "integrity": "sha512-G7Rmo3OJMvlqE79amJX8VJKDiRcd7/r61wh9fnvvG8cAjhA9edklGw/dCxRSQmfZ/z8NDums5srSVgwZos1qfg==", "dev": true, "requires": { "@types/jest": "26.x", @@ -18706,7 +18850,7 @@ "fast-json-stable-stringify": "2.x", "jest-util": "^26.1.0", "json5": "2.x", - "lodash.memoize": "4.x", + "lodash": "4.x", "make-error": "1.x", "mkdirp": "1.x", "semver": "7.x", @@ -18714,9 +18858,9 @@ }, "dependencies": { "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "dev": true, "requires": { "minimist": "^1.2.5" @@ -18854,9 +18998,9 @@ "integrity": "sha512-bna6Yi1pRznoo6Bz1cE6btB/Yy8Xywytyfrzu/wc+NFW3ZF0I+2iCGImhBsoYYCOWuICtRO4yHcnDlzgo1AdNg==" }, "typescript": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", - "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.5.tgz", + "integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==", "dev": true }, "unicode-canonical-property-names-ecmascript": { @@ -20972,9 +21116,9 @@ } }, "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.5.tgz", + "integrity": "sha512-jYRGS3zWy20NtDtK2kBgo/TlAoy5YUuhD9/LZ7z7W4j1Fdw2cqD0xEEclf8fxc8xjD6X5Qr+qQQwCEsP8iRiYg==", "dev": true }, "yn": { diff --git a/kafka-ui-react-app/package.json b/kafka-ui-react-app/package.json index c70429557f..9d813e9bda 100644 --- a/kafka-ui-react-app/package.json +++ b/kafka-ui-react-app/package.json @@ -3,19 +3,22 @@ "version": "0.1.0", "private": true, "dependencies": { + "@hookform/error-message": "0.0.5", + "@types/node-fetch": "^2.5.8", "bulma": "^0.9.2", "bulma-switch": "^2.0.0", "classnames": "^2.2.6", - "date-fns": "^2.16.1", + "date-fns": "^2.17.0", "eslint-import-resolver-node": "^0.3.4", - "eslint-import-resolver-typescript": "^2.3.0", + "eslint-import-resolver-typescript": "^2.4.0", "immer": "^8.0.1", "lodash": "^4.17.20", + "node-fetch": "^2.6.1", "pretty-ms": "^6.0.1", "react": "^17.0.1", - "react-datepicker": "^3.3.0", + "react-datepicker": "^3.5.0", "react-dom": "^17.0.1", - "react-hook-form": "^4.10.2", + "react-hook-form": "^6.15.1", "react-json-tree": "^0.13.0", "react-multi-select-component": "^2.0.14", "react-redux": "^7.2.2", @@ -73,24 +76,25 @@ "@types/enzyme": "^3.10.8", "@types/jest": "^26.0.20", "@types/lodash": "^4.14.165", - "@types/node": "^12.19.8", - "@types/react": "^17.0.0", + "@types/node": "^12.20.2", + "@types/react": "^17.0.2", "@types/react-datepicker": "^3.1.1", - "@types/react-dom": "^17.0.0", + "@types/react-dom": "^17.0.1", "@types/react-redux": "^7.1.11", "@types/react-router-dom": "^5.1.6", "@types/redux": "^3.6.0", + "@types/redux-mock-store": "^1.0.2", "@types/redux-thunk": "^2.1.0", "@types/uuid": "^8.3.0", - "@typescript-eslint/eslint-plugin": "^4.9.0", - "@typescript-eslint/parser": "^4.9.0", + "@typescript-eslint/eslint-plugin": "^4.15.1", + "@typescript-eslint/parser": "^4.15.1", "@wojtekmaj/enzyme-adapter-react-17": "^0.4.1", "dotenv": "^8.2.0", "enzyme": "^3.11.0", "enzyme-to-json": "^3.6.1", - "eslint": "^7.14.0", + "eslint": "^7.20.0", "eslint-config-airbnb": "^18.2.1", - "eslint-config-airbnb-typescript": "^12.0.0", + "eslint-config-airbnb-typescript": "^12.3.1", "eslint-config-prettier": "^6.15.0", "eslint-plugin-import": "^2.22.1", "eslint-plugin-jsx-a11y": "^6.4.1", @@ -98,14 +102,16 @@ "eslint-plugin-react": "^7.21.5", "eslint-plugin-react-hooks": "^2.5.1", "esprint": "^0.6.0", + "fetch-mock-jest": "^1.5.1", "husky": "^4.3.0", - "lint-staged": "^10.5.2", + "lint-staged": "^10.5.4", "node-sass": "^4.14.1", "prettier": "^2.2.1", "react-scripts": "4.0.2", - "ts-jest": "^26.4.4", + "redux-mock-store": "^1.5.4", + "ts-jest": "^26.5.1", "ts-node": "^9.1.1", - "typescript": "~4.1.2" + "typescript": "^4.1.5" }, "engines": { "node": ">=14.15.4" diff --git a/kafka-ui-react-app/src/components/Topics/Edit/Edit.tsx b/kafka-ui-react-app/src/components/Topics/Edit/Edit.tsx index 615a476718..eff06ca29a 100644 --- a/kafka-ui-react-app/src/components/Topics/Edit/Edit.tsx +++ b/kafka-ui-react-app/src/components/Topics/Edit/Edit.tsx @@ -8,7 +8,7 @@ import { CleanupPolicy, } from 'redux/interfaces'; import { TopicConfig } from 'generated-sources'; -import { useForm, FormContext } from 'react-hook-form'; +import { useForm, FormProvider } from 'react-hook-form'; import { camelCase } from 'lodash'; import TopicForm from '../shared/Form/TopicForm'; @@ -127,7 +127,7 @@ const Edit: React.FC = ({
{/* eslint-disable-next-line react/jsx-props-no-spreading */} - + = ({ isEditing onSubmit={methods.handleSubmit(onSubmit)} /> - +
); diff --git a/kafka-ui-react-app/src/components/Topics/New/New.tsx b/kafka-ui-react-app/src/components/Topics/New/New.tsx index bd7b7f2221..cfb634e1f3 100644 --- a/kafka-ui-react-app/src/components/Topics/New/New.tsx +++ b/kafka-ui-react-app/src/components/Topics/New/New.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { ClusterName, TopicName, TopicFormDataRaw } from 'redux/interfaces'; -import { useForm, FormContext } from 'react-hook-form'; +import { useForm, FormProvider } from 'react-hook-form'; import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb'; import { clusterTopicsPath } from 'lib/paths'; @@ -54,12 +54,12 @@ const New: React.FC = ({
{/* eslint-disable react/jsx-props-no-spreading */} - + - +
); diff --git a/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamSelect.tsx b/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamSelect.tsx index c992ffbb8f..143984d6b7 100644 --- a/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamSelect.tsx +++ b/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamSelect.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { useFormContext, ErrorMessage } from 'react-hook-form'; +import { useFormContext } from 'react-hook-form'; import { TopicConfigValue } from 'redux/interfaces'; +import { ErrorMessage } from '@hookform/error-message'; import CustomParamOptions from './CustomParamOptions'; import { INDEX_PREFIX } from './CustomParams'; @@ -19,11 +20,11 @@ const CustomParamSelect: React.FC = ({ existingFields, onNameChange, }) => { - const { register, errors, getValues, triggerValidation } = useFormContext(); + const { register, errors, getValues, trigger } = useFormContext(); const optInputName = `${index}[name]`; const selectedMustBeUniq = (selected: string) => { - const values = getValues({ nest: true }); + const values = getValues(); const customParamsValues: TopicConfigValue = values.customParams; const valid = !Object.entries(customParamsValues).some( @@ -40,7 +41,7 @@ const CustomParamSelect: React.FC = ({ const onChange = (inputName: string) => ( event: React.ChangeEvent ) => { - triggerValidation(inputName); + trigger(inputName); onNameChange(index, event.target.value); }; diff --git a/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamValue.tsx b/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamValue.tsx index f322cec1b8..af98f870bb 100644 --- a/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamValue.tsx +++ b/kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamValue.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { useFormContext, ErrorMessage } from 'react-hook-form'; +import { useFormContext } from 'react-hook-form'; import { TopicConfig } from 'generated-sources'; +import { ErrorMessage } from '@hookform/error-message'; import CUSTOM_PARAMS_OPTIONS from './customParamsOptions'; interface Props { @@ -25,8 +26,7 @@ const CustomParamValue: React.FC = ({ if (selectedParamName && !defaultValue) { setValue( valInputName, - CUSTOM_PARAMS_OPTIONS[selectedParamName].defaultValue, - true + CUSTOM_PARAMS_OPTIONS[selectedParamName].defaultValue ); } }, [selectedParamName, setValue, valInputName]); diff --git a/kafka-ui-react-app/src/components/Topics/shared/Form/TimeToRetain.tsx b/kafka-ui-react-app/src/components/Topics/shared/Form/TimeToRetain.tsx index 5e4494001d..86d89cd3ab 100644 --- a/kafka-ui-react-app/src/components/Topics/shared/Form/TimeToRetain.tsx +++ b/kafka-ui-react-app/src/components/Topics/shared/Form/TimeToRetain.tsx @@ -1,6 +1,8 @@ import React from 'react'; import prettyMilliseconds from 'pretty-ms'; -import { useFormContext, ErrorMessage } from 'react-hook-form'; +import { useFormContext } from 'react-hook-form'; +import { ErrorMessage } from '@hookform/error-message'; + import { MILLISECONDS_IN_WEEK, MILLISECONDS_IN_SECOND } from 'lib/constants'; import TimeToRetainBtns from './TimeToRetainBtns'; diff --git a/kafka-ui-react-app/src/components/Topics/shared/Form/TopicForm.tsx b/kafka-ui-react-app/src/components/Topics/shared/Form/TopicForm.tsx index 994231e760..3b277c5a69 100644 --- a/kafka-ui-react-app/src/components/Topics/shared/Form/TopicForm.tsx +++ b/kafka-ui-react-app/src/components/Topics/shared/Form/TopicForm.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import { useFormContext, ErrorMessage } from 'react-hook-form'; +import { useFormContext } from 'react-hook-form'; import { TOPIC_NAME_VALIDATION_PATTERN, BYTES_IN_GB } from 'lib/constants'; import { CleanupPolicy, TopicName, TopicConfigByName } from 'redux/interfaces'; +import { ErrorMessage } from '@hookform/error-message'; import CustomParamsContainer from './CustomParams/CustomParamsContainer'; import TimeToRetain from './TimeToRetain'; diff --git a/kafka-ui-react-app/src/redux/actions/__test__/actions.spec.ts b/kafka-ui-react-app/src/redux/actions/__test__/actions.spec.ts new file mode 100644 index 0000000000..b463fa1003 --- /dev/null +++ b/kafka-ui-react-app/src/redux/actions/__test__/actions.spec.ts @@ -0,0 +1,28 @@ +import * as actions from '../actions'; + +describe('Actions', () => { + describe('fetchClusterStatsAction', () => { + it('creates an REQUEST action', () => { + expect(actions.fetchClusterStatsAction.request()).toEqual({ + type: 'GET_CLUSTER_STATUS__REQUEST', + }); + }); + + it('creates an SUCCESS action', () => { + expect( + actions.fetchClusterStatsAction.success({ brokerCount: 1 }) + ).toEqual({ + type: 'GET_CLUSTER_STATUS__SUCCESS', + payload: { + brokerCount: 1, + }, + }); + }); + + it('creates an FAILURE action', () => { + expect(actions.fetchClusterStatsAction.failure()).toEqual({ + type: 'GET_CLUSTER_STATUS__FAILURE', + }); + }); + }); +}); diff --git a/kafka-ui-react-app/src/redux/actions/__test__/fixtures.ts b/kafka-ui-react-app/src/redux/actions/__test__/fixtures.ts new file mode 100644 index 0000000000..109bab9b46 --- /dev/null +++ b/kafka-ui-react-app/src/redux/actions/__test__/fixtures.ts @@ -0,0 +1,13 @@ +import { ClusterStats } from 'generated-sources'; + +export const clusterStats: ClusterStats = { + brokerCount: 1, + zooKeeperStatus: 1, + activeControllers: 1, + onlinePartitionCount: 6, + offlinePartitionCount: 0, + inSyncReplicasCount: 6, + outOfSyncReplicasCount: 0, + underReplicatedPartitionCount: 0, + diskUsage: [{ brokerId: 1, segmentSize: 6538, segmentCount: 6 }], +}; diff --git a/kafka-ui-react-app/src/redux/actions/__test__/thunks.spec.ts b/kafka-ui-react-app/src/redux/actions/__test__/thunks.spec.ts new file mode 100644 index 0000000000..134fecaeed --- /dev/null +++ b/kafka-ui-react-app/src/redux/actions/__test__/thunks.spec.ts @@ -0,0 +1,52 @@ +import configureMockStore, { + MockStoreCreator, + MockStoreEnhanced, +} from 'redux-mock-store'; +import thunk, { ThunkDispatch } from 'redux-thunk'; +import fetchMock from 'fetch-mock-jest'; +import { Middleware } from 'redux'; +import { RootState, Action } from 'redux/interfaces'; +import * as actions from 'redux/actions/actions'; +import * as thunks from 'redux/actions/thunks'; +import * as fixtures from './fixtures'; + +const middlewares: Array = [thunk]; +type DispatchExts = ThunkDispatch; + +const mockStoreCreator: MockStoreCreator< + RootState, + DispatchExts +> = configureMockStore(middlewares); + +const store: MockStoreEnhanced = mockStoreCreator(); + +const clusterName = 'local'; + +describe('Thunks', () => { + afterEach(() => { + fetchMock.restore(); + store.clearActions(); + }); + + describe('fetchClusterStats', () => { + it('creates GET_CLUSTER_STATUS__SUCCESS when fetching cluster stats', async () => { + fetchMock.getOnce(`/api/clusters/${clusterName}/stats`, { + body: fixtures.clusterStats, + }); + await store.dispatch(thunks.fetchClusterStats(clusterName)); + expect(store.getActions()).toEqual([ + actions.fetchClusterStatsAction.request(), + actions.fetchClusterStatsAction.success(fixtures.clusterStats), + ]); + }); + + it('creates GET_CLUSTER_STATUS__FAILURE when fetching cluster stats', async () => { + fetchMock.getOnce(`/api/clusters/${clusterName}/stats`, 404); + await store.dispatch(thunks.fetchClusterStats(clusterName)); + expect(store.getActions()).toEqual([ + actions.fetchClusterStatsAction.request(), + actions.fetchClusterStatsAction.failure(), + ]); + }); + }); +}); diff --git a/kafka-ui-react-app/src/redux/actions/thunks.ts b/kafka-ui-react-app/src/redux/actions/thunks.ts index 49f76f130e..1b82578df9 100644 --- a/kafka-ui-react-app/src/redux/actions/thunks.ts +++ b/kafka-ui-react-app/src/redux/actions/thunks.ts @@ -8,7 +8,7 @@ import { } from 'generated-sources'; import { ConsumerGroupID, - PromiseThunk, + PromiseThunkResult, ClusterName, BrokerId, TopicName, @@ -23,7 +23,7 @@ import * as actions from './actions'; const apiClientConf = new Configuration(BASE_PARAMS); const apiClient = new ApiClustersApi(apiClientConf); -export const fetchClustersList = (): PromiseThunk => async (dispatch) => { +export const fetchClustersList = (): PromiseThunkResult => async (dispatch) => { dispatch(actions.fetchClusterListAction.request()); try { const clusters: Cluster[] = await apiClient.getClusters(); @@ -35,7 +35,7 @@ export const fetchClustersList = (): PromiseThunk => async (dispatch) => { export const fetchClusterStats = ( clusterName: ClusterName -): PromiseThunk => async (dispatch) => { +): PromiseThunkResult => async (dispatch) => { dispatch(actions.fetchClusterStatsAction.request()); try { const payload = await apiClient.getClusterStats({ clusterName }); @@ -47,7 +47,7 @@ export const fetchClusterStats = ( export const fetchClusterMetrics = ( clusterName: ClusterName -): PromiseThunk => async (dispatch) => { +): PromiseThunkResult => async (dispatch) => { dispatch(actions.fetchClusterMetricsAction.request()); try { const payload = await apiClient.getClusterMetrics({ clusterName }); @@ -59,7 +59,7 @@ export const fetchClusterMetrics = ( export const fetchBrokers = ( clusterName: ClusterName -): PromiseThunk => async (dispatch) => { +): PromiseThunkResult => async (dispatch) => { dispatch(actions.fetchBrokersAction.request()); try { const payload = await apiClient.getBrokers({ clusterName }); @@ -72,7 +72,7 @@ export const fetchBrokers = ( export const fetchBrokerMetrics = ( clusterName: ClusterName, brokerId: BrokerId -): PromiseThunk => async (dispatch) => { +): PromiseThunkResult => async (dispatch) => { dispatch(actions.fetchBrokerMetricsAction.request()); try { const payload = await apiClient.getBrokersMetrics({ @@ -87,7 +87,7 @@ export const fetchBrokerMetrics = ( export const fetchTopicsList = ( clusterName: ClusterName -): PromiseThunk => async (dispatch) => { +): PromiseThunkResult => async (dispatch) => { dispatch(actions.fetchTopicsListAction.request()); try { const topics = await apiClient.getTopics({ clusterName }); @@ -101,7 +101,7 @@ export const fetchTopicMessages = ( clusterName: ClusterName, topicName: TopicName, queryParams: Partial -): PromiseThunk => async (dispatch) => { +): PromiseThunkResult => async (dispatch) => { dispatch(actions.fetchTopicMessagesAction.request()); try { const messages = await apiClient.getTopicMessages({ @@ -118,7 +118,7 @@ export const fetchTopicMessages = ( export const fetchTopicDetails = ( clusterName: ClusterName, topicName: TopicName -): PromiseThunk => async (dispatch) => { +): PromiseThunkResult => async (dispatch) => { dispatch(actions.fetchTopicDetailsAction.request()); try { const topicDetails = await apiClient.getTopicDetails({ @@ -139,7 +139,7 @@ export const fetchTopicDetails = ( export const fetchTopicConfig = ( clusterName: ClusterName, topicName: TopicName -): PromiseThunk => async (dispatch) => { +): PromiseThunkResult => async (dispatch) => { dispatch(actions.fetchTopicConfigAction.request()); try { const config = await apiClient.getTopicConfigs({ clusterName, topicName }); @@ -188,7 +188,7 @@ const formatTopicFormData = (form: TopicFormDataRaw): TopicFormData => { export const createTopic = ( clusterName: ClusterName, form: TopicFormDataRaw -): PromiseThunk => async (dispatch) => { +): PromiseThunkResult => async (dispatch) => { dispatch(actions.createTopicAction.request()); try { const topic: Topic = await apiClient.createTopic({ @@ -204,7 +204,7 @@ export const createTopic = ( export const updateTopic = ( clusterName: ClusterName, form: TopicFormDataRaw -): PromiseThunk => async (dispatch) => { +): PromiseThunkResult => async (dispatch) => { dispatch(actions.updateTopicAction.request()); try { const topic: Topic = await apiClient.updateTopic({ @@ -220,7 +220,7 @@ export const updateTopic = ( export const fetchConsumerGroupsList = ( clusterName: ClusterName -): PromiseThunk => async (dispatch) => { +): PromiseThunkResult => async (dispatch) => { dispatch(actions.fetchConsumerGroupsAction.request()); try { const consumerGroups = await apiClient.getConsumerGroups({ clusterName }); @@ -233,7 +233,7 @@ export const fetchConsumerGroupsList = ( export const fetchConsumerGroupDetails = ( clusterName: ClusterName, consumerGroupID: ConsumerGroupID -): PromiseThunk => async (dispatch) => { +): PromiseThunkResult => async (dispatch) => { dispatch(actions.fetchConsumerGroupDetailsAction.request()); try { const consumerGroupDetails = await apiClient.getConsumerGroup({ diff --git a/kafka-ui-react-app/src/redux/interfaces/index.ts b/kafka-ui-react-app/src/redux/interfaces/index.ts index 56055cbed7..79fba45d4b 100644 --- a/kafka-ui-react-app/src/redux/interfaces/index.ts +++ b/kafka-ui-react-app/src/redux/interfaces/index.ts @@ -1,4 +1,3 @@ -import { AnyAction } from 'redux'; import { ActionType } from 'typesafe-actions'; import { ThunkAction } from 'redux-thunk'; @@ -26,9 +25,13 @@ export interface RootState { export type Action = ActionType; -export type PromiseThunk = ThunkAction< - Promise, +export type ThunkResult = ThunkAction< + ReturnType, RootState, undefined, - AnyAction + Action +>; + +export type PromiseThunkResult = ThunkResult< + Promise >; diff --git a/kafka-ui-react-app/src/redux/reducers/clusters/__test__/fixtures.ts b/kafka-ui-react-app/src/redux/reducers/clusters/__test__/fixtures.ts new file mode 100644 index 0000000000..62e1bc4920 --- /dev/null +++ b/kafka-ui-react-app/src/redux/reducers/clusters/__test__/fixtures.ts @@ -0,0 +1,27 @@ +import { Cluster, ServerStatus } from 'generated-sources'; + +export const onlineClusterPayload: Cluster = { + name: 'secondLocal', + defaultCluster: true, + status: ServerStatus.Online, + brokerCount: 1, + onlinePartitionCount: 6, + topicCount: 3, + bytesInPerSec: 1.55, + bytesOutPerSec: 9.314, +}; +export const offlineClusterPayload: Cluster = { + name: 'local', + defaultCluster: false, + status: ServerStatus.Offline, + brokerCount: 1, + onlinePartitionCount: 2, + topicCount: 2, + bytesInPerSec: 3.42, + bytesOutPerSec: 4.14, +}; + +export const clustersPayload: Cluster[] = [ + onlineClusterPayload, + offlineClusterPayload, +]; diff --git a/kafka-ui-react-app/src/redux/reducers/clusters/__test__/reducer.spec.ts b/kafka-ui-react-app/src/redux/reducers/clusters/__test__/reducer.spec.ts new file mode 100644 index 0000000000..3c942e0396 --- /dev/null +++ b/kafka-ui-react-app/src/redux/reducers/clusters/__test__/reducer.spec.ts @@ -0,0 +1,15 @@ +import { fetchClusterListAction } from 'redux/actions'; +import reducer from 'redux/reducers/clusters/reducer'; +import { clustersPayload } from './fixtures'; + +describe('Clusters reducer', () => { + it('returns the initial state', () => { + expect(reducer(undefined, fetchClusterListAction.request())).toEqual([]); + }); + + it('reacts on GET_CLUSTERS__SUCCESS and returns payload', () => { + expect( + reducer(undefined, fetchClusterListAction.success(clustersPayload)) + ).toEqual(clustersPayload); + }); +}); diff --git a/kafka-ui-react-app/src/redux/reducers/clusters/__test__/selectors.spec.ts b/kafka-ui-react-app/src/redux/reducers/clusters/__test__/selectors.spec.ts new file mode 100644 index 0000000000..c80eac2d4e --- /dev/null +++ b/kafka-ui-react-app/src/redux/reducers/clusters/__test__/selectors.spec.ts @@ -0,0 +1,58 @@ +import { fetchClusterListAction } from 'redux/actions'; +import configureStore from 'redux/store/configureStore'; +import * as selectors from '../selectors'; +import { + clustersPayload, + offlineClusterPayload, + onlineClusterPayload, +} from './fixtures'; + +const store = configureStore(); + +describe('Clusters selectors', () => { + describe('Initial State', () => { + it('returns fetch status', () => { + expect(selectors.getIsClusterListFetched(store.getState())).toBeFalsy(); + }); + + it('returns cluster list', () => { + expect(selectors.getClusterList(store.getState())).toEqual([]); + }); + + it('returns online cluster list', () => { + expect(selectors.getOnlineClusters(store.getState())).toEqual([]); + }); + + it('returns offline cluster list', () => { + expect(selectors.getOfflineClusters(store.getState())).toEqual([]); + }); + }); + + describe('state', () => { + beforeAll(() => { + store.dispatch(fetchClusterListAction.success(clustersPayload)); + }); + + it('returns fetch status', () => { + expect(selectors.getIsClusterListFetched(store.getState())).toBeTruthy(); + }); + + it('returns cluster list', () => { + expect(selectors.getClusterList(store.getState())).toEqual( + clustersPayload + ); + }); + + it('returns online cluster list', () => { + expect(selectors.getOnlineClusters(store.getState())).toEqual([ + onlineClusterPayload, + ]); + }); + + it('returns offline cluster list', () => { + expect(selectors.getOfflineClusters(store.getState())).toEqual([ + offlineClusterPayload, + ]); + }); + }); +}); diff --git a/kafka-ui-react-app/src/redux/store/configureStore/dev.ts b/kafka-ui-react-app/src/redux/store/configureStore/dev.ts index e90d7c2af0..4a68a5a513 100644 --- a/kafka-ui-react-app/src/redux/store/configureStore/dev.ts +++ b/kafka-ui-react-app/src/redux/store/configureStore/dev.ts @@ -1,6 +1,8 @@ import { createStore, applyMiddleware, compose } from 'redux'; -import thunk from 'redux-thunk'; -import rootReducer from '../../reducers'; +import thunk, { ThunkMiddleware } from 'redux-thunk'; +import { RootState } from 'redux/interfaces'; +import { Action } from 'typesafe-actions'; +import rootReducer from 'redux/reducers'; declare global { interface Window { @@ -9,7 +11,7 @@ declare global { } export default () => { - const middlewares = [thunk]; + const middlewares = [thunk as ThunkMiddleware]; const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; diff --git a/kafka-ui-react-app/src/redux/store/configureStore/prod.ts b/kafka-ui-react-app/src/redux/store/configureStore/prod.ts index a21256ba50..2316c82211 100644 --- a/kafka-ui-react-app/src/redux/store/configureStore/prod.ts +++ b/kafka-ui-react-app/src/redux/store/configureStore/prod.ts @@ -1,6 +1,6 @@ import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; -import rootReducer from '../../reducers'; +import rootReducer from 'redux/reducers'; export default () => { const middlewares = [thunk];