diff --git a/package-lock.json b/package-lock.json index a2c287562..863477392 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2723,33 +2723,33 @@ "integrity": "sha512-60CHpq+eqnTxLZQ4PGHYNwUX572hgpMHGPtTWMjdTMsAvlm69lZV/4ly6O3sAYkomo4NggGcomrDpBe34rxUqw==" }, "@pollyjs/adapter": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@pollyjs/adapter/-/adapter-5.0.0.tgz", - "integrity": "sha512-GaJUp9hKKKbRbh1FDbjVfxNGIYs8/1QQI5SR+zjz+OjpjV2btRPFCq1cqO4ORrHA2pTIC8IvEL3lgPSG4v/cPg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/adapter/-/adapter-4.3.0.tgz", + "integrity": "sha512-8/kELw/esDY+Mi6xiYRSX3EHKoVmPeqjRYk7DHFbHhXoMs6ENrPS0ay8Ajl0KHppAnutTk4YLqaI/3VqFCR5iw==", "dev": true, "requires": { - "@pollyjs/utils": "^5.0.0" + "@pollyjs/utils": "^4.3.0" } }, "@pollyjs/adapter-node-http": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@pollyjs/adapter-node-http/-/adapter-node-http-5.0.0.tgz", - "integrity": "sha512-9WjV6UVHWpcDZc1Dt5Slxn191iN55RpCirEAdt+h5wvPgRJmsLuXMI1vT3r9va8Z+a3qCqM458waNfr5us2Wuw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/adapter-node-http/-/adapter-node-http-4.3.0.tgz", + "integrity": "sha512-13LC4/9a6rv8Av0qMM2k+MhVm9Txxai8aLZQabX0XTbnY9e+4yxeIdBC96HAgzmHqWlq30r8Tkgypu3agiKA9w==", "dev": true, "requires": { - "@pollyjs/adapter": "^5.0.0", - "@pollyjs/utils": "^5.0.0", + "@pollyjs/adapter": "^4.3.0", + "@pollyjs/utils": "^4.3.0", "lodash-es": "^4.17.11", "nock": "^12.0.3" } }, "@pollyjs/core": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@pollyjs/core/-/core-5.0.0.tgz", - "integrity": "sha512-f/v5z7aKSWdeBCZQFiQGL4aZmdWAuQWV+U/fMbAIEYjkX8Av0gWPhkFyeMfeFriYMg7Ts1XxPNI7LYroCnjn7w==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/core/-/core-4.3.0.tgz", + "integrity": "sha512-8Fs0Lg19P39oO/GvzWoC/fkckrCSx9rL5DPmU4Ez/Q+WXnDzmWtHI1x/jmD+jv5JLc2ig/ueWugIpE0f9eZbAQ==", "dev": true, "requires": { - "@pollyjs/utils": "^5.0.0", + "@pollyjs/utils": "^4.3.0", "@sindresorhus/fnv1a": "^1.2.0", "blueimp-md5": "^2.10.0", "fast-json-stable-stringify": "^2.0.0", @@ -2760,12 +2760,12 @@ } }, "@pollyjs/node-server": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@pollyjs/node-server/-/node-server-5.0.0.tgz", - "integrity": "sha512-DK1hqsZnIU7TXECNPI6E+ojaSpv62lt3+8eGn3qFbsa61ToTFQLFEMNfcTWA6ZXArrpdzYAdKVTt8BsdEujHkg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/node-server/-/node-server-4.3.0.tgz", + "integrity": "sha512-pGrX889RkJXleW7p1cMKJqEtuasABbosneU9VrHOUYOMlYnObIOTt5y/n3m0NMAh9SyyusgqC7yQ18/PnMCgfg==", "dev": true, "requires": { - "@pollyjs/utils": "^5.0.0", + "@pollyjs/utils": "^4.3.0", "body-parser": "^1.19.0", "cors": "^2.8.5", "express": "^4.17.1", @@ -2789,12 +2789,12 @@ } }, "@pollyjs/persister": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@pollyjs/persister/-/persister-5.0.0.tgz", - "integrity": "sha512-bTJes0c2/y4xrXi1vPypJhup/N/VPC1jY7maOuSv4pOFo6VAvoVJGT2sgMMnPU7qHSRn9Y6v+S7QqGtLOZCyAA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/persister/-/persister-4.3.0.tgz", + "integrity": "sha512-oKTl++rZdT/5tMoeHMsgUAHjnRf/4qLNv7kc7u8ddldjgZ4eDAIWlG6BwFkhDxjhV+ofVlnLxFnRjmK4qrrmqA==", "dev": true, "requires": { - "@pollyjs/utils": "^5.0.0", + "@pollyjs/utils": "^4.3.0", "bowser": "^2.4.0", "fast-json-stable-stringify": "^2.0.0", "lodash-es": "^4.17.11", @@ -2803,19 +2803,19 @@ } }, "@pollyjs/persister-fs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@pollyjs/persister-fs/-/persister-fs-5.0.0.tgz", - "integrity": "sha512-ju75JJ6sSJ/q68rB74wxIlvXCq/riuCqW3pS/Ucd4SFfks/HxXxM3yGTHn0Qq5SrmY9cYbQFfpOz0WCNDIqr+A==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/persister-fs/-/persister-fs-4.3.0.tgz", + "integrity": "sha512-2DUIyl/3mr5F1Orq6bnpW6Witz2I8ulMGsqCFrlh4LaA4DlSg2SwOv88bbjzMCfqGP1CN3U5Zu8o7tZlFxkd8w==", "dev": true, "requires": { - "@pollyjs/node-server": "^5.0.0", - "@pollyjs/persister": "^5.0.0" + "@pollyjs/node-server": "^4.3.0", + "@pollyjs/persister": "^4.3.0" } }, "@pollyjs/utils": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@pollyjs/utils/-/utils-5.0.0.tgz", - "integrity": "sha512-zXoR13NGR1fVoUAcKR9/8AYCXZsMkG5EdvTZbR1nk5hCYJN1AR73HAKXMPsk/2vkLnBr6LWoAr3f9LjwqJOehQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@pollyjs/utils/-/utils-4.3.0.tgz", + "integrity": "sha512-8BYWtP4nK6mAlDgZQ8j2+EZjQH2beoHaHnZDyG7GdspOLeILtXhHLeAxp371YSKN387t7OEBS0nIQSMppHuTQg==", "dev": true, "requires": { "qs": "^6.7.0", @@ -3855,6 +3855,29 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.6.tgz", "integrity": "sha512-FjsYUPzEJdGXjwKqSpE0/9QEh6kzhTAeObA54rn6j3rR4C/mzpI9L0KNfoeASSPMMdxIsoJuCLDWcM/rVjIsSA==" }, + "@types/node-fetch": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", + "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -4113,6 +4136,15 @@ "integrity": "sha512-wx2LQVvKlEkhXp/HoKIZ/aSL+TvfJdKco8i0xJS3aR877mg4qBHzNT6+B5a61vewZHo79EdZavskGnRXEC2H6A==", "dev": true }, + "@types/setup-polly-jest": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@types/setup-polly-jest/-/setup-polly-jest-0.5.0.tgz", + "integrity": "sha512-adGkOa52Z/zU6gZ6oU7iUyS6BOmueFUjPIXrW0INNZPZqB5p68Q6dukWVk2bqVXwDUy3Cd6B/aADSouClwwmew==", + "dev": true, + "requires": { + "@types/pollyjs__core": "*" + } + }, "@types/shallowequal": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/shallowequal/-/shallowequal-1.1.1.tgz", @@ -15148,6 +15180,12 @@ "pretty-format": "^24.9.0" } }, + "jest-localstorage-mock": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/jest-localstorage-mock/-/jest-localstorage-mock-2.4.3.tgz", + "integrity": "sha512-UgifkHKoWVRUoSqO4Z4Z+Hl1NbiYBVDlmkmulFFeRRneGECWAlAdGWJdyz+2NisjOZnnQoxQl0s5dQ7ch62Jxw==", + "dev": true + }, "jest-matcher-utils": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", @@ -20510,9 +20548,9 @@ "dev": true }, "setup-polly-jest": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/setup-polly-jest/-/setup-polly-jest-0.9.1.tgz", - "integrity": "sha512-BbOxCvMnDHAPG9e3Qw3Ol4/ZWLwnDnhODqrfiIpAtF7Azu0O3PI4svZIfsh+/EV9xNj15LMkvchaWsDvF4A3hQ==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/setup-polly-jest/-/setup-polly-jest-0.8.0.tgz", + "integrity": "sha512-dY2vPM5c7mOoF7EbujEqapI6DgbG0x+yN/3cNW3coL7Kmypzu6Zwd978ssIzxAwjf9lXwhw8T9jMBjReDXf63A==", "dev": true }, "sha.js": { diff --git a/package.json b/package.json index a03c260ba..1d0ca3558 100644 --- a/package.json +++ b/package.json @@ -83,9 +83,9 @@ "@babel/preset-react": "^7.7.4", "@babel/preset-typescript": "^7.7.4", "@babel/runtime": "^7.7.6", - "@pollyjs/adapter-node-http": "^5.0.0", - "@pollyjs/core": "^5.0.0", - "@pollyjs/persister-fs": "^5.0.0", + "@pollyjs/adapter-node-http": "^4.3.0", + "@pollyjs/core": "^4.3.0", + "@pollyjs/persister-fs": "^4.3.0", "@storybook/addon-storyshots": "^5.2.8", "@storybook/react": "^5.1.9", "@testing-library/react-hooks": "^1.1.0", @@ -96,6 +96,7 @@ "@types/jest": "^24.0.24", "@types/lodash-es": "^4.17.3", "@types/moment-timezone": "^0.5.12", + "@types/node-fetch": "^2.5.7", "@types/pollyjs__adapter-node-http": "^2.0.0", "@types/pollyjs__persister-fs": "^2.0.0", "@types/react": "^16.9.16", @@ -108,6 +109,7 @@ "@types/react-sortable-tree": "^0.3.6", "@types/react-test-renderer": "^16.8.2", "@types/semver-compare": "^1.0.1", + "@types/setup-polly-jest": "^0.5.0", "@types/storybook__addon-storyshots": "^3.4.9", "@types/storybook__react": "^4.0.2", "@types/url-join": "^4.0.0", @@ -138,6 +140,7 @@ "husky": "^3.0.8", "jest": "^24.8.0", "jest-file": "^1.0.0", + "jest-localstorage-mock": "^2.4.3", "lint-staged": "^9.4.2", "mock-apollo-client": "^0.4.0", "node-fetch": "^2.6.0", @@ -148,7 +151,7 @@ "require-context.macro": "^1.1.1", "rimraf": "^3.0.0", "start-server-and-test": "^1.11.0", - "setup-polly-jest": "^0.9.0", + "setup-polly-jest": "^0.8.0", "testcafe": "^1.3.3", "ts-jest": "^24.2.0", "tsconfig-paths-webpack-plugin": "^3.2.0", @@ -160,6 +163,9 @@ "fsevents": "^1.2.9" }, "jest": { + "setupFiles": [ + "jest-localstorage-mock" + ], "transform": { "^.+\\.(jsx?|tsx?)$": "babel-jest", "^.+\\.(png|svg|jpe?g)$": "jest-file" diff --git a/recordings/User_3768991250/will-be-logged-if-has-valid-token_3465908808/recording.har b/recordings/User_3768991250/will-be-logged-if-has-valid-token_3465908808/recording.har new file mode 100644 index 000000000..af02d5788 --- /dev/null +++ b/recordings/User_3768991250/will-be-logged-if-has-valid-token_3465908808/recording.har @@ -0,0 +1,128 @@ +{ + "log": { + "_recordingName": "User/will be logged if has valid token", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "4.3.0" + }, + "entries": [ + { + "_id": "414f6b24b58b132c92e9a6ea67613a15", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 691, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "accept", + "value": "*/*" + }, + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "691" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "gzip,deflate" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "localhost:8000" + } + ], + "headersSize": 254, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": "[{\"operationName\":\"VerifyToken\",\"variables\":{\"token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTUyMzk4OTcsImV4cCI6MTU5NTI0MDE5NywidG9rZW4iOiJxQ1Jia0dOMnpOT28iLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwidHlwZSI6ImFjY2VzcyIsInVzZXJfaWQiOiJWWE5sY2pveU1RPT0iLCJpc19zdGFmZiI6dHJ1ZX0.l-FnFDVmi5fASo7Uae2Emewu2pKyO2qLz7ZQl1fSzo4\"},\"query\":\"fragment User on User {\\n id\\n email\\n firstName\\n lastName\\n userPermissions {\\n code\\n name\\n __typename\\n }\\n avatar {\\n url\\n __typename\\n }\\n __typename\\n}\\n\\nmutation VerifyToken($token: String!) {\\n tokenVerify(token: $token) {\\n payload\\n user {\\n ...User\\n __typename\\n }\\n __typename\\n }\\n}\\n\"}]" + }, + "queryString": [], + "url": "http://localhost:8000/graphql/" + }, + "response": { + "bodySize": 1619, + "content": { + "mimeType": "application/json", + "size": 1619, + "text": "[{\"data\": {\"tokenVerify\": {\"payload\": {\"iat\": 1595239897, \"exp\": 1595240197, \"token\": \"qCRbkGN2zNOo\", \"email\": \"admin@example.com\", \"type\": \"access\", \"user_id\": \"VXNlcjoyMQ==\", \"is_staff\": true}, \"user\": {\"id\": \"VXNlcjoyMQ==\", \"email\": \"admin@example.com\", \"firstName\": \"\", \"lastName\": \"\", \"userPermissions\": [{\"code\": \"MANAGE_APPS\", \"name\": \"Manage apps\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_CHECKOUTS\", \"name\": \"Manage checkouts\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_DISCOUNTS\", \"name\": \"Manage sales and vouchers.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_GIFT_CARD\", \"name\": \"Manage gift cards.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_MENUS\", \"name\": \"Manage navigation.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_ORDERS\", \"name\": \"Manage orders.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_PAGES\", \"name\": \"Manage pages.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_PLUGINS\", \"name\": \"Manage plugins\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_PRODUCTS\", \"name\": \"Manage products.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_SETTINGS\", \"name\": \"Manage settings.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_SHIPPING\", \"name\": \"Manage shipping.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_STAFF\", \"name\": \"Manage staff.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_TRANSLATIONS\", \"name\": \"Manage translations.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_USERS\", \"name\": \"Manage customers.\", \"__typename\": \"UserPermission\"}], \"avatar\": null, \"__typename\": \"User\"}, \"__typename\": \"VerifyToken\"}}}]" + }, + "cookies": [], + "headers": [ + { + "name": "date", + "value": "Tue, 21 Jul 2020 10:59:19 GMT" + }, + { + "name": "server", + "value": "WSGIServer/0.2 CPython/3.8.1" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-allow-methods", + "value": "POST, OPTIONS" + }, + { + "name": "access-control-allow-headers", + "value": "Origin, Content-Type, Accept, Authorization" + }, + { + "name": "content-length", + "value": "1619" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + } + ], + "headersSize": 316, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2020-07-21T10:59:19.225Z", + "time": 70, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 70 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/recordings/User_3768991250/will-not-be-logged-if-has-expired-token_544348836/recording.har b/recordings/User_3768991250/will-not-be-logged-if-has-expired-token_544348836/recording.har new file mode 100644 index 000000000..775ee5be6 --- /dev/null +++ b/recordings/User_3768991250/will-not-be-logged-if-has-expired-token_544348836/recording.har @@ -0,0 +1,128 @@ +{ + "log": { + "_recordingName": "User/will not be logged if has expired token", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "4.3.0" + }, + "entries": [ + { + "_id": "414f6b24b58b132c92e9a6ea67613a15", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 691, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "accept", + "value": "*/*" + }, + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "691" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "gzip,deflate" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "localhost:8000" + } + ], + "headersSize": 254, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": "[{\"operationName\":\"VerifyToken\",\"variables\":{\"token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTUyMzk4OTcsImV4cCI6MTU5NTI0MDE5NywidG9rZW4iOiJxQ1Jia0dOMnpOT28iLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwidHlwZSI6ImFjY2VzcyIsInVzZXJfaWQiOiJWWE5sY2pveU1RPT0iLCJpc19zdGFmZiI6dHJ1ZX0.l-FnFDVmi5fASo7Uae2Emewu2pKyO2qLz7ZQl1fSzo4\"},\"query\":\"fragment User on User {\\n id\\n email\\n firstName\\n lastName\\n userPermissions {\\n code\\n name\\n __typename\\n }\\n avatar {\\n url\\n __typename\\n }\\n __typename\\n}\\n\\nmutation VerifyToken($token: String!) {\\n tokenVerify(token: $token) {\\n payload\\n user {\\n ...User\\n __typename\\n }\\n __typename\\n }\\n}\\n\"}]" + }, + "queryString": [], + "url": "http://localhost:8000/graphql/" + }, + "response": { + "bodySize": 89, + "content": { + "mimeType": "application/json", + "size": 89, + "text": "[{\"data\": {\"tokenVerify\": {\"payload\": null, \"user\": null, \"__typename\": \"VerifyToken\"}}}]" + }, + "cookies": [], + "headers": [ + { + "name": "date", + "value": "Tue, 21 Jul 2020 13:43:50 GMT" + }, + { + "name": "server", + "value": "WSGIServer/0.2 CPython/3.8.1" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-allow-methods", + "value": "POST, OPTIONS" + }, + { + "name": "access-control-allow-headers", + "value": "Origin, Content-Type, Accept, Authorization" + }, + { + "name": "content-length", + "value": "89" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + } + ], + "headersSize": 314, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2020-07-21T13:43:50.249Z", + "time": 17, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 17 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/recordings/User_3768991250/will-not-be-logged-if-has-invalid-token_1301762210/recording.har b/recordings/User_3768991250/will-not-be-logged-if-has-invalid-token_1301762210/recording.har new file mode 100644 index 000000000..a4d7605fa --- /dev/null +++ b/recordings/User_3768991250/will-not-be-logged-if-has-invalid-token_1301762210/recording.har @@ -0,0 +1,128 @@ +{ + "log": { + "_recordingName": "User/will not be logged if has invalid token", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "4.3.0" + }, + "entries": [ + { + "_id": "f0343691dcc48a40921887f4f58c55b6", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 692, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "accept", + "value": "*/*" + }, + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "692" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "gzip,deflate" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "localhost:8000" + } + ], + "headersSize": 254, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": "[{\"operationName\":\"VerifyToken\",\"variables\":{\"token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTUyMzk4OTcsImV4cCI6MTU5NTI0MDE5NywidG9rZW4iOiJxQ1Jia0dOMnpOT28iLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwidHlwZSI6ImFjY2VzcyIsInVzZXJfaWQiOiJWWE5sY2pveU1RPT0iLCJpc19zdGFmZiI6dHJ1ZX0.l-FnFDVmi5fASo7Uae2Emewu2pKyO2qLz7ZQl1fSzo41\"},\"query\":\"fragment User on User {\\n id\\n email\\n firstName\\n lastName\\n userPermissions {\\n code\\n name\\n __typename\\n }\\n avatar {\\n url\\n __typename\\n }\\n __typename\\n}\\n\\nmutation VerifyToken($token: String!) {\\n tokenVerify(token: $token) {\\n payload\\n user {\\n ...User\\n __typename\\n }\\n __typename\\n }\\n}\\n\"}]" + }, + "queryString": [], + "url": "http://localhost:8000/graphql/" + }, + "response": { + "bodySize": 89, + "content": { + "mimeType": "application/json", + "size": 89, + "text": "[{\"data\": {\"tokenVerify\": {\"payload\": null, \"user\": null, \"__typename\": \"VerifyToken\"}}}]" + }, + "cookies": [], + "headers": [ + { + "name": "date", + "value": "Tue, 21 Jul 2020 11:52:05 GMT" + }, + { + "name": "server", + "value": "WSGIServer/0.2 CPython/3.8.1" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-allow-methods", + "value": "POST, OPTIONS" + }, + { + "name": "access-control-allow-headers", + "value": "Origin, Content-Type, Accept, Authorization" + }, + { + "name": "content-length", + "value": "89" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + } + ], + "headersSize": 314, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2020-07-21T11:52:05.050Z", + "time": 169, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 169 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/recordings/User_3768991250/will-not-be-logged-in-if-doesn-t-have-valid-credentials_3719199657/recording.har b/recordings/User_3768991250/will-not-be-logged-in-if-doesn-t-have-valid-credentials_3719199657/recording.har new file mode 100644 index 000000000..5e16f41bc --- /dev/null +++ b/recordings/User_3768991250/will-not-be-logged-in-if-doesn-t-have-valid-credentials_3719199657/recording.har @@ -0,0 +1,128 @@ +{ + "log": { + "_recordingName": "User/will not be logged in if doesn't have valid credentials", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "4.3.0" + }, + "entries": [ + { + "_id": "8e6a0aa8632ed8e653d2c35119288634", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 1263, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "accept", + "value": "*/*" + }, + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "1263" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "gzip,deflate" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "localhost:8000" + } + ], + "headersSize": 255, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": "[{\"operationName\":\"VerifyToken\",\"variables\":{\"token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTUyNTc4MjQsImV4cCI6MTU5NTI1ODEyNCwidG9rZW4iOiJxQ1Jia0dOMnpOT28iLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwidHlwZSI6ImFjY2VzcyIsInVzZXJfaWQiOiJWWE5sY2pveU1RPT0iLCJpc19zdGFmZiI6dHJ1ZX0.-zPNOLaP5zLOcMW1Xb6G5mf_95J24oBtb07wSRddVOw\"},\"query\":\"fragment User on User {\\n id\\n email\\n firstName\\n lastName\\n userPermissions {\\n code\\n name\\n __typename\\n }\\n avatar {\\n url\\n __typename\\n }\\n __typename\\n}\\n\\nmutation VerifyToken($token: String!) {\\n tokenVerify(token: $token) {\\n payload\\n user {\\n ...User\\n __typename\\n }\\n __typename\\n }\\n}\\n\"},{\"operationName\":\"TokenAuth\",\"variables\":{\"email\":\"admin@example.com\",\"password\":\"admin1\"},\"query\":\"fragment User on User {\\n id\\n email\\n firstName\\n lastName\\n userPermissions {\\n code\\n name\\n __typename\\n }\\n avatar {\\n url\\n __typename\\n }\\n __typename\\n}\\n\\nmutation TokenAuth($email: String!, $password: String!) {\\n tokenCreate(email: $email, password: $password) {\\n token\\n errors: accountErrors {\\n field\\n message\\n __typename\\n }\\n user {\\n ...User\\n __typename\\n }\\n __typename\\n }\\n}\\n\"}]" + }, + "queryString": [], + "url": "http://localhost:8000/graphql/" + }, + "response": { + "bodySize": 1814, + "content": { + "mimeType": "application/json", + "size": 1814, + "text": "[{\"data\": {\"tokenVerify\": {\"payload\": {\"iat\": 1595257824, \"exp\": 1595258124, \"token\": \"qCRbkGN2zNOo\", \"email\": \"admin@example.com\", \"type\": \"access\", \"user_id\": \"VXNlcjoyMQ==\", \"is_staff\": true}, \"user\": {\"id\": \"VXNlcjoyMQ==\", \"email\": \"admin@example.com\", \"firstName\": \"\", \"lastName\": \"\", \"userPermissions\": [{\"code\": \"MANAGE_APPS\", \"name\": \"Manage apps\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_CHECKOUTS\", \"name\": \"Manage checkouts\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_DISCOUNTS\", \"name\": \"Manage sales and vouchers.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_GIFT_CARD\", \"name\": \"Manage gift cards.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_MENUS\", \"name\": \"Manage navigation.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_ORDERS\", \"name\": \"Manage orders.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_PAGES\", \"name\": \"Manage pages.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_PLUGINS\", \"name\": \"Manage plugins\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_PRODUCTS\", \"name\": \"Manage products.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_SETTINGS\", \"name\": \"Manage settings.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_SHIPPING\", \"name\": \"Manage shipping.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_STAFF\", \"name\": \"Manage staff.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_TRANSLATIONS\", \"name\": \"Manage translations.\", \"__typename\": \"UserPermission\"}, {\"code\": \"MANAGE_USERS\", \"name\": \"Manage customers.\", \"__typename\": \"UserPermission\"}], \"avatar\": null, \"__typename\": \"User\"}, \"__typename\": \"VerifyToken\"}}}, {\"data\": {\"tokenCreate\": {\"token\": null, \"errors\": [{\"field\": \"email\", \"message\": \"Please, enter valid credentials\", \"__typename\": \"AccountError\"}], \"user\": null, \"__typename\": \"CreateToken\"}}}]" + }, + "cookies": [], + "headers": [ + { + "name": "date", + "value": "Mon, 20 Jul 2020 15:12:28 GMT" + }, + { + "name": "server", + "value": "WSGIServer/0.2 CPython/3.8.1" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-allow-methods", + "value": "POST, OPTIONS" + }, + { + "name": "access-control-allow-headers", + "value": "Origin, Content-Type, Accept, Authorization" + }, + { + "name": "content-length", + "value": "1814" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + } + ], + "headersSize": 316, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2020-07-20T15:12:28.390Z", + "time": 146, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 146 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/auth/AuthProvider.test.ts b/src/auth/AuthProvider.test.ts index e69de29bb..9b10fd6df 100644 --- a/src/auth/AuthProvider.test.ts +++ b/src/auth/AuthProvider.test.ts @@ -0,0 +1,76 @@ +import setupApi from "@test/api"; +import { act, renderHook } from "@testing-library/react-hooks"; +import ApolloClient from "apollo-client"; + +import { useAuthProvider } from "./AuthProvider"; +import { setAuthToken } from "./utils"; + +const apolloClient = setupApi(); + +function renderAuthProvider(apolloClient: ApolloClient) { + const intl = { + formatMessage: ({ defaultMessage }) => defaultMessage + }; + const notify = jest.fn(); + + const { result } = renderHook(() => + useAuthProvider(intl as any, notify, apolloClient) + ); + + return result; +} + +const credentials = { + email: "admin@example.com", + password: "admin", + token: + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTUyMzk4OTcsImV4cCI6MTU5NTI0MDE5NywidG9rZW4iOiJxQ1Jia0dOMnpOT28iLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwidHlwZSI6ImFjY2VzcyIsInVzZXJfaWQiOiJWWE5sY2pveU1RPT0iLCJpc19zdGFmZiI6dHJ1ZX0.l-FnFDVmi5fASo7Uae2Emewu2pKyO2qLz7ZQl1fSzo4" +}; + +beforeEach(() => { + localStorage.clear(); +}); + +describe("User", () => { + it("will be logged in if has valid credentials", async done => { + const hook = renderAuthProvider(apolloClient); + + await act(() => + hook.current.login(credentials.email, credentials.password) + ); + expect(hook.current.userContext.email).toBe(credentials.email); + + done(); + }); + + it("will not be logged in if doesn't have valid credentials", async done => { + const hook = renderAuthProvider(apolloClient); + + await act(() => + hook.current.login(credentials.email, credentials.password + "1") + ); + expect(hook.current.userContext).toBe(null); + + done(); + }); + + it("will be logged if has valid token", async done => { + setAuthToken(credentials.token, false); + const hook = renderAuthProvider(apolloClient); + + await act(() => hook.current.autologinPromise.current); + expect(hook.current.userContext.email).toBe(credentials.email); + + done(); + }); + + it("will not be logged if has invalid token", async done => { + setAuthToken(credentials.token + "1", false); + const hook = renderAuthProvider(apolloClient); + + await act(() => hook.current.autologinPromise.current); + expect(hook.current.userContext).toBe(undefined); + + done(); + }); +}); diff --git a/src/auth/AuthProvider.tsx b/src/auth/AuthProvider.tsx index 57e695345..a059e4aa6 100644 --- a/src/auth/AuthProvider.tsx +++ b/src/auth/AuthProvider.tsx @@ -9,7 +9,7 @@ import { saveCredentials } from "@saleor/utils/credentialsManagement"; import ApolloClient from "apollo-client"; -import React, { useContext, useEffect, useState } from "react"; +import React, { useContext, useEffect, useRef, useState } from "react"; import { useApolloClient, useMutation } from "react-apollo"; import { IntlShape, useIntl } from "react-intl"; @@ -31,12 +31,13 @@ import { const persistToken = false; -function useAuthProvider( +export function useAuthProvider( intl: IntlShape, notify: IMessageContext, apolloClient: ApolloClient ) { const [userContext, setUserContext] = useState(undefined); + const autologinPromise = useRef>(); const logout = () => { setUserContext(undefined); @@ -111,21 +112,25 @@ function useAuthProvider( useEffect(() => { const token = getAuthToken(); if (!!token && !userContext) { - verifyToken(token); + autologinPromise.current = tokenVerify({ variables: { token } }); } else { - loginWithCredentialsManagementAPI(login); + autologinPromise.current = loginWithCredentialsManagementAPI(login); } }, []); const login = async (email: string, password: string) => { - tokenAuth({ variables: { email, password } }).then(result => { - if (result && !result.data.tokenCreate.errors.length) { - if (!!onLogin) { - onLogin(); - } - saveCredentials(result.data.tokenCreate.user, password); + const result = await tokenAuth({ variables: { email, password } }); + + if (result && !result.data.tokenCreate.errors.length) { + if (!!onLogin) { + onLogin(); } - }); + saveCredentials(result.data.tokenCreate.user, password); + + return result.data.tokenCreate.user; + } + + return null; }; const loginByToken = (token: string, user: User) => { @@ -133,8 +138,6 @@ function useAuthProvider( setAuthToken(token, persistToken); }; - const verifyToken = (token: string) => tokenVerify({ variables: { token } }); - const refreshToken = async () => { const token = getAuthToken(); @@ -144,6 +147,7 @@ function useAuthProvider( }; return { + autologinPromise, login, loginByToken, logout, diff --git a/src/utils/credentialsManagement.ts b/src/utils/credentialsManagement.ts index e87aa9679..7f7998caa 100644 --- a/src/utils/credentialsManagement.ts +++ b/src/utils/credentialsManagement.ts @@ -3,14 +3,16 @@ import { User } from "@saleor/fragments/types/User"; export const isSupported = navigator.credentials && navigator.credentials.preventSilentAccess; -export function login(loginFn: (id: string, password: string) => void) { +export function login(loginFn: (id: string, password: string) => T): T { if (isSupported) { navigator.credentials.get({ password: true }).then(credential => { if (credential instanceof PasswordCredential) { - loginFn(credential.id, credential.password); + return loginFn(credential.id, credential.password); } }); } + + return null; } export function saveCredentials(user: User, password: string) { diff --git a/testUtils/api.ts b/testUtils/api.ts index 6792ef5ea..583f2a6de 100644 --- a/testUtils/api.ts +++ b/testUtils/api.ts @@ -8,23 +8,18 @@ import fetch from "node-fetch"; import path from "path"; import { setupPolly } from "setup-polly-jest"; +Polly.register(NodeHttpAdapter); +Polly.register(FSPersister); + function setupApi() { - Polly.register(NodeHttpAdapter); - Polly.register(FSPersister); setupPolly({ - adapterOptions: { - fetch: { - context: global - } - }, adapters: ["node-http"], persister: "fs", persisterOptions: { fs: { recordingsDir: path.resolve(__dirname, "../recordings") } - }, - recordIfMissing: true + } }); const cache = new InMemoryCache(); const link = new BatchHttpLink({