[CHORE] Specs. Improvements (#202)

* [CHORE] Improve types

* [CHORE] Example of actions & thunks specs

* [CHORE] Example of reducer & selectors specs

* [CHORE] Update dependencies
This commit is contained in:
Oleg Shur 2021-02-20 00:10:50 +03:00 committed by GitHub
parent 92c0332cb1
commit 8f63cf775e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 580 additions and 228 deletions

View file

@ -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": {

View file

@ -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"

View file

@ -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<Props> = ({
<div className="box">
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<FormContext {...methods}>
<FormProvider {...methods}>
<TopicForm
topicName={topicName}
config={config}
@ -135,7 +135,7 @@ const Edit: React.FC<Props> = ({
isEditing
onSubmit={methods.handleSubmit(onSubmit)}
/>
</FormContext>
</FormProvider>
</div>
</div>
);

View file

@ -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<Props> = ({
<div className="box">
{/* eslint-disable react/jsx-props-no-spreading */}
<FormContext {...methods}>
<FormProvider {...methods}>
<TopicForm
isSubmitting={isSubmitting}
onSubmit={methods.handleSubmit(onSubmit)}
/>
</FormContext>
</FormProvider>
</div>
</div>
);

View file

@ -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<Props> = ({
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<Props> = ({
const onChange = (inputName: string) => (
event: React.ChangeEvent<HTMLSelectElement>
) => {
triggerValidation(inputName);
trigger(inputName);
onNameChange(index, event.target.value);
};

View file

@ -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<Props> = ({
if (selectedParamName && !defaultValue) {
setValue(
valInputName,
CUSTOM_PARAMS_OPTIONS[selectedParamName].defaultValue,
true
CUSTOM_PARAMS_OPTIONS[selectedParamName].defaultValue
);
}
}, [selectedParamName, setValue, valInputName]);

View file

@ -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';

View file

@ -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';

View file

@ -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',
});
});
});
});

View file

@ -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 }],
};

View file

@ -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<Middleware> = [thunk];
type DispatchExts = ThunkDispatch<RootState, undefined, Action>;
const mockStoreCreator: MockStoreCreator<
RootState,
DispatchExts
> = configureMockStore<RootState, DispatchExts>(middlewares);
const store: MockStoreEnhanced<RootState, DispatchExts> = 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(),
]);
});
});
});

View file

@ -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<void> => 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<void> => async (dispatch) => {
export const fetchClusterStats = (
clusterName: ClusterName
): PromiseThunk<void> => 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<void> => 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<void> => 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<void> => 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<void> => 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<TopicMessageQueryParams>
): PromiseThunk<void> => 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<void> => 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<void> => 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<void> => 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<void> => 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<void> => 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<void> => async (dispatch) => {
): PromiseThunkResult => async (dispatch) => {
dispatch(actions.fetchConsumerGroupDetailsAction.request());
try {
const consumerGroupDetails = await apiClient.getConsumerGroup({

View file

@ -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<typeof actions>;
export type PromiseThunk<T> = ThunkAction<
Promise<T>,
export type ThunkResult<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
undefined,
AnyAction
Action
>;
export type PromiseThunkResult<ReturnType = void> = ThunkResult<
Promise<ReturnType>
>;

View file

@ -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,
];

View file

@ -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);
});
});

View file

@ -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,
]);
});
});
});

View file

@ -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<RootState, Action>];
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

View file

@ -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];