From 478e81ff39a1f78f2844c5affcc4dc339db486f9 Mon Sep 17 00:00:00 2001 From: Alan Greene Date: Thu, 6 Oct 2022 17:05:13 +0100 Subject: [PATCH] Replace fetch-mock with msw in tests Use mock service worker (`msw`) in tests to more closely replicate a real environment, mocking at the network level instead of at the API level. This gives greater visibility into tests that are not properly isolated, avoids issues specific to `fetch` or whichever request library is being used, and could also be used for e2e testing in future. Another motivation behind the change is the fact that `fetch-mock` hasn't been updated in about 2 years and uses a number of deprecated packages including `querystring` which will no longer receive updates for vulnerabilities. --- config_frontend/msw.js | 21 + config_frontend/setupTests.js | 21 +- package-lock.json | 1483 +++++++++++++++++++++--- package.json | 2 +- src/api/clusterInterceptors.test.js | 17 +- src/api/clusterTasks.test.js | 20 +- src/api/clusterTriggerBindings.test.js | 16 +- src/api/comms.test.js | 24 +- src/api/eventListeners.test.js | 14 +- src/api/extensions.test.js | 9 +- src/api/index.test.js | 124 +- src/api/pipelineResources.test.js | 25 +- src/api/pipelineRuns.test.js | 104 +- src/api/pipelines.test.js | 17 +- src/api/runs.test.js | 55 +- src/api/serviceAccounts.test.js | 9 +- src/api/taskRuns.test.js | 210 ++-- src/api/tasks.test.js | 17 +- src/api/triggerBindings.test.js | 14 +- src/api/triggerTemplates.test.js | 14 +- src/api/triggers.test.js | 12 +- src/containers/App/App.test.js | 2 +- src/utils/index.test.js | 7 +- 23 files changed, 1771 insertions(+), 466 deletions(-) create mode 100644 config_frontend/msw.js diff --git a/config_frontend/msw.js b/config_frontend/msw.js new file mode 100644 index 000000000..26d515dee --- /dev/null +++ b/config_frontend/msw.js @@ -0,0 +1,21 @@ +/* +Copyright 2022 The Tekton Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; + +const server = setupServer( + rest.get(/\/properties$/, (req, res, ctx) => res(ctx.json({}))) +); + +export { rest, server }; diff --git a/config_frontend/setupTests.js b/config_frontend/setupTests.js index cd587fe60..1c5395e92 100644 --- a/config_frontend/setupTests.js +++ b/config_frontend/setupTests.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -13,23 +13,32 @@ limitations under the License. import { setLogger } from 'react-query'; import fetch from 'node-fetch'; -import fetchMock from 'fetch-mock'; import { TextDecoder, TextEncoder } from 'util'; +import { server } from './msw'; + setLogger({ log: console.log, // eslint-disable-line no-console warn: console.warn, // eslint-disable-line no-console error: () => {} }); +// Establish API mocking before all tests. +beforeAll(() => + server.listen({ + onUnhandledRequest: 'bypass' // reduce noise in test logs, TODO: revisit + }) +); +// Reset any request handlers that we may add during the tests, +// so they don't affect other tests. +afterEach(() => server.resetHandlers()); +// Clean up after the tests are finished. +afterAll(() => server.close()); + if (!global.fetch) { global.fetch = fetch; } -fetchMock.catch(); -fetchMock.config.overwriteRoutes = true; -fetchMock.config.warnOnFallback = false; - window.HTMLElement.prototype.scrollIntoView = function scrollIntoViewTestStub() {}; window.TextDecoder = TextDecoder; diff --git a/package-lock.json b/package-lock.json index 6ac2492ea..880b38cc1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -72,7 +72,6 @@ "eslint-plugin-react": "^7.31.8", "eslint-plugin-react-hooks": "^4.6.0", "eslint-webpack-plugin": "^3.2.0", - "fetch-mock": "^9.10.7", "file-loader": "^6.0.0", "glob": "^8.0.3", "history": "^5.3.0", @@ -82,6 +81,7 @@ "lodash.difference": "^4.5.0", "lodash.omit": "^4.5.0", "mini-css-extract-plugin": "^2.6.1", + "msw": "^0.47.4", "node-fetch": "^3.2.10", "prettier": "^2.7.1", "sass": "^1.55.0", @@ -4199,6 +4199,38 @@ "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==", "dev": true }, + "node_modules/@mswjs/cookies": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-0.2.2.tgz", + "integrity": "sha512-mlN83YSrcFgk7Dm1Mys40DLssI1KdJji2CMKN8eOlBqsTADYzj2+jWzsANsUTFbxDMWPD5e9bfA1RGqBpS3O1g==", + "dev": true, + "dependencies": { + "@types/set-cookie-parser": "^2.4.0", + "set-cookie-parser": "^2.4.6" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.17.5.tgz", + "integrity": "sha512-/uZkyPUZMRExZs+DZQVnc+uoDwLfs1gFNvcRY5S3Gu78U+uhovaSEUW3tuyld1e7Oke5Qphfseb8v66V+H1zWQ==", + "dev": true, + "dependencies": { + "@open-draft/until": "^1.0.3", + "@types/debug": "^4.1.7", + "@xmldom/xmldom": "^0.7.5", + "debug": "^4.3.3", + "headers-polyfill": "^3.1.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.2.4", + "web-encoding": "^1.1.5" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -4281,6 +4313,12 @@ "node": ">=10" } }, + "node_modules/@open-draft/until": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz", + "integrity": "sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==", + "dev": true + }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.7.tgz", @@ -11205,6 +11243,21 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "node_modules/@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/eslint": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", @@ -11336,6 +11389,12 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/js-levenshtein": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz", + "integrity": "sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g==", + "dev": true + }, "node_modules/@types/jsdom": { "version": "20.0.0", "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.0.tgz", @@ -11404,6 +11463,12 @@ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", "dev": true }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, "node_modules/@types/node": { "version": "14.18.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.9.tgz", @@ -11527,6 +11592,15 @@ "@types/node": "*" } }, + "node_modules/@types/set-cookie-parser": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.2.tgz", + "integrity": "sha512-fBZgytwhYAUkj/jC/FAV4RQ5EerRup1YQsXQCh8rZfiHkc4UahC192oH0smGwsXol3cL3A5oETuAHeQHmhXM4w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", @@ -11996,6 +12070,15 @@ } } }, + "node_modules/@xmldom/xmldom": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", + "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -12008,6 +12091,13 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "node_modules/@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "dev": true, + "optional": true + }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -12726,6 +12816,18 @@ "url": "https://tidelift.com/funding/github/npm/autoprefixer" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -13548,6 +13650,41 @@ "file-uri-to-path": "1.0.0" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/blob-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", @@ -14357,6 +14494,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "node_modules/check-more-types": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", @@ -14599,6 +14742,18 @@ "node": ">=8" } }, + "node_modules/cli-spinners": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-table3": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz", @@ -14630,6 +14785,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -14641,6 +14805,15 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -16245,6 +16418,15 @@ "node": ">= 10" } }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -18223,6 +18405,32 @@ "node": ">=0.10.0" } }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -18457,45 +18665,6 @@ "node": "^12.20 || >= 14.13" } }, - "node_modules/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, - "dependencies": { - "@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" - }, - "engines": { - "node": ">=4.0.0" - }, - "funding": { - "type": "charity", - "url": "https://www.justgiving.com/refugee-support-europe" - }, - "peerDependencies": { - "node-fetch": "*" - }, - "peerDependenciesMeta": { - "node-fetch": { - "optional": true - } - } - }, - "node_modules/fetch-mock/node_modules/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 - }, "node_modules/fetch-retry": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.3.tgz", @@ -18833,6 +19002,15 @@ } } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -19540,6 +19718,15 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "node_modules/graphql": { + "version": "16.6.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", + "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -19891,6 +20078,12 @@ "he": "bin/he" } }, + "node_modules/headers-polyfill": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.1.1.tgz", + "integrity": "sha512-ifvvIC+VDeLTEkJDwxECSI7k9rJF7sJavCh/UfhGsgJ+LXMbGILRf+NXhc4znuf+JA5X2/leQdOXk6Lq6Y2/wQ==", + "dev": true + }, "node_modules/highlight.js": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", @@ -20518,6 +20711,84 @@ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", "dev": true }, + "node_modules/inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/internal-slot": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", @@ -20886,6 +21157,21 @@ "node": ">=6" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -20924,6 +21210,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", @@ -20945,6 +21240,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-node-process": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.0.1.tgz", + "integrity": "sha512-5IcdXuf++TTNt3oGl9EBdkvndXA8gmc4bz/Y+mdEpWh3Mcn/+kOw6hI7LD5CocqJWMzeb0I0ClndRVNdEPuJXQ==", + "dev": true + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -21086,12 +21387,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", - "dev": true - }, "node_modules/is-symbol": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", @@ -21107,6 +21402,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", + "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -24404,6 +24718,15 @@ "node": ">=8" } }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/js-sdsl": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", @@ -24976,12 +25299,6 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "dev": true }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, "node_modules/lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -25941,6 +26258,224 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/msw": { + "version": "0.47.4", + "resolved": "https://registry.npmjs.org/msw/-/msw-0.47.4.tgz", + "integrity": "sha512-Psftt8Yfl0+l+qqg9OlmKEsxF8S/vtda0CmlR6y8wTaWrMMzuCDa55n2hEGC0ZRDwuV6FFWc/4CjoDsBpATKBw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@mswjs/cookies": "^0.2.2", + "@mswjs/interceptors": "^0.17.5", + "@open-draft/until": "^1.0.3", + "@types/cookie": "^0.4.1", + "@types/js-levenshtein": "^1.1.1", + "chalk": "4.1.1", + "chokidar": "^3.4.2", + "cookie": "^0.4.2", + "graphql": "^15.0.0 || ^16.0.0", + "headers-polyfill": "^3.1.0", + "inquirer": "^8.2.0", + "is-node-process": "^1.0.1", + "js-levenshtein": "^1.1.6", + "node-fetch": "^2.6.7", + "outvariant": "^1.3.0", + "path-to-regexp": "^6.2.0", + "statuses": "^2.0.0", + "strict-event-emitter": "^0.2.6", + "type-fest": "^2.19.0", + "yargs": "^17.3.1" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.2.x <= 4.8.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/msw/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/msw/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/msw/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/msw/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true + }, + "node_modules/msw/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/msw/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/msw/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/msw/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/msw/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/msw/node_modules/yargs": { + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", + "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/msw/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", @@ -25954,6 +26489,12 @@ "multicast-dns": "cli.js" } }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, "node_modules/nan": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", @@ -26657,6 +27198,81 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -26673,12 +27289,27 @@ "node": ">=0.10.0" } }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ospath": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", "dev": true }, + "node_modules/outvariant": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.3.0.tgz", + "integrity": "sha512-yeWM9k6UPfG/nzxdaPlJkB2p08hCg4xP6Lx99F+vP8YF7xyZVfTmJjrrNalkmzudD4WFvNLVudQikqUmF8zhVQ==", + "dev": true + }, "node_modules/p-all": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-all/-/p-all-2.1.0.tgz", @@ -28987,6 +29618,15 @@ "node": "6.* || >= 7.*" } }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -29645,6 +30285,12 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "node_modules/set-cookie-parser": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz", + "integrity": "sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==", + "dev": true + }, "node_modules/set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -30528,6 +31174,15 @@ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, + "node_modules/strict-event-emitter": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.6.tgz", + "integrity": "sha512-qDZOqEBoNtKLPb/qAutkXUt7hs3zXgYA1xX4pVa+gZHCZZVLr2r81AzHsK5YrQQhRNphMtkOUyAyOr9e1IxJTw==", + "dev": true, + "dependencies": { + "events": "^3.3.0" + } + }, "node_modules/strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", @@ -31285,15 +31940,6 @@ "node": ">= 4.0.0" } }, - "node_modules/tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", @@ -32505,6 +33151,41 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "dev": true, + "dependencies": { + "util": "^0.12.3" + }, + "optionalDependencies": { + "@zxing/text-encoding": "0.9.0" + } + }, + "node_modules/web-encoding/node_modules/util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, "node_modules/web-namespaces": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", @@ -32967,23 +33648,6 @@ "node": ">=12" } }, - "node_modules/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, - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "node_modules/whatwg-url/node_modules/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 - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -33021,6 +33685,26 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "node_modules/which-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", + "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wicg-inert": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/wicg-inert/-/wicg-inert-3.1.1.tgz", @@ -36404,6 +37088,32 @@ } } }, + "@mswjs/cookies": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-0.2.2.tgz", + "integrity": "sha512-mlN83YSrcFgk7Dm1Mys40DLssI1KdJji2CMKN8eOlBqsTADYzj2+jWzsANsUTFbxDMWPD5e9bfA1RGqBpS3O1g==", + "dev": true, + "requires": { + "@types/set-cookie-parser": "^2.4.0", + "set-cookie-parser": "^2.4.6" + } + }, + "@mswjs/interceptors": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.17.5.tgz", + "integrity": "sha512-/uZkyPUZMRExZs+DZQVnc+uoDwLfs1gFNvcRY5S3Gu78U+uhovaSEUW3tuyld1e7Oke5Qphfseb8v66V+H1zWQ==", + "dev": true, + "requires": { + "@open-draft/until": "^1.0.3", + "@types/debug": "^4.1.7", + "@xmldom/xmldom": "^0.7.5", + "debug": "^4.3.3", + "headers-polyfill": "^3.1.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.2.4", + "web-encoding": "^1.1.5" + } + }, "@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -36470,6 +37180,12 @@ "rimraf": "^3.0.2" } }, + "@open-draft/until": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz", + "integrity": "sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==", + "dev": true + }, "@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.7.tgz", @@ -41678,6 +42394,21 @@ "@types/node": "*" } }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, + "requires": { + "@types/ms": "*" + } + }, "@types/eslint": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", @@ -41809,6 +42540,12 @@ "@types/istanbul-lib-report": "*" } }, + "@types/js-levenshtein": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz", + "integrity": "sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g==", + "dev": true + }, "@types/jsdom": { "version": "20.0.0", "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.0.tgz", @@ -41876,6 +42613,12 @@ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", "dev": true }, + "@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, "@types/node": { "version": "14.18.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.9.tgz", @@ -42001,6 +42744,15 @@ "@types/node": "*" } }, + "@types/set-cookie-parser": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.2.tgz", + "integrity": "sha512-fBZgytwhYAUkj/jC/FAV4RQ5EerRup1YQsXQCh8rZfiHkc4UahC192oH0smGwsXol3cL3A5oETuAHeQHmhXM4w==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/sinonjs__fake-timers": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", @@ -42456,6 +43208,12 @@ "dev": true, "requires": {} }, + "@xmldom/xmldom": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", + "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==", + "dev": true + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -42468,6 +43226,13 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "dev": true, + "optional": true + }, "abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -43014,6 +43779,12 @@ "postcss-value-parser": "^4.1.0" } }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -43642,6 +44413,29 @@ "file-uri-to-path": "1.0.0" } }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + } + } + }, "blob-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", @@ -44283,6 +45077,12 @@ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", "dev": true }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "check-more-types": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", @@ -44471,6 +45271,12 @@ "restore-cursor": "^3.1.0" } }, + "cli-spinners": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "dev": true + }, "cli-table3": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz", @@ -44491,6 +45297,12 @@ "string-width": "^4.2.0" } }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, "cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -44502,6 +45314,12 @@ "wrap-ansi": "^7.0.0" } }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true + }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -45746,6 +46564,15 @@ "execa": "^5.0.0" } }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, "define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -47281,6 +48108,28 @@ "is-extendable": "^1.0.1" } }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "dependencies": { + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + } + } + }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -47466,32 +48315,6 @@ "web-streams-polyfill": "^3.0.3" } }, - "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": { - "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 - } - } - }, "fetch-retry": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.3.tgz", @@ -47756,6 +48579,15 @@ "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", "dev": true }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -48295,6 +49127,12 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "graphql": { + "version": "16.6.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", + "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==", + "dev": true + }, "handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -48557,6 +49395,12 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "headers-polyfill": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.1.1.tgz", + "integrity": "sha512-ifvvIC+VDeLTEkJDwxECSI7k9rJF7sJavCh/UfhGsgJ+LXMbGILRf+NXhc4znuf+JA5X2/leQdOXk6Lq6Y2/wQ==", + "dev": true + }, "highlight.js": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", @@ -49038,6 +49882,65 @@ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", "dev": true }, + "inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "internal-slot": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", @@ -49288,6 +50191,15 @@ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -49313,6 +50225,12 @@ "is-path-inside": "^3.0.2" } }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, "is-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", @@ -49325,6 +50243,12 @@ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true }, + "is-node-process": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.0.1.tgz", + "integrity": "sha512-5IcdXuf++TTNt3oGl9EBdkvndXA8gmc4bz/Y+mdEpWh3Mcn/+kOw6hI7LD5CocqJWMzeb0I0ClndRVNdEPuJXQ==", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -49421,12 +50345,6 @@ "has-tostringtag": "^1.0.0" } }, - "is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", - "dev": true - }, "is-symbol": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", @@ -49436,6 +50354,19 @@ "has-symbols": "^1.0.2" } }, + "is-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", + "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -51985,6 +52916,12 @@ } } }, + "js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true + }, "js-sdsl": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", @@ -52438,12 +53375,6 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "dev": true }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, "lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -53199,6 +54130,157 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "msw": { + "version": "0.47.4", + "resolved": "https://registry.npmjs.org/msw/-/msw-0.47.4.tgz", + "integrity": "sha512-Psftt8Yfl0+l+qqg9OlmKEsxF8S/vtda0CmlR6y8wTaWrMMzuCDa55n2hEGC0ZRDwuV6FFWc/4CjoDsBpATKBw==", + "dev": true, + "requires": { + "@mswjs/cookies": "^0.2.2", + "@mswjs/interceptors": "^0.17.5", + "@open-draft/until": "^1.0.3", + "@types/cookie": "^0.4.1", + "@types/js-levenshtein": "^1.1.1", + "chalk": "4.1.1", + "chokidar": "^3.4.2", + "cookie": "^0.4.2", + "graphql": "^15.0.0 || ^16.0.0", + "headers-polyfill": "^3.1.0", + "inquirer": "^8.2.0", + "is-node-process": "^1.0.1", + "js-levenshtein": "^1.1.6", + "node-fetch": "^2.6.7", + "outvariant": "^1.3.0", + "path-to-regexp": "^6.2.0", + "statuses": "^2.0.0", + "strict-event-emitter": "^0.2.6", + "type-fest": "^2.19.0", + "yargs": "^17.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "yargs": { + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", + "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + } + } + }, "multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", @@ -53209,6 +54291,12 @@ "thunky": "^1.0.2" } }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, "nan": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", @@ -53767,6 +54855,59 @@ } } }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -53780,12 +54921,24 @@ "dev": true, "optional": true }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true + }, "ospath": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", "dev": true }, + "outvariant": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.3.0.tgz", + "integrity": "sha512-yeWM9k6UPfG/nzxdaPlJkB2p08hCg4xP6Lx99F+vP8YF7xyZVfTmJjrrNalkmzudD4WFvNLVudQikqUmF8zhVQ==", + "dev": true + }, "p-all": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-all/-/p-all-2.1.0.tgz", @@ -55576,6 +56729,12 @@ "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", "dev": true }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -56103,6 +57262,12 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "set-cookie-parser": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz", + "integrity": "sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==", + "dev": true + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -56850,6 +58015,15 @@ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, + "strict-event-emitter": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.6.tgz", + "integrity": "sha512-qDZOqEBoNtKLPb/qAutkXUt7hs3zXgYA1xX4pVa+gZHCZZVLr2r81AzHsK5YrQQhRNphMtkOUyAyOr9e1IxJTw==", + "dev": true, + "requires": { + "events": "^3.3.0" + } + }, "strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", @@ -57438,15 +58612,6 @@ } } }, - "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" - } - }, "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", @@ -58408,6 +59573,41 @@ "minimalistic-assert": "^1.0.0" } }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "dev": true, + "requires": { + "@zxing/text-encoding": "0.9.0", + "util": "^0.12.3" + }, + "dependencies": { + "util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + } + } + }, "web-namespaces": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", @@ -58732,25 +59932,6 @@ "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", "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" - }, - "dependencies": { - "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 - } - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -58779,6 +59960,20 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "which-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", + "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + } + }, "wicg-inert": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/wicg-inert/-/wicg-inert-3.1.1.tgz", diff --git a/package.json b/package.json index 75b5fe0f9..485292b50 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,6 @@ "eslint-plugin-react": "^7.31.8", "eslint-plugin-react-hooks": "^4.6.0", "eslint-webpack-plugin": "^3.2.0", - "fetch-mock": "^9.10.7", "file-loader": "^6.0.0", "glob": "^8.0.3", "history": "^5.3.0", @@ -88,6 +87,7 @@ "lodash.difference": "^4.5.0", "lodash.omit": "^4.5.0", "mini-css-extract-plugin": "^2.6.1", + "msw": "^0.47.4", "node-fetch": "^3.2.10", "prettier": "^2.7.1", "sass": "^1.55.0", diff --git a/src/api/clusterInterceptors.test.js b/src/api/clusterInterceptors.test.js index 57d333c3f..fa6051f83 100644 --- a/src/api/clusterInterceptors.test.js +++ b/src/api/clusterInterceptors.test.js @@ -1,5 +1,5 @@ /* -Copyright 2021 The Tekton Authors +Copyright 2021-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,28 +11,33 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; import * as API from './clusterInterceptors'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('getClusterInterceptors', () => { const data = { items: 'clusterinterceptors' }; - fetchMock.get(/clusterinterceptors/, data); + + server.use( + rest.get(/\/clusterinterceptors\/$/, (req, res, ctx) => res(ctx.json(data))) + ); + return API.getClusterInterceptors().then(tasks => { expect(tasks).toEqual(data); - fetchMock.restore(); }); }); it('getClusterInterceptor', () => { const name = 'foo'; const data = { fake: 'clusterinterceptor' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); + return API.getClusterInterceptor({ name }).then(task => { expect(task).toEqual(data); - fetchMock.restore(); }); }); diff --git a/src/api/clusterTasks.test.js b/src/api/clusterTasks.test.js index 706426e24..964a42495 100644 --- a/src/api/clusterTasks.test.js +++ b/src/api/clusterTasks.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,38 +11,42 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; import * as API from './clusterTasks'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('getClusterTasks', () => { const data = { items: 'clustertasks' }; - fetchMock.get(/clustertasks/, data); + server.use( + rest.get(/\/clustertasks\//, (req, res, ctx) => res(ctx.json(data))) + ); + return API.getClusterTasks().then(tasks => { expect(tasks).toEqual(data); - fetchMock.restore(); }); }); it('getClusterTask', () => { const name = 'foo'; const data = { fake: 'clustertask' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getClusterTask({ name }).then(task => { expect(task).toEqual(data); - fetchMock.restore(); }); }); it('deletePipelineRun', () => { const name = 'foo'; const data = { fake: 'clusterTask' }; - fetchMock.delete(`end:${name}`, data); + server.use( + rest.delete(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.deleteClusterTask({ name }).then(clusterTask => { expect(clusterTask).toEqual(data); - fetchMock.restore(); }); }); diff --git a/src/api/clusterTriggerBindings.test.js b/src/api/clusterTriggerBindings.test.js index 652067fb9..befcb3d65 100644 --- a/src/api/clusterTriggerBindings.test.js +++ b/src/api/clusterTriggerBindings.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,17 +11,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; import * as API from './clusterTriggerBindings'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('getClusterTriggerBinding', () => { const name = 'foo'; const data = { fake: 'clusterTriggerBinding' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getClusterTriggerBinding({ name }).then(clusterTriggerBinding => { expect(clusterTriggerBinding).toEqual(data); - fetchMock.restore(); }); }); @@ -29,10 +30,13 @@ it('getClusterTriggerBindings', () => { const data = { items: 'clusterTriggerBindings' }; - fetchMock.get(/clustertriggerbindings/, data); + server.use( + rest.get(/\/clustertriggerbindings\//, (req, res, ctx) => + res(ctx.json(data)) + ) + ); return API.getClusterTriggerBindings().then(clusterTriggerBindings => { expect(clusterTriggerBindings).toEqual(data); - fetchMock.restore(); }); }); diff --git a/src/api/comms.test.js b/src/api/comms.test.js index de4ba3d28..a32967a77 100644 --- a/src/api/comms.test.js +++ b/src/api/comms.test.js @@ -11,8 +11,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; - import { checkStatus, get, @@ -22,6 +20,7 @@ import { post, request } from './comms'; +import { rest, server } from '../../config_frontend/msw'; const uri = 'http://example.com'; @@ -146,20 +145,17 @@ describe('request', () => { const data = { fake: 'data' }; - - fetchMock.mock(uri, data); + server.use(rest.get(uri, (req, res, ctx) => res(ctx.json(data)))); return request(uri).then(response => { expect(response).toEqual(data); - fetchMock.restore(); }); }); it('throws on error', () => { - fetchMock.mock(uri, 400); + server.use(rest.get(uri, (req, res, ctx) => res(ctx.status(400)))); expect.assertions(1); return request(uri).catch(e => { expect(e).not.toBeNull(); - fetchMock.restore(); }); }); }); @@ -169,10 +165,9 @@ describe('get', () => { const data = { fake: 'data' }; - fetchMock.get(uri, data); + server.use(rest.get(uri, (req, res, ctx) => res(ctx.json(data)))); return get(uri).then(response => { expect(response).toEqual(data); - fetchMock.restore(); }); }); }); @@ -182,11 +177,12 @@ describe('post', () => { const data = { fake: 'data' }; - fetchMock.post(uri, data); - return post(uri, data).then(() => { - const options = fetchMock.lastOptions(); - expect(options.body).toEqual(JSON.stringify(data)); - fetchMock.restore(); + server.use( + // echo the received body so we can assert on it + rest.post(uri, async (req, res, ctx) => res(ctx.json(await req.json()))) + ); + return post(uri, data).then(responseBody => { + expect(responseBody).toEqual(data); }); }); }); diff --git a/src/api/eventListeners.test.js b/src/api/eventListeners.test.js index c583bc3a5..3db1822e3 100644 --- a/src/api/eventListeners.test.js +++ b/src/api/eventListeners.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,17 +11,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; import * as API from './eventListeners'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('getEventListener', () => { const name = 'foo'; const data = { fake: 'eventListener' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getEventListener({ name }).then(eventListener => { expect(eventListener).toEqual(data); - fetchMock.restore(); }); }); @@ -29,10 +30,11 @@ it('getEventListeners', () => { const data = { items: 'eventListeners' }; - fetchMock.get(/eventlisteners/, data); + server.use( + rest.get(/\/eventlisteners\//, (req, res, ctx) => res(ctx.json(data))) + ); return API.getEventListeners().then(eventListeners => { expect(eventListeners).toEqual(data); - fetchMock.restore(); }); }); diff --git a/src/api/extensions.test.js b/src/api/extensions.test.js index bafb34f20..4fdba6c46 100644 --- a/src/api/extensions.test.js +++ b/src/api/extensions.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,9 +11,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; import * as API from './extensions'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('getExtensions', () => { const displayName = 'displayName'; @@ -25,10 +25,11 @@ it('getExtensions', () => { ] } }; - fetchMock.get(/extensions/, extensions); + server.use( + rest.get(/\/extensions\//, (req, res, ctx) => res(ctx.json(extensions))) + ); return API.getExtensions().then(response => { expect(response).toEqual(extensions); - fetchMock.restore(); }); }); diff --git a/src/api/index.test.js b/src/api/index.test.js index a492aee04..e895436ee 100644 --- a/src/api/index.test.js +++ b/src/api/index.test.js @@ -11,11 +11,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; import { renderHook } from '@testing-library/react-hooks'; import { labels } from '@tektoncd/dashboard-utils'; import { getAPIWrapper, getQueryClient } from '../utils/test'; +import { rest, server } from '../../config_frontend/msw'; import * as API from '.'; import * as ClusterTasksAPI from './clusterTasks'; @@ -29,11 +29,12 @@ it('getCustomResource', () => { const name = 'testresource'; const namespace = 'testnamespace'; const data = { fake: 'resourcedata' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getCustomResource({ group, version, type, namespace, name }).then( resource => { expect(resource).toEqual(data); - fetchMock.restore(); } ); }); @@ -44,11 +45,12 @@ it('getCustomResources', () => { const type = 'testtype'; const namespace = 'testnamespace'; const data = { items: 'resourcedata' }; - fetchMock.get(`end:${type}/`, data); + server.use( + rest.get(new RegExp(`/${type}/$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getCustomResources({ group, version, type, namespace }).then( resources => { expect(resources).toEqual(data); - fetchMock.restore(); } ); }); @@ -81,7 +83,9 @@ it('useCustomResources', async () => { { metadata: { name: 'resource2' } } ] }; - fetchMock.get(/fake_type/, resources); + server.use( + rest.get(/\/fake_type\//, (req, res, ctx) => res(ctx.json(resources))) + ); const { result, waitFor } = renderHook( () => API.useCustomResources({ group, type, version }), { @@ -91,7 +95,6 @@ it('useCustomResources', async () => { await waitFor(() => result.current.isFetching); await waitFor(() => !result.current.isFetching); expect(result.current.data).toEqual(resources.items); - fetchMock.restore(); }); it('useAPIResource', () => { @@ -150,10 +153,11 @@ it('getNamespaces returns the correct data', () => { const data = { items: 'namespaces' }; - fetchMock.get(/namespaces/, data); + server.use( + rest.get(/\/namespaces\//, (req, res, ctx) => res(ctx.json(data))) + ); return API.getNamespaces().then(response => { expect(response).toEqual(data); - fetchMock.restore(); }); }); @@ -165,14 +169,15 @@ it('useNamespaces', async () => { { metadata: { name: 'namespace2' } } ] }; - fetchMock.get(/namespaces/, namespaces); + server.use( + rest.get(/\/namespaces\//, (req, res, ctx) => res(ctx.json(namespaces))) + ); const { result, waitFor } = renderHook(() => API.useNamespaces(), { wrapper: getAPIWrapper() }); await waitFor(() => result.current.isFetching); await waitFor(() => !result.current.isFetching); expect(result.current.data).toEqual(namespaces.items); - fetchMock.restore(); }); it('usePod', async () => { @@ -182,7 +187,7 @@ it('usePod', async () => { metadata: {}, spec: 'fake_spec' }; - fetchMock.get(/pods/, pod); + server.use(rest.get(/\/pods\//, (req, res, ctx) => res(ctx.json(pod)))); const { result, waitFor } = renderHook( () => API.usePod({ name, namespace }), { @@ -192,7 +197,6 @@ it('usePod', async () => { await waitFor(() => result.current.isFetching); await waitFor(() => !result.current.isFetching); expect(result.current.data).toEqual(pod); - fetchMock.restore(); }); it('useEvents', async () => { @@ -203,7 +207,7 @@ it('useEvents', async () => { metadata: {}, items: [{ metadata: { name: 'event1' } }, { metadata: { name: 'event2' } }] }; - fetchMock.get(/events/, events); + server.use(rest.get(/\/events\//, (req, res, ctx) => res(ctx.json(events)))); const { result, waitFor } = renderHook( () => API.useEvents({ involvedObjectKind, involvedObjectName, namespace }), { @@ -213,7 +217,6 @@ it('useEvents', async () => { await waitFor(() => result.current.isFetching); await waitFor(() => !result.current.isFetching); expect(result.current.data).toEqual(events.items); - fetchMock.restore(); }); it('getExternalLogURL', () => { @@ -230,17 +233,13 @@ it('getPodLog', () => { const namespace = 'default'; const name = 'foo'; const data = 'logs'; - const responseConfig = { - body: data, - status: 200, - headers: { 'Content-Type': 'text/plain' } - }; - fetchMock.get(`end:${name}/log`, responseConfig, { - sendAsJson: false - }); + server.use( + rest.get(new RegExp(`/${name}/log$`), (req, res, ctx) => + res(ctx.text(data)) + ) + ); return API.getPodLog({ name, namespace }).then(log => { expect(log).toEqual(data); - fetchMock.restore(); }); }); @@ -249,17 +248,15 @@ it('getPodLog with container name', () => { const name = 'foo'; const container = 'containerName'; const data = 'logs'; - const responseConfig = { - body: data, - status: 200, - headers: { 'Content-Type': 'text/plain' } - }; - fetchMock.get(`end:${name}/log?container=${container}`, responseConfig, { - sendAsJson: false - }); + server.use( + rest.get(new RegExp(`/${name}/log$`), async (req, res, ctx) => + req.url.searchParams.get('container') === container + ? res(await ctx.text(data)) + : res(ctx.json(404)) + ) + ); return API.getPodLog({ container, name, namespace }).then(log => { expect(log).toEqual(data); - fetchMock.restore(); }); }); @@ -407,11 +404,13 @@ it('importResources', () => { } }; - fetchMock.post('*', { body: data, status: 201 }); + server.use( + rest.post(/\/pipelineruns\//, async (req, res, ctx) => + res(ctx.status(201), ctx.json(await req.json())) + ) + ); return API.importResources(payload).then(response => { expect(response).toEqual(data); - expect(JSON.parse(fetchMock.lastOptions().body)).toMatchObject(data); - fetchMock.restore(); mockDateNow.mockRestore(); }); }); @@ -563,11 +562,13 @@ it('importResources with revision and no serviceAccount', () => { } }; - fetchMock.post('*', { body: data, status: 201 }); + server.use( + rest.post(/\/pipelineruns\//, async (req, res, ctx) => + res(ctx.status(201), ctx.json(await req.json())) + ) + ); return API.importResources(payload).then(response => { expect(response).toEqual(data); - expect(JSON.parse(fetchMock.lastOptions().body)).toMatchObject(data); - fetchMock.restore(); mockDateNow.mockRestore(); }); }); @@ -579,10 +580,13 @@ describe('getAPIResource', () => { const type = 'testtype'; const apiResource = { name: type }; const data = { resources: [apiResource] }; - fetchMock.get(`end:/apis/${group}/${version}`, data); + server.use( + rest.get(new RegExp(`/apis/${group}/${version}$`), (req, res, ctx) => + res(ctx.json(data)) + ) + ); return API.getAPIResource({ group, version, type }).then(resource => { expect(resource).toEqual(apiResource); - fetchMock.restore(); }); }); @@ -592,10 +596,13 @@ describe('getAPIResource', () => { const type = 'testtype'; const apiResource = { name: type }; const data = { resources: [apiResource] }; - fetchMock.get(`end:/api/${version}`, data); + server.use( + rest.get(new RegExp(`/api/${version}$`), (req, res, ctx) => + res(ctx.json(data)) + ) + ); return API.getAPIResource({ group, version, type }).then(resource => { expect(resource).toEqual(apiResource); - fetchMock.restore(); }); }); }); @@ -603,42 +610,41 @@ describe('getAPIResource', () => { describe('getInstallProperties', () => { it('returns expected data', async () => { const data = { fake: 'properties' }; - fetchMock.get(/properties/, data); + server.use( + rest.get(/\/properties$/, (req, res, ctx) => res(ctx.json(data))) + ); const properties = await API.getInstallProperties(); expect(properties).toEqual(data); - fetchMock.restore(); }); it('handles error in case of Dashboard client mode', async () => { - const error = new Error(); - error.response = { - status: 404 - }; - fetchMock.get(/properties/, { throws: error }); + server.use( + rest.get(/\/properties$/, (req, res, ctx) => res(ctx.status(404))) + ); const properties = await API.getInstallProperties(); expect(properties.dashboardVersion).toEqual('kubectl-proxy-client'); - fetchMock.restore(); }); it('handles unexpected errors', async () => { - const error = new Error(); - fetchMock.get(/properties/, { throws: error }); + server.use( + rest.get(/\/properties$/, (req, res, ctx) => res(ctx.status(500))) + ); const properties = await API.getInstallProperties(); expect(properties).toBeUndefined(); - fetchMock.restore(); }); }); it('useProperties', async () => { const properties = { fake: 'properties' }; - fetchMock.get(/properties/, properties); + server.use( + rest.get(/\/properties$/, (req, res, ctx) => res(ctx.json(properties))) + ); const { result, waitFor } = renderHook(() => API.useProperties(), { wrapper: getAPIWrapper() }); await waitFor(() => result.current.isFetching); await waitFor(() => !result.current.isFetching); expect(result.current.data).toEqual(properties); - fetchMock.restore(); }); it('other hooks that depend on useProperties', async () => { @@ -663,7 +669,9 @@ it('other hooks that depend on useProperties', async () => { triggersNamespace, triggersVersion }; - fetchMock.get(/properties/, properties); + server.use( + rest.get(/\/properties$/, (req, res, ctx) => res(ctx.json(properties))) + ); const { result, waitFor } = renderHook(() => API.useProperties(), { wrapper: getAPIWrapper({ queryClient }) }); @@ -720,6 +728,4 @@ it('other hooks that depend on useProperties', async () => { } ); expect(isTriggersInstalledResult.current).toEqual(true); - - fetchMock.restore(); }); diff --git a/src/api/pipelineResources.test.js b/src/api/pipelineResources.test.js index 1575d4616..067b834ce 100644 --- a/src/api/pipelineResources.test.js +++ b/src/api/pipelineResources.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,10 +11,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; - import * as API from './pipelineResources'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('createPipelineResource', () => { const namespace = 'namespace1'; @@ -40,20 +39,22 @@ it('createPipelineResource', () => { } }; const data = { fake: 'data' }; - fetchMock.post('*', data); + server.use( + rest.post(/\/pipelineresources\//, (req, res, ctx) => res(ctx.json(data))) + ); return API.createPipelineResource({ namespace, payload }).then(response => { expect(response).toEqual(data); - fetchMock.restore(); }); }); it('deletePipelineResource', () => { const name = 'foo'; const data = { fake: 'pipelineResource' }; - fetchMock.delete(`end:${name}`, data); + server.use( + rest.delete(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.deletePipelineResource({ name }).then(pipelineResource => { expect(pipelineResource).toEqual(data); - fetchMock.restore(); }); }); @@ -61,20 +62,22 @@ it('getPipelineResources', () => { const data = { items: 'pipelineResources' }; - fetchMock.get(/pipelineresources/, data); + server.use( + rest.get(/\/pipelineresources\//, (req, res, ctx) => res(ctx.json(data))) + ); return API.getPipelineResources().then(pipelineResources => { expect(pipelineResources).toEqual(data); - fetchMock.restore(); }); }); it('getPipelineResource', () => { const name = 'foo'; const data = { fake: 'pipelineResource' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getPipelineResource({ name }).then(pipelineResource => { expect(pipelineResource).toEqual(data); - fetchMock.restore(); }); }); diff --git a/src/api/pipelineRuns.test.js b/src/api/pipelineRuns.test.js index 0d8d1a387..29120573e 100644 --- a/src/api/pipelineRuns.test.js +++ b/src/api/pipelineRuns.test.js @@ -11,23 +11,24 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; - import * as API from './pipelineRuns'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('cancelPipelineRun', () => { const name = 'foo'; const namespace = 'foospace'; const payload = [{ op: 'replace', path: '/spec/status', value: 'Cancelled' }]; const returnedPipelineRun = { fake: 'PipelineRun' }; - fetchMock.patch(`end:${name}`, returnedPipelineRun); + server.use( + rest.patch(new RegExp(`/${name}$`), async (req, res, ctx) => + (await req.text()) === JSON.stringify(payload) + ? res(ctx.json(returnedPipelineRun)) + : res(ctx.json(400)) + ) + ); return API.cancelPipelineRun({ name, namespace }).then(response => { - expect(fetchMock.lastOptions()).toMatchObject({ - body: JSON.stringify(payload) - }); expect(response).toEqual(returnedPipelineRun); - fetchMock.restore(); }); }); @@ -37,13 +38,15 @@ it('cancelPipelineRun with non-default status', () => { const status = 'StoppedRunFinally'; const payload = [{ op: 'replace', path: '/spec/status', value: status }]; const returnedPipelineRun = { fake: 'PipelineRun' }; - fetchMock.patch(`end:${name}`, returnedPipelineRun); + server.use( + rest.patch(new RegExp(`/${name}$`), async (req, res, ctx) => + (await req.text()) === JSON.stringify(payload) + ? res(ctx.json(returnedPipelineRun)) + : res(ctx.json(400)) + ) + ); return API.cancelPipelineRun({ name, namespace, status }).then(response => { - expect(fetchMock.lastOptions()).toMatchObject({ - body: JSON.stringify(payload) - }); expect(response).toEqual(returnedPipelineRun); - fetchMock.restore(); }); }); @@ -85,13 +88,15 @@ it('createPipelineRun', () => { timeout } }; - fetchMock.post('*', { body: data, status: 201 }); + server.use( + rest.post(/\/pipelineruns/, async (req, res, ctx) => { + expect(await req.json()).toEqual(data); + return res(ctx.status(201), ctx.json(data)); + }) + ); + return API.createPipelineRun(payload).then(response => { expect(response).toEqual(data); - expect(fetchMock.lastOptions()).toMatchObject({ - body: JSON.stringify(data) - }); - fetchMock.restore(); mockDateNow.mockRestore(); }); }); @@ -142,13 +147,15 @@ it('createPipelineRun with nodeSelector', () => { timeout } }; - fetchMock.post('*', { body: data, status: 201 }); + server.use( + rest.post(/\/pipelineruns/, async (req, res, ctx) => { + expect(await req.json()).toEqual(data); + return res(ctx.status(201), ctx.json(data)); + }) + ); + return API.createPipelineRun(payload).then(response => { expect(response).toEqual(data); - expect(fetchMock.lastOptions()).toMatchObject({ - body: JSON.stringify(data) - }); - fetchMock.restore(); mockDateNow.mockRestore(); }); }); @@ -156,20 +163,22 @@ it('createPipelineRun with nodeSelector', () => { it('deletePipelineRun', () => { const name = 'foo'; const data = { fake: 'pipelineRun' }; - fetchMock.delete(`end:${name}`, data); + server.use( + rest.delete(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.deletePipelineRun({ name }).then(pipelineRun => { expect(pipelineRun).toEqual(data); - fetchMock.restore(); }); }); it('getPipelineRun', () => { const name = 'foo'; const data = { fake: 'pipelineRun' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getPipelineRun({ name }).then(pipelineRun => { expect(pipelineRun).toEqual(data); - fetchMock.restore(); }); }); @@ -177,10 +186,11 @@ it('getPipelineRuns', () => { const data = { items: 'pipelineRuns' }; - fetchMock.get(/pipelineruns/, data); + server.use( + rest.get(/\/pipelineruns\//, (req, res, ctx) => res(ctx.json(data))) + ); return API.getPipelineRuns({ filters: [] }).then(pipelineRuns => { expect(pipelineRuns).toEqual(data); - fetchMock.restore(); }); }); @@ -189,11 +199,12 @@ it('getPipelineRuns With Query Params', () => { const data = { items: 'pipelineRuns' }; - fetchMock.get(/pipelineruns/, data); + server.use( + rest.get(/\/pipelineruns\//, (req, res, ctx) => res(ctx.json(data))) + ); return API.getPipelineRuns({ pipelineName, filters: [] }).then( pipelineRuns => { expect(pipelineRuns).toEqual(data); - fetchMock.restore(); } ); }); @@ -238,23 +249,26 @@ it('usePipelineRun', () => { }); it('rerunPipelineRun', () => { - const filter = 'end:/pipelineruns/'; const originalPipelineRun = { metadata: { name: 'fake_pipelineRun' }, spec: { status: 'fake_status' }, status: 'fake_status' }; const newPipelineRun = { metadata: { name: 'fake_pipelineRun_rerun' } }; - fetchMock.post(filter, { body: newPipelineRun, status: 201 }); + server.use( + rest.post(/\/pipelineruns\/$/, async (req, res, ctx) => { + const { metadata, spec, status } = await req.json(); + expect(metadata.generateName).toMatch( + new RegExp(originalPipelineRun.metadata.name) + ); + expect(spec.status).toBeUndefined(); + expect(status).toBeUndefined(); + return res(ctx.status(201), ctx.json(newPipelineRun)); + }) + ); + return API.rerunPipelineRun(originalPipelineRun).then(data => { - const body = JSON.parse(fetchMock.lastCall(filter)[1].body); - expect(body.metadata.generateName).toMatch( - new RegExp(originalPipelineRun.metadata.name) - ); - expect(body.status).toBeUndefined(); - expect(body.spec.status).toBeUndefined(); expect(data).toEqual(newPipelineRun); - fetchMock.restore(); }); }); @@ -263,14 +277,16 @@ it('startPipelineRun', () => { const namespace = 'foospace'; const returnedPipelineRun = { fake: 'PipelineRun' }; const payload = [{ op: 'remove', path: '/spec/status' }]; - fetchMock.patch(`end:${name}`, returnedPipelineRun); + server.use( + rest.patch(new RegExp(`/${name}$`), async (req, res, ctx) => + (await req.text()) === JSON.stringify(payload) + ? res(ctx.json(returnedPipelineRun)) + : res(ctx.json(400)) + ) + ); return API.startPipelineRun({ metadata: { name, namespace } }).then( response => { - expect(fetchMock.lastOptions()).toMatchObject({ - body: JSON.stringify(payload) - }); expect(response).toEqual(returnedPipelineRun); - fetchMock.restore(); } ); }); diff --git a/src/api/pipelines.test.js b/src/api/pipelines.test.js index 647b56d7f..1965053e4 100644 --- a/src/api/pipelines.test.js +++ b/src/api/pipelines.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,38 +11,39 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; import * as API from './pipelines'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('getPipelines', () => { const data = { items: 'pipelines' }; - fetchMock.get(/pipelines/, data); + server.use(rest.get(/\/pipelines\//, (req, res, ctx) => res(ctx.json(data)))); return API.getPipelines().then(pipelines => { expect(pipelines).toEqual(data); - fetchMock.restore(); }); }); it('getPipeline', () => { const name = 'foo'; const data = { fake: 'pipeline' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getPipeline({ name }).then(pipeline => { expect(pipeline).toEqual(data); - fetchMock.restore(); }); }); it('deletePipeline', () => { const name = 'foo'; const data = { fake: 'pipeline' }; - fetchMock.delete(`end:${name}`, data); + server.use( + rest.delete(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.deletePipeline({ name }).then(pipeline => { expect(pipeline).toEqual(data); - fetchMock.restore(); }); }); diff --git a/src/api/runs.test.js b/src/api/runs.test.js index ce5380f16..1dd9e5e60 100644 --- a/src/api/runs.test.js +++ b/src/api/runs.test.js @@ -11,10 +11,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; - import * as API from './runs'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('cancelRun', () => { const name = 'foo'; @@ -23,33 +22,41 @@ it('cancelRun', () => { const payload = [ { op: 'replace', path: '/spec/status', value: 'RunCancelled' } ]; - fetchMock.patch(`end:${name}`, returnedRun); + server.use( + rest.patch(new RegExp(`/${name}$`), async (req, res, ctx) => + (await req.text()) === JSON.stringify(payload) + ? res(ctx.json(returnedRun)) + : res(ctx.json(400)) + ) + ); return API.cancelRun({ name, namespace }).then(response => { - expect(fetchMock.lastOptions()).toMatchObject({ - body: JSON.stringify(payload) - }); expect(response).toEqual(returnedRun); - fetchMock.restore(); }); }); it('deleteRun', () => { const name = 'foo'; const data = { fake: 'Run' }; - fetchMock.delete(`end:${name}`, data); + server.use( + rest.delete(new RegExp(`/${name}$`), async (req, res, ctx) => + res(ctx.json(data)) + ) + ); return API.deleteRun({ name }).then(run => { expect(run).toEqual(data); - fetchMock.restore(); }); }); it('getRun', () => { const name = 'foo'; const data = { fake: 'Run' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), async (req, res, ctx) => + res(ctx.json(data)) + ) + ); return API.getRun({ name }).then(run => { expect(run).toEqual(data); - fetchMock.restore(); }); }); @@ -57,10 +64,11 @@ it('getRuns', () => { const data = { items: 'Runs' }; - fetchMock.get(/runs/, data); + server.use( + rest.get(/\/runs\//, async (req, res, ctx) => res(ctx.json(data))) + ); return API.getRuns({ filters: [] }).then(runs => { expect(runs).toEqual(data); - fetchMock.restore(); }); }); @@ -104,22 +112,25 @@ it('useRun', () => { }); it('rerunRun', () => { - const filter = 'end:/runs/'; const originalRun = { metadata: { name: 'fake_run' }, spec: { status: 'fake_status' }, status: 'fake_status' }; const newRun = { metadata: { name: 'fake_run_rerun' } }; - fetchMock.post(filter, { body: newRun, status: 201 }); + server.use( + rest.post(/\/runs\/$/, async (req, res, ctx) => { + const { metadata, spec, status } = await req.json(); + expect(metadata.generateName).toMatch( + new RegExp(originalRun.metadata.name) + ); + expect(spec.status).toBeUndefined(); + expect(status).toBeUndefined(); + return res(ctx.status(201), ctx.json(newRun)); + }) + ); + return API.rerunRun(originalRun).then(data => { - const body = JSON.parse(fetchMock.lastCall(filter)[1].body); - expect(body.metadata.generateName).toMatch( - new RegExp(originalRun.metadata.name) - ); - expect(body.status).toBeUndefined(); - expect(body.spec.status).toBeUndefined(); expect(data).toEqual(newRun); - fetchMock.restore(); }); }); diff --git a/src/api/serviceAccounts.test.js b/src/api/serviceAccounts.test.js index c16f7ae5d..dca4777f8 100644 --- a/src/api/serviceAccounts.test.js +++ b/src/api/serviceAccounts.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,16 +11,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; import * as API from './serviceAccounts'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('getServiceAccounts returns the correct data', () => { const data = { items: 'serviceaccounts' }; - fetchMock.get(/serviceaccounts/, data); + server.use( + rest.get(/\/serviceaccounts\//, (req, res, ctx) => res(ctx.json(data))) + ); return API.getServiceAccounts().then(response => { expect(response).toEqual(data); - fetchMock.restore(); }); }); diff --git a/src/api/taskRuns.test.js b/src/api/taskRuns.test.js index c2d1ad3d4..cfca6f2f3 100644 --- a/src/api/taskRuns.test.js +++ b/src/api/taskRuns.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,10 +11,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; - import * as API from './taskRuns'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('cancelTaskRun', () => { const name = 'foo'; @@ -23,27 +22,32 @@ it('cancelTaskRun', () => { const payload = [ { op: 'replace', path: '/spec/status', value: 'TaskRunCancelled' } ]; - fetchMock.patch(`end:${name}`, returnedTaskRun); + server.use( + rest.patch(new RegExp(`/${name}$`), async (req, res, ctx) => + (await req.text()) === JSON.stringify(payload) + ? res(ctx.json(returnedTaskRun)) + : res(ctx.json(400)) + ) + ); return API.cancelTaskRun({ name, namespace }).then(response => { - expect(fetchMock.lastOptions()).toMatchObject({ - body: JSON.stringify(payload) - }); expect(response).toEqual(returnedTaskRun); - fetchMock.restore(); }); }); it('createTaskRun uses correct kubernetes information', () => { const data = { fake: 'createtaskrun' }; - fetchMock.post(/taskruns/, { body: data, status: 201 }); + server.use( + rest.post(/\/taskruns\//, async (req, res, ctx) => { + const sentBody = await req.json(); + expect(sentBody.apiVersion).toEqual('tekton.dev/v1beta1'); + expect(sentBody.kind).toEqual('TaskRun'); + expect(sentBody).toHaveProperty('metadata'); + expect(sentBody).toHaveProperty('spec'); + return res(ctx.status(201), ctx.json(data)); + }) + ); return API.createTaskRun({}).then(response => { expect(response).toEqual(data); - const sentBody = JSON.parse(fetchMock.lastOptions().body); - expect(sentBody.apiVersion).toEqual('tekton.dev/v1beta1'); - expect(sentBody.kind).toEqual('TaskRun'); - expect(sentBody).toHaveProperty('metadata'); - expect(sentBody).toHaveProperty('spec'); - fetchMock.restore(); }); }); @@ -54,51 +58,60 @@ it('createTaskRun has correct metadata', () => { const namespace = 'fake-namespace'; const taskName = 'fake-task'; const labels = { app: 'fake-app' }; - fetchMock.post(/taskruns/, {}); + server.use( + rest.post(/\/taskruns\//, async (req, res, ctx) => { + const { metadata: sentMetadata } = await req.json(); + expect(sentMetadata.name).toMatch(taskName); // include name + expect(sentMetadata.name).toMatch('fake-timestamp'); // include timestamp + expect(sentMetadata.namespace).toEqual(namespace); + expect(sentMetadata.labels.app).toEqual('fake-app'); + return res(ctx.status(201), ctx.json({})); + }) + ); return API.createTaskRun({ namespace, taskName, labels }).then(() => { - const sentMetadata = JSON.parse(fetchMock.lastOptions().body).metadata; - expect(sentMetadata.name).toMatch(taskName); // include name - expect(sentMetadata.name).toMatch('fake-timestamp'); // include timestamp - expect(sentMetadata.namespace).toEqual(namespace); - expect(sentMetadata.labels.app).toEqual('fake-app'); - fetchMock.restore(); mockDateNow.mockRestore(); }); }); it('createTaskRun handles taskRef', () => { const taskName = 'fake-task'; - fetchMock.post(/taskruns/, {}); - return API.createTaskRun({ taskName }).then(() => { - const sentSpec = JSON.parse(fetchMock.lastOptions().body).spec; - expect(sentSpec.taskRef.name).toEqual(taskName); - expect(sentSpec.taskRef.kind).toEqual('Task'); - fetchMock.restore(); - }); + server.use( + rest.post(/\/taskruns\//, async (req, res, ctx) => { + const { spec: sentSpec } = await req.json(); + expect(sentSpec.taskRef.name).toEqual(taskName); + expect(sentSpec.taskRef.kind).toEqual('Task'); + return res(ctx.status(201), ctx.json({})); + }) + ); + return API.createTaskRun({ taskName }); }); it('createTaskRun handles ClusterTask in taskRef', () => { const taskName = 'fake-task'; - fetchMock.post(/taskruns/, {}); - return API.createTaskRun({ taskName, kind: 'ClusterTask' }).then(() => { - const sentSpec = JSON.parse(fetchMock.lastOptions().body).spec; - expect(sentSpec.taskRef.kind).toEqual('ClusterTask'); - fetchMock.restore(); - }); + server.use( + rest.post(/\/taskruns\//, async (req, res, ctx) => { + const { spec: sentSpec } = await req.json(); + expect(sentSpec.taskRef.kind).toEqual('ClusterTask'); + return res(ctx.status(201), ctx.json({})); + }) + ); + return API.createTaskRun({ taskName, kind: 'ClusterTask' }); }); it('createTaskRun handles parameters', () => { const taskName = 'fake-task'; const params = { 'fake-param-name': 'fake-param-value' }; - fetchMock.post(/taskruns/, {}); - return API.createTaskRun({ taskName, params }).then(() => { - const sentSpec = JSON.parse(fetchMock.lastOptions().body).spec; - expect(sentSpec.params).toContainEqual({ - name: 'fake-param-name', - value: 'fake-param-value' - }); - fetchMock.restore(); - }); + server.use( + rest.post(/\/taskruns\//, async (req, res, ctx) => { + const { spec: sentSpec } = await req.json(); + expect(sentSpec.params).toContainEqual({ + name: 'fake-param-name', + value: 'fake-param-value' + }); + return res(ctx.status(201), ctx.json({})); + }) + ); + return API.createTaskRun({ taskName, params }); }); it('createTaskRun handles resources', () => { @@ -107,72 +120,83 @@ it('createTaskRun handles resources', () => { inputs: { 'fake-task-input': 'fake-input-resource' }, outputs: { 'fake-task-output': 'fake-output-resource' } }; - fetchMock.post(/taskruns/, {}); - return API.createTaskRun({ taskName, resources }).then(() => { - const sentResources = JSON.parse(fetchMock.lastOptions().body).spec - .resources; - expect(sentResources.inputs).toContainEqual({ - name: 'fake-task-input', - resourceRef: { name: 'fake-input-resource' } - }); - expect(sentResources.outputs).toContainEqual({ - name: 'fake-task-output', - resourceRef: { name: 'fake-output-resource' } - }); - fetchMock.restore(); - }); + server.use( + rest.post(/\/taskruns\//, async (req, res, ctx) => { + const { + spec: { resources: sentResources } + } = await req.json(); + expect(sentResources.inputs).toContainEqual({ + name: 'fake-task-input', + resourceRef: { name: 'fake-input-resource' } + }); + expect(sentResources.outputs).toContainEqual({ + name: 'fake-task-output', + resourceRef: { name: 'fake-output-resource' } + }); + return res(ctx.status(201), ctx.json({})); + }) + ); + return API.createTaskRun({ taskName, resources }); }); it('createTaskRun handles serviceAccount', () => { const taskName = 'fake-task'; const serviceAccount = 'fake-service-account'; - fetchMock.post(/taskruns/, {}); - return API.createTaskRun({ taskName, serviceAccount }).then(() => { - const sentSpec = JSON.parse(fetchMock.lastOptions().body).spec; - expect(sentSpec.serviceAccountName).toEqual(serviceAccount); - fetchMock.restore(); - }); + server.use( + rest.post(/\/taskruns\//, async (req, res, ctx) => { + const { spec: sentSpec } = await req.json(); + expect(sentSpec.serviceAccountName).toEqual(serviceAccount); + return res(ctx.status(201), ctx.json({})); + }) + ); + return API.createTaskRun({ taskName, serviceAccount }); }); it('createTaskRun handles nodeSelector', () => { const taskName = 'fake-task'; const nodeSelector = { disk: 'ssd' }; - fetchMock.post(/taskruns/, {}); - return API.createTaskRun({ taskName, nodeSelector }).then(() => { - const sentSpec = JSON.parse(fetchMock.lastOptions().body).spec; - expect(sentSpec.podTemplate).toEqual({ nodeSelector }); - fetchMock.restore(); - }); + server.use( + rest.post(/\/taskruns\//, async (req, res, ctx) => { + const { spec: sentSpec } = await req.json(); + expect(sentSpec.podTemplate).toEqual({ nodeSelector }); + return res(ctx.status(201), ctx.json({})); + }) + ); + return API.createTaskRun({ taskName, nodeSelector }); }); it('createTaskRun handles timeout', () => { const taskName = 'fake-task'; const timeout = 'fake-timeout'; - fetchMock.post(/taskruns/, {}); - return API.createTaskRun({ taskName, timeout }).then(() => { - const sentSpec = JSON.parse(fetchMock.lastOptions().body).spec; - expect(sentSpec.timeout).toEqual(timeout); - fetchMock.restore(); - }); + server.use( + rest.post(/\/taskruns\//, async (req, res, ctx) => { + const { spec: sentSpec } = await req.json(); + expect(sentSpec.timeout).toEqual(timeout); + return res(ctx.status(201), ctx.json({})); + }) + ); + return API.createTaskRun({ taskName, timeout }); }); it('deleteTaskRun', () => { const name = 'foo'; const data = { fake: 'taskRun' }; - fetchMock.delete(`end:${name}`, data); + server.use( + rest.delete(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.deleteTaskRun({ name }).then(taskRun => { expect(taskRun).toEqual(data); - fetchMock.restore(); }); }); it('getTaskRun', () => { const name = 'foo'; const data = { fake: 'taskRun' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getTaskRun({ name }).then(taskRun => { expect(taskRun).toEqual(data); - fetchMock.restore(); }); }); @@ -180,10 +204,9 @@ it('getTaskRuns', () => { const data = { items: 'taskRuns' }; - fetchMock.get(/taskruns/, data); + server.use(rest.get(/\/taskruns\//, (req, res, ctx) => res(ctx.json(data)))); return API.getTaskRuns().then(taskRuns => { expect(taskRuns).toEqual(data); - fetchMock.restore(); }); }); @@ -192,10 +215,9 @@ it('getTaskRuns With Query Params', () => { const data = { items: 'taskRuns' }; - fetchMock.get(/taskruns/, data); + server.use(rest.get(/\/taskruns\//, (req, res, ctx) => res(ctx.json(data)))); return API.getTaskRuns({ taskName }).then(taskRuns => { expect(taskRuns).toEqual(data); - fetchMock.restore(); }); }); @@ -239,22 +261,24 @@ it('useTaskRun', () => { }); it('rerunTaskRun', () => { - const filter = 'end:/taskruns/'; const originalTaskRun = { metadata: { name: 'fake_taskRun' }, spec: { status: 'fake_status' }, status: 'fake_status' }; const newTaskRun = { metadata: { name: 'fake_taskRun_rerun' } }; - fetchMock.post(filter, { body: newTaskRun, status: 201 }); + server.use( + rest.post(/\/taskruns\/$/, async (req, res, ctx) => { + const { metadata, spec, status } = await req.json(); + expect(metadata.generateName).toMatch( + new RegExp(originalTaskRun.metadata.name) + ); + expect(spec.status).toBeUndefined(); + expect(status).toBeUndefined(); + return res(ctx.status(201), ctx.json(newTaskRun)); + }) + ); return API.rerunTaskRun(originalTaskRun).then(data => { - const body = JSON.parse(fetchMock.lastCall(filter)[1].body); - expect(body.metadata.generateName).toMatch( - new RegExp(originalTaskRun.metadata.name) - ); - expect(body.status).toBeUndefined(); - expect(body.spec.status).toBeUndefined(); expect(data).toEqual(newTaskRun); - fetchMock.restore(); }); }); diff --git a/src/api/tasks.test.js b/src/api/tasks.test.js index 996ab21a4..ca55cb39d 100644 --- a/src/api/tasks.test.js +++ b/src/api/tasks.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,38 +11,39 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; import * as API from './tasks'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('getTasks', () => { const data = { items: 'tasks' }; - fetchMock.get(/tasks/, data); + server.use(rest.get(/\/tasks\//, (req, res, ctx) => res(ctx.json(data)))); return API.getTasks().then(tasks => { expect(tasks).toEqual(data); - fetchMock.restore(); }); }); it('getTask', () => { const name = 'foo'; const data = { fake: 'task' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getTask({ name }).then(task => { expect(task).toEqual(data); - fetchMock.restore(); }); }); it('deleteTask', () => { const name = 'foo'; const data = { fake: 'task' }; - fetchMock.delete(`end:${name}`, data); + server.use( + rest.delete(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.deleteTask({ name }).then(task => { expect(task).toEqual(data); - fetchMock.restore(); }); }); diff --git a/src/api/triggerBindings.test.js b/src/api/triggerBindings.test.js index 79d20c120..663cb6f43 100644 --- a/src/api/triggerBindings.test.js +++ b/src/api/triggerBindings.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,17 +11,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; import * as API from './triggerBindings'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('getTriggerBinding', () => { const name = 'foo'; const data = { fake: 'triggerBinding' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getTriggerBinding({ name }).then(triggerBinding => { expect(triggerBinding).toEqual(data); - fetchMock.restore(); }); }); @@ -29,10 +30,11 @@ it('getTriggerBindings', () => { const data = { items: 'triggerBindings' }; - fetchMock.get(/triggerbindings/, data); + server.use( + rest.get(/\/triggerbindings\//, (req, res, ctx) => res(ctx.json(data))) + ); return API.getTriggerBindings().then(triggerBindings => { expect(triggerBindings).toEqual(data); - fetchMock.restore(); }); }); diff --git a/src/api/triggerTemplates.test.js b/src/api/triggerTemplates.test.js index 7f03321f5..654084c16 100644 --- a/src/api/triggerTemplates.test.js +++ b/src/api/triggerTemplates.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,17 +11,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; import * as API from './triggerTemplates'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('getTriggerTemplate', () => { const name = 'foo'; const data = { fake: 'triggerTemplate' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getTriggerTemplate({ name }).then(triggerTemplate => { expect(triggerTemplate).toEqual(data); - fetchMock.restore(); }); }); @@ -29,10 +30,11 @@ it('getTriggerTemplates', () => { const data = { items: 'triggerTemplates' }; - fetchMock.get(/triggertemplates/, data); + server.use( + rest.get(/\/triggertemplates\//, (req, res, ctx) => res(ctx.json(data))) + ); return API.getTriggerTemplates().then(triggerTemplates => { expect(triggerTemplates).toEqual(data); - fetchMock.restore(); }); }); diff --git a/src/api/triggers.test.js b/src/api/triggers.test.js index 03a106dac..515222943 100644 --- a/src/api/triggers.test.js +++ b/src/api/triggers.test.js @@ -1,5 +1,5 @@ /* -Copyright 2021 The Tekton Authors +Copyright 2021-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -11,17 +11,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from 'fetch-mock'; import * as API from './triggers'; import * as utils from './utils'; +import { rest, server } from '../../config_frontend/msw'; it('getTrigger', () => { const name = 'foo'; const data = { fake: 'trigger' }; - fetchMock.get(`end:${name}`, data); + server.use( + rest.get(new RegExp(`/${name}$`), (req, res, ctx) => res(ctx.json(data))) + ); return API.getTrigger({ name }).then(trigger => { expect(trigger).toEqual(data); - fetchMock.restore(); }); }); @@ -29,10 +30,9 @@ it('getTriggers', () => { const data = { items: 'triggers' }; - fetchMock.get(/triggers/, data); + server.use(rest.get(/\/triggers\//, (req, res, ctx) => res(ctx.json(data)))); return API.getTriggers().then(triggers => { expect(triggers).toEqual(data); - fetchMock.restore(); }); }); diff --git a/src/containers/App/App.test.js b/src/containers/App/App.test.js index c834fc800..b5edfeabd 100644 --- a/src/containers/App/App.test.js +++ b/src/containers/App/App.test.js @@ -63,7 +63,7 @@ describe('App', () => { }); it('calls namespaces API in full cluster mode', async () => { - jest.spyOn(API, 'getNamespaces'); + jest.spyOn(API, 'getNamespaces').mockImplementation(() => {}); const { queryByText } = render(); await waitFor(() => queryByText('Tekton resources')); diff --git a/src/utils/index.test.js b/src/utils/index.test.js index 291ba2d85..92a1b2440 100644 --- a/src/utils/index.test.js +++ b/src/utils/index.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2021 The Tekton Authors +Copyright 2019-2022 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -111,7 +111,7 @@ describe('fetchLogsFallback', () => { const stepName = 'fake_stepName'; const stepStatus = { container }; const taskRun = { metadata: { namespace }, status: { podName } }; - jest.spyOn(comms, 'get'); + jest.spyOn(comms, 'get').mockImplementation(() => {}); const fallback = fetchLogsFallback(externalLogsURL); fallback(stepName, stepStatus, taskRun); @@ -193,7 +193,7 @@ describe('getLogsRetriever', () => { it('should handle default logs retriever with external fallback enabled', async () => { const externalLogsURL = 'fake_externalLogsURL'; - jest.spyOn(API, 'getPodLog'); + jest.spyOn(API, 'getPodLog').mockImplementation(() => {}); const onFallback = jest.fn(); const logsRetriever = getLogsRetriever({ externalLogsURL, onFallback }); expect(logsRetriever).toBeDefined(); @@ -212,6 +212,7 @@ describe('getLogsRetriever', () => { jest.spyOn(API, 'getPodLog').mockImplementation(() => { throw new Error(); }); + jest.spyOn(comms, 'get').mockImplementation(() => {}); const onFallback = jest.fn(); const logsRetriever = getLogsRetriever({ externalLogsURL, onFallback }); expect(logsRetriever).toBeDefined();