diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8b5192a..d66a5fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,7 @@ on: branches: - master - release + - pre-release pull_request: jobs: test: @@ -38,8 +39,6 @@ jobs: run: npm ci - name: Lint run: npm run lint - - name: Test unit - run: npm run test:unit - name: Test E2E run: npm run test:e2e id: test-e2e diff --git a/.gitignore b/.gitignore index 96a5178..525d616 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,8 @@ # tests /coverage /mocks -/test/e2e/fixtures/files-watch +/test/e2e/fixtures/temp +/test/e2e/fixtures/mocks.config.js # misc .DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md index acac218..137847d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,6 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [To be deprecated] -- Remove deprecated "/mocks" api path. -- Remove property "name" from behavior model. ## [unreleased] ### Added @@ -14,6 +12,43 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed ### Removed +## [2.0.0] - 2021-02-17 + +### Added +- Add mocks, routes, routes-variants and mock-custom-routes-variants apis + +### Changed +- feat: Move behaviors and fixtures apis under legacy folder +- refactor: Use helper to create routers with same structure +- chore(deps): Update dependencies + +### Removed +- Remove deprecated api paths +- Remove adminApiDeprecatedPaths option. + +### BREAKING CHANGES +- Move behaviors and fixtures apis under legacy folder +- Remove deprecated api paths +- Remove adminApiDeprecatedPaths option. + +## [2.0.0-beta.2] - 2021-02-16 + +### Changed +- chore(deps): Update mocks-server/core dependency. Adapt tests. + +## [2.0.0-beta.1] - 2021-02-14 + +### Added +- Add mocks, routes, routes-variants and mock-custom-routes-variants apis + +### Changed +- Move behaviors and fixtures apis under legacy folder +- refactor: Use helper to create routers with same structure + +### Removed +- Remove deprecated api paths +- Remove adminApiDeprecatedPaths option. + ## [1.5.0] - 2020-12-25 ### Added diff --git a/README.md b/README.md index bdd88fc..1a75d5d 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,11 @@ # [![Mocks Server][logo-url]][website-url] Mocks Server Plugin Admin Api -Plugin for [Mocks Server][website-url] that provides an API REST that allows to change dinamically the current behavior, change delay time, and another [Mocks Server options][options-url]. +Plugin for [Mocks Server][website-url] that provides an API REST that allows to change the current behavior, change delay time, and another [Mocks Server options][options-url]. -This is __very useful when running acceptance tests, as you can change the behavior of the api__ simply making an HTTP request in your tests `before` method, for example. +This is __very useful when running acceptance tests, as you can change the current mock__ simply with a HTTP request in the `before` method of your tests, for example. + +A __client for the administration api__ is also distributed as a separated package: [@mocks-server/admin-api-client](https://www.npmjs.com/package/@mocks-server/admin-api-client). ## Usage @@ -17,27 +19,34 @@ This plugin is included in the [main distribution of the Mocks Server project][m ## Options -* `adminApiPath` - Base path for the administration api. Default is "/admin". You should change it only if there is any conflict with the api you are mocking. -* `adminApiDeprecatedPaths` - Boolean option, disables deprecated "/mocks" api path, which is still enabled by default. +* __`adminApiPath`__ _(String)_: Path for the administration api. Default is `/admin`. You should change it only in case there is any conflict with the api you are mocking. -Read more about [how to define options for the mocks-server plugins here](https://www.mocks-server.org/docs/configuration-options). +Read more about [how to set options in Mocks Server here](https://www.mocks-server.org/docs/configuration-options). ## API Resources Available api resources are: -* `GET` `/admin/about` Returns plugin information. +* `GET` `/admin/about` Returns "plugin-admin-api" information. * Response body example: `{ "version": "1.2.0" }` -* `GET` `/admin/behaviors` Returns behaviors collection. -* `GET` `/admin/behaviors/:id` Returns an specific behavior. -* `GET` `/admin/fixtures` Returns fixtures collection. -* `GET` `/admin/fixtures/:id` Returns an specific fixture. +* `GET` `/admin/mocks` Returns mocks. +* `GET` `/admin/mocks/:id` Returns a specific mock. +* `GET` `/admin/routes` Returns routes collection. +* `GET` `/admin/routes/:id` Returns a specific route. +* `GET` `/admin/routes-variants` Returns routes variants collection. +* `GET` `/admin/routes-variants/:id` Returns a specific route variant. +* `GET` `/admin/mock-custom-routes-variants` Returns an array of currently custom routes variants ids. +* `POST` `/admin/mock-custom-routes-variants` Defines a route variant to be used by current mock. + * Request body example: `{ "id": "users:error" }` +* `DELETE` `/admin/mock-custom-routes-variants` Restore routes variants to those defined in current mock. * `GET` `/admin/settings` Returns current server settings. - * Response body example: `{ "delay": 0, behavior: "foo-behavior", path: "mocks" }` + * Response body example: `{ "delay": 0, mock: "foo-mock", path: "mocks" }` * `PATCH` `/admin/settings` Changes current server settings. * Request body example: `{ "delay": 3000 }` +* `GET` `/admin/alerts` Returns current alerts. +* `GET` `/admin/alerts/:id` Returns a specific alert. The alert `id` is equivalent to the alert `context` _(read the [developing plugins chapter](plugins-developing-plugins.md) for further info about alerts)_. -> Deprecated api resources under "/mocks" api path are still available. +> v1.x deprecated api resources are also still available under the `/legacy` path. ## Contributing diff --git a/jest.config.js b/jest.config.js index 6ab54f4..1ecb0ad 100644 --- a/jest.config.js +++ b/jest.config.js @@ -25,8 +25,8 @@ module.exports = { }, // The glob patterns Jest uses to detect test files - testMatch: ["/test/unit/**/*.spec.js"], - // testMatch: ["/test/unit/**/Plugin.spec.js"], + testMatch: ["/test/e2e/**/*.spec.js"], + // testMatch: ["/test/e2e/**/legacy-behaviors-api.spec.js"], // The test environment that will be used for testing testEnvironment: "node", diff --git a/jest.e2e.config.js b/jest.e2e.config.js deleted file mode 100644 index 165c323..0000000 --- a/jest.e2e.config.js +++ /dev/null @@ -1,16 +0,0 @@ -// For a detailed explanation regarding each configuration property, visit: -// https://jestjs.io/docs/en/configuration.html - -module.exports = { - // Automatically clear mock calls and instances between every test - clearMocks: true, - - testMatch: ["/test/e2e/**/*.spec.js"], - // testMatch: ["/test/e2e/**/stop-plugin.spec.js"], - - // Indicates whether the coverage information should be collected while executing the test - collectCoverage: false, - - // The test environment that will be used for testing - testEnvironment: "node", -}; diff --git a/package-lock.json b/package-lock.json index 0b942f1..d8a05ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,48 +1,41 @@ { "name": "@mocks-server/plugin-admin-api", - "version": "1.5.0", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "dev": true, "requires": { "@babel/highlight": "^7.10.4" } }, "@babel/core": { - "version": "7.12.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz", - "integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==", + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", + "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.1", + "@babel/generator": "^7.12.10", "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.1", - "@babel/parser": "^7.12.3", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.10", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.10", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", "json5": "^2.1.2", "lodash": "^4.17.19", - "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" }, "dependencies": { - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -58,12 +51,12 @@ } }, "@babel/generator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz", - "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", + "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", "dev": true, "requires": { - "@babel/types": "^7.12.1", + "@babel/types": "^7.12.11", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -77,41 +70,41 @@ } }, "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz", + "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" + "@babel/helper-get-function-arity": "^7.12.10", + "@babel/template": "^7.12.7", + "@babel/types": "^7.12.11" } }, "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz", + "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==", "dev": true, "requires": { - "@babel/types": "^7.10.4" + "@babel/types": "^7.12.10" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz", - "integrity": "sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz", + "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==", "dev": true, "requires": { - "@babel/types": "^7.12.1" + "@babel/types": "^7.12.7" } }, "@babel/helper-module-imports": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz", - "integrity": "sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", + "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", "dev": true, "requires": { - "@babel/types": "^7.12.1" + "@babel/types": "^7.12.5" } }, "@babel/helper-module-transforms": { @@ -129,23 +122,15 @@ "@babel/traverse": "^7.12.1", "@babel/types": "^7.12.1", "lodash": "^4.17.19" - }, - "dependencies": { - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - } } }, "@babel/helper-optimise-call-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", - "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz", + "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==", "dev": true, "requires": { - "@babel/types": "^7.10.4" + "@babel/types": "^7.12.10" } }, "@babel/helper-plugin-utils": { @@ -155,15 +140,15 @@ "dev": true }, "@babel/helper-replace-supers": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz", - "integrity": "sha512-zJjTvtNJnCFsCXVi5rUInstLd/EIVNmIKA1Q9ynESmMBWPWd+7sdR+G4/wdu+Mppfep0XLyG2m7EBPvjCeFyrw==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz", + "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.12.1", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1" + "@babel/helper-member-expression-to-functions": "^7.12.7", + "@babel/helper-optimise-call-expression": "^7.12.10", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.11" } }, "@babel/helper-simple-access": { @@ -176,12 +161,12 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz", + "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==", "dev": true, "requires": { - "@babel/types": "^7.11.0" + "@babel/types": "^7.12.11" } }, "@babel/helper-validator-identifier": { @@ -191,14 +176,14 @@ "dev": true }, "@babel/helpers": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.1.tgz", - "integrity": "sha512-9JoDSBGoWtmbay98efmT2+mySkwjzeFeAL9BuWNoVQpkPFQF8SIIFUfY5os9u8wVzglzoiPRSW7cuJmBDUt43g==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz", + "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==", "dev": true, "requires": { "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1" + "@babel/traverse": "^7.12.5", + "@babel/types": "^7.12.5" } }, "@babel/highlight": { @@ -226,9 +211,9 @@ } }, "@babel/parser": { - "version": "7.12.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.3.tgz", - "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", + "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==", "dev": true }, "@babel/plugin-syntax-async-generators": { @@ -330,29 +315,38 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz", + "integrity": "sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", + "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" + "@babel/parser": "^7.12.7", + "@babel/types": "^7.12.7" } }, "@babel/traverse": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.1.tgz", - "integrity": "sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", + "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==", "dev": true, "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.1", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.12.1", - "@babel/types": "^7.12.1", + "@babel/code-frame": "^7.12.11", + "@babel/generator": "^7.12.11", + "@babel/helper-function-name": "^7.12.11", + "@babel/helper-split-export-declaration": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/types": "^7.12.12", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.19" @@ -363,30 +357,24 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true } } }, "@babel/types": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", - "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.12.11", "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" }, "dependencies": { - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", "dev": true } } @@ -419,9 +407,9 @@ } }, "@eslint/eslintrc": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz", - "integrity": "sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", + "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -431,7 +419,7 @@ "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^3.13.1", - "lodash": "^4.17.19", + "lodash": "^4.17.20", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, @@ -465,9 +453,18 @@ } }, "@hapi/hoek": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.0.4.tgz", - "integrity": "sha512-EwaJS7RjoXUZ2cXXKZZxZqieGtc7RbvQhUy8FwDoMQtxWVi14tFjeFCYPZAM1mBCpOpiBpyaZbb9NeHc7eGKgw==" + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.1.1.tgz", + "integrity": "sha512-CAEbWH7OIur6jEOzaai83jq3FmKmv4PmX1JYfs9IrYcGEVI/lyL1EXJGCj7eFVJ0bg5QR8LMxBlEtA+xKiLpFw==" + }, + "@hapi/topo": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", + "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -497,114 +494,103 @@ "dev": true }, "@jest/console": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.1.tgz", - "integrity": "sha512-cjqcXepwC5M+VeIhwT6Xpi/tT4AiNzlIx8SMJ9IihduHnsSrnWNvTBfKIpmqOOCNOPqtbBx6w2JqfoLOJguo8g==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz", + "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==", "dev": true, "requires": { - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^26.6.1", - "jest-util": "^26.6.1", + "jest-message-util": "^26.6.2", + "jest-util": "^26.6.2", "slash": "^3.0.0" } }, "@jest/core": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.1.tgz", - "integrity": "sha512-p4F0pgK3rKnoS9olXXXOkbus1Bsu6fd8pcvLMPsUy4CVXZ8WSeiwQ1lK5hwkCIqJ+amZOYPd778sbPha/S8Srw==", + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz", + "integrity": "sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==", "dev": true, "requires": { - "@jest/console": "^26.6.1", - "@jest/reporters": "^26.6.1", - "@jest/test-result": "^26.6.1", - "@jest/transform": "^26.6.1", - "@jest/types": "^26.6.1", + "@jest/console": "^26.6.2", + "@jest/reporters": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.4", - "jest-changed-files": "^26.6.1", - "jest-config": "^26.6.1", - "jest-haste-map": "^26.6.1", - "jest-message-util": "^26.6.1", + "jest-changed-files": "^26.6.2", + "jest-config": "^26.6.3", + "jest-haste-map": "^26.6.2", + "jest-message-util": "^26.6.2", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.6.1", - "jest-resolve-dependencies": "^26.6.1", - "jest-runner": "^26.6.1", - "jest-runtime": "^26.6.1", - "jest-snapshot": "^26.6.1", - "jest-util": "^26.6.1", - "jest-validate": "^26.6.1", - "jest-watcher": "^26.6.1", + "jest-resolve": "^26.6.2", + "jest-resolve-dependencies": "^26.6.3", + "jest-runner": "^26.6.3", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "jest-watcher": "^26.6.2", "micromatch": "^4.0.2", "p-each-series": "^2.1.0", "rimraf": "^3.0.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } } }, "@jest/environment": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.1.tgz", - "integrity": "sha512-GNvHwkOFJtNgSwdzH9flUPzF9AYAZhUg124CBoQcwcZCM9s5TLz8Y3fMtiaWt4ffbigoetjGk5PU2Dd8nLrSEw==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz", + "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==", "dev": true, "requires": { - "@jest/fake-timers": "^26.6.1", - "@jest/types": "^26.6.1", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", "@types/node": "*", - "jest-mock": "^26.6.1" + "jest-mock": "^26.6.2" } }, "@jest/fake-timers": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.1.tgz", - "integrity": "sha512-T/SkMLgOquenw/nIisBRD6XAYpFir0kNuclYLkse5BpzeDUukyBr+K31xgAo9M0hgjU9ORlekAYPSzc0DKfmKg==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz", + "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==", "dev": true, "requires": { - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "@sinonjs/fake-timers": "^6.0.1", "@types/node": "*", - "jest-message-util": "^26.6.1", - "jest-mock": "^26.6.1", - "jest-util": "^26.6.1" + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" } }, "@jest/globals": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.1.tgz", - "integrity": "sha512-acxXsSguuLV/CeMYmBseefw6apO7NuXqpE+v5r3yD9ye2PY7h1nS20vY7Obk2w6S7eJO4OIAJeDnoGcLC/McEQ==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz", + "integrity": "sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==", "dev": true, "requires": { - "@jest/environment": "^26.6.1", - "@jest/types": "^26.6.1", - "expect": "^26.6.1" + "@jest/environment": "^26.6.2", + "@jest/types": "^26.6.2", + "expect": "^26.6.2" } }, "@jest/reporters": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.1.tgz", - "integrity": "sha512-J6OlXVFY3q1SXWJhjme5i7qT/BAZSikdOK2t8Ht5OS32BDo6KfG5CzIzzIFnAVd82/WWbc9Hb7SJ/jwSvVH9YA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.2.tgz", + "integrity": "sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^26.6.1", - "@jest/test-result": "^26.6.1", - "@jest/transform": "^26.6.1", - "@jest/types": "^26.6.1", + "@jest/console": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", @@ -615,22 +601,22 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.2", - "jest-haste-map": "^26.6.1", - "jest-resolve": "^26.6.1", - "jest-util": "^26.6.1", - "jest-worker": "^26.6.1", + "jest-haste-map": "^26.6.2", + "jest-resolve": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", "node-notifier": "^8.0.0", "slash": "^3.0.0", "source-map": "^0.6.0", "string-length": "^4.0.1", "terminal-link": "^2.0.0", - "v8-to-istanbul": "^6.0.1" + "v8-to-istanbul": "^7.0.0" } }, "@jest/source-map": { - "version": "26.5.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.5.0.tgz", - "integrity": "sha512-jWAw9ZwYHJMe9eZq/WrsHlwF8E3hM9gynlcDpOyCb9bR8wEd9ZNBZCi7/jZyzHxC7t3thZ10gO2IDhu0bPKS5g==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz", + "integrity": "sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==", "dev": true, "requires": { "callsites": "^3.0.0", @@ -639,46 +625,46 @@ } }, "@jest/test-result": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.1.tgz", - "integrity": "sha512-wqAgIerIN2gSdT2A8WeA5+AFh9XQBqYGf8etK143yng3qYd0mF0ie2W5PVmgnjw4VDU6ammI9NdXrKgNhreawg==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz", + "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==", "dev": true, "requires": { - "@jest/console": "^26.6.1", - "@jest/types": "^26.6.1", + "@jest/console": "^26.6.2", + "@jest/types": "^26.6.2", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.1.tgz", - "integrity": "sha512-0csqA/XApZiNeTIPYh6koIDCACSoR6hi29T61tKJMtCZdEC+tF3PoNt7MS0oK/zKC6daBgCbqXxia5ztr/NyCQ==", + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz", + "integrity": "sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==", "dev": true, "requires": { - "@jest/test-result": "^26.6.1", + "@jest/test-result": "^26.6.2", "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.6.1", - "jest-runner": "^26.6.1", - "jest-runtime": "^26.6.1" + "jest-haste-map": "^26.6.2", + "jest-runner": "^26.6.3", + "jest-runtime": "^26.6.3" } }, "@jest/transform": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.1.tgz", - "integrity": "sha512-oNFAqVtqRxZRx6vXL3I4bPKUK0BIlEeaalkwxyQGGI8oXDQBtYQBpiMe5F7qPs4QdvvFYB42gPGIMMcxXaBBxQ==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz", + "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "babel-plugin-istanbul": "^6.0.0", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.6.1", + "jest-haste-map": "^26.6.2", "jest-regex-util": "^26.0.0", - "jest-util": "^26.6.1", + "jest-util": "^26.6.2", "micromatch": "^4.0.2", "pirates": "^4.0.1", "slash": "^3.0.0", @@ -687,9 +673,9 @@ } }, "@jest/types": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.1.tgz", - "integrity": "sha512-ywHavIKNpAVrStiRY5wiyehvcktpijpItvGiK72RAn5ctqmzvPk8OvKnvHeBqa1XdQr959CTWAJMqxI8BTibyg==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", @@ -700,32 +686,72 @@ } }, "@mocks-server/admin-api-paths": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mocks-server/admin-api-paths/-/admin-api-paths-1.1.0.tgz", - "integrity": "sha512-qFcIsRtfD9uXj3Js0qKyKZKUeoCgzcjxZWPw3Xe64bPByE5lrPYlMzVMbmENVLIkQS5aOlVttxOzpG8jHO/DxA==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@mocks-server/admin-api-paths/-/admin-api-paths-2.0.0.tgz", + "integrity": "sha512-UvhMPsF1TCstAIOluEb+P2Y33f60JhiC97kkQTAdPfQcd+dgtX28gGB7+M+t4+72OyFgGfSAUIHawfxiSFvhVA==" }, "@mocks-server/core": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@mocks-server/core/-/core-1.6.0.tgz", - "integrity": "sha512-Gh2C7RGXvs09x7qDArby2XN1G11iOyLY5AcZzSaJXHM59F59NV9E17rNKf5i8S2XJVv1aNA4WO/AqsIfMFDcXQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@mocks-server/core/-/core-2.0.0.tgz", + "integrity": "sha512-qvMLu2DEIWB4GPphUJTqwtGpnB5nKwm5l9l31LAni4biw9Om0GHBF2Ahvw5+5Hz4QlkxLCju4mkHVwX4+rtldA==", "dev": true, "requires": { - "@hapi/boom": "9.1.0", + "@hapi/boom": "9.1.1", "body-parser": "1.19.0", - "commander": "6.2.0", + "commander": "6.2.1", "cors": "2.8.5", "express": "4.17.1", "express-request-id": "1.4.1", - "fs-extra": "9.0.1", + "fs-extra": "9.1.0", + "globule": "1.3.2", "is-promise": "4.0.0", "lodash": "4.17.20", "md5": "2.3.0", - "node-watch": "0.7.0", + "node-watch": "0.7.1", "require-all": "3.0.0", "route-parser": "0.0.5", - "winston": "3.3.3" + "winston": "3.3.3", + "winston-array-transport": "1.0.1" + }, + "dependencies": { + "@hapi/boom": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-9.1.1.tgz", + "integrity": "sha512-VNR8eDbBrOxBgbkddRYIe7+8DZ+vSbV6qlmaN2x7eWjsUjy2VmQgChkOKcVZIeupEZYj+I0dqNg430OhwzagjA==", + "dev": true, + "requires": { + "@hapi/hoek": "9.x.x" + } + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + } } }, + "@sideway/address": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.1.tgz", + "integrity": "sha512-+I5aaQr3m0OAmMr7RQ3fR9zx55sejEYR2BFJaxL+zT3VM2611X0SHvPWIbAUBZVTn/YzYKbV8gJ2oT/QELknfQ==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==", + "dev": true + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "dev": true + }, "@sinonjs/commons": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", @@ -744,20 +770,10 @@ "@sinonjs/commons": "^1.7.0" } }, - "@sinonjs/formatio": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", - "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^5.0.2" - } - }, "@sinonjs/samsam": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.2.0.tgz", - "integrity": "sha512-CaIcyX5cDsjcW/ab7HposFWzV1kC++4HNsfnEdFJa7cP1QIuILAKV+BgfeqRXhcnSAc76r/Rh/O5C+300BwUIw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", "dev": true, "requires": { "@sinonjs/commons": "^1.6.0", @@ -772,9 +788,9 @@ "dev": true }, "@types/babel__core": { - "version": "7.1.10", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.10.tgz", - "integrity": "sha512-x8OM8XzITIMyiwl5Vmo2B1cR1S1Ipkyv4mdlbJjMa1lmuKvKY9FrBbEANIaMlnWn5Rf7uO+rC/VgYabNkE17Hw==", + "version": "7.1.12", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz", + "integrity": "sha512-wMTHiiTiBAAPebqaPiPDLFA4LYPKr6Ph0Xq/6rq1Ur3v66HXyG+clfR9CNETkD7MQS8ZHvpQOtA53DLws5WAEQ==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -794,9 +810,9 @@ } }, "@types/babel__template": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.3.tgz", - "integrity": "sha512-uCoznIPDmnickEi6D0v11SBpW0OuVqHJCa7syXqQHy5uktSCreIlt0iglsCnmvz8yCb38hGcWeseA8cWJSwv5Q==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.0.tgz", + "integrity": "sha512-NTPErx4/FiPCGScH7foPyr+/1Dkzkni+rHiYHHoTjvwou7AQzJkNeD60A9CXRy+ZEN2B1bggmkTMCDb+Mv5k+A==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -804,9 +820,9 @@ } }, "@types/babel__traverse": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.15.tgz", - "integrity": "sha512-Pzh9O3sTK8V6I1olsXpCfj2k/ygO2q1X0vhhnDrEQyYLHZesWz+zMZMVcwXLCYf0U36EtmyYaFGPfXlTtDHe3A==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.0.tgz", + "integrity": "sha512-kSjgDMZONiIfSH1Nxcr5JIRMwUetDki63FSQfpTCz8ogF3Ulqm8+mr5f78dUYs6vMiB6gBusQqfQmBvHZj/lwg==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -846,9 +862,9 @@ } }, "@types/node": { - "version": "14.14.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.5.tgz", - "integrity": "sha512-H5Wn24s/ZOukBmDn03nnGTp18A60ny9AmCwnEcgJiTgSGsCO7k+NWP7zjCCbhlcnVCoI+co52dUAt9GMhOSULw==", + "version": "14.14.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz", + "integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A==", "dev": true }, "@types/normalize-package-data": { @@ -864,9 +880,9 @@ "dev": true }, "@types/prettier": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.5.tgz", - "integrity": "sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.6.tgz", + "integrity": "sha512-6gOkRe7OIioWAXfnO/2lFiv+SJichKVSys1mSsgyrYHSEjk8Ctv4tSR/Odvnu+HWlH2C8j53dahU03XmQdd5fA==", "dev": true }, "@types/stack-utils": { @@ -876,18 +892,18 @@ "dev": true }, "@types/yargs": { - "version": "15.0.9", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.9.tgz", - "integrity": "sha512-HmU8SeIRhZCWcnRskCs36Q1Q00KBV6Cqh/ora8WN1+22dY07AZdn6Gel8QZ3t26XYPImtcL8WV/eqjhVmMEw4g==", + "version": "15.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.12.tgz", + "integrity": "sha512-f+fD/fQAo3BCbCDlrUpznF1A5Zp9rB0noS5vnoormHSIPFKL0Z2DcUJ3Gxp5ytH4uLRNxy7AwYUC9exZzqGMAw==", "dev": true, "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", - "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", + "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", "dev": true }, "abab": { @@ -993,12 +1009,6 @@ } } }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -1078,9 +1088,9 @@ "dev": true }, "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, "async": { @@ -1119,17 +1129,26 @@ "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", "dev": true }, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "dev": true, + "requires": { + "follow-redirects": "^1.10.0" + } + }, "babel-jest": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.1.tgz", - "integrity": "sha512-duMWEOKrSBYRVTTNpL2SipNIWnZOjP77auOBMPQ3zXAdnDbyZQWU8r/RxNWpUf9N6cgPFecQYelYLytTVXVDtA==", + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz", + "integrity": "sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==", "dev": true, "requires": { - "@jest/transform": "^26.6.1", - "@jest/types": "^26.6.1", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", "@types/babel__core": "^7.1.7", "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^26.5.0", + "babel-preset-jest": "^26.6.2", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "slash": "^3.0.0" @@ -1149,9 +1168,9 @@ } }, "babel-plugin-jest-hoist": { - "version": "26.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.5.0.tgz", - "integrity": "sha512-ck17uZFD3CDfuwCLATWZxkkuGGFhMij8quP8CNhwj8ek1mqFgbFzRJ30xwC04LLscj/aKsVFfRST+b5PT7rSuw==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz", + "integrity": "sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -1161,9 +1180,9 @@ } }, "babel-preset-current-node-syntax": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.4.tgz", - "integrity": "sha512-5/INNCYhUGqw7VbVjT/hb3ucjgkVHKXY7lX3ZjlN4gm565VyFmJUrJ/h+h16ECVB38R/9SF6aACydpKMLZ/c9w==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, "requires": { "@babel/plugin-syntax-async-generators": "^7.8.4", @@ -1176,17 +1195,18 @@ "@babel/plugin-syntax-numeric-separator": "^7.8.3", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" } }, "babel-preset-jest": { - "version": "26.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.5.0.tgz", - "integrity": "sha512-F2vTluljhqkiGSJGBg/jOruA8vIIIL11YrxRcO7nviNTMbbofPSHwnm8mgP7d/wS7wRSexRoI6X1A6T74d4LQA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz", + "integrity": "sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^26.5.0", - "babel-preset-current-node-syntax": "^0.1.3" + "babel-plugin-jest-hoist": "^26.6.2", + "babel-preset-current-node-syntax": "^1.0.0" } }, "balanced-match": { @@ -1259,12 +1279,6 @@ "tweetnacl": "^0.14.3" } }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -1461,9 +1475,9 @@ "dev": true }, "cjs-module-lexer": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.4.3.tgz", - "integrity": "sha512-5RLK0Qfs0PNDpEyBXIr3bIT1Muw3ojSlvpw6dAmkUcO0+uTrsBn7GuEIgx40u+OzbCBLDta7nvmud85P4EmTsQ==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz", + "integrity": "sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==", "dev": true }, "class-utils": { @@ -1523,12 +1537,6 @@ "color-convert": "^2.0.1" } }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1544,18 +1552,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, "slice-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", @@ -1566,17 +1562,6 @@ "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } } } }, @@ -1589,31 +1574,6 @@ "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - } } }, "co": { @@ -1789,6 +1749,15 @@ "yaml": "^1.10.0" } }, + "cross-fetch": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.6.tgz", + "integrity": "sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ==", + "dev": true, + "requires": { + "node-fetch": "2.6.1" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1972,9 +1941,9 @@ "dev": true }, "diff-sequences": { - "version": "26.5.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.5.0.tgz", - "integrity": "sha512-ZXx86srb/iYy6jG71k++wBN9P9J05UNQ5hQHQd9MtMPvcqXPx/vKU69jfHV637D00Q2gSgPk2D+jSx3l1lDW/Q==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", + "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", "dev": true }, "doctrine": { @@ -2025,9 +1994,9 @@ "dev": true }, "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "enabled": { @@ -2134,13 +2103,13 @@ } }, "eslint": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.12.1.tgz", - "integrity": "sha512-HlMTEdr/LicJfN08LB3nM1rRYliDXOmfoO4vj39xN6BLpFzF00hbwBoqHk8UcJ2M/3nlARZWy/mslvGEuZFvsg==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.20.0.tgz", + "integrity": "sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.2.1", + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.3.0", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -2150,10 +2119,10 @@ "eslint-scope": "^5.1.1", "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.0", - "esquery": "^1.2.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", + "file-entry-cache": "^6.0.0", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", "globals": "^12.1.0", @@ -2164,7 +2133,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.19", + "lodash": "^4.17.20", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -2173,19 +2142,16 @@ "semver": "^7.2.1", "strip-ansi": "^6.0.0", "strip-json-comments": "^3.1.0", - "table": "^5.2.3", + "table": "^6.0.4", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" } }, "eslint-config-prettier": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz", - "integrity": "sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==", - "dev": true, - "requires": { - "get-stdin": "^6.0.0" - } + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz", + "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==", + "dev": true }, "eslint-plugin-no-only-tests": { "version": "2.4.0", @@ -2194,9 +2160,9 @@ "dev": true }, "eslint-plugin-prettier": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", - "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz", + "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" @@ -2236,13 +2202,13 @@ "dev": true }, "espree": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", - "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", "dev": true, "requires": { "acorn": "^7.4.0", - "acorn-jsx": "^5.2.0", + "acorn-jsx": "^5.3.1", "eslint-visitor-keys": "^1.3.0" }, "dependencies": { @@ -2261,9 +2227,9 @@ "dev": true }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -2440,16 +2406,16 @@ } }, "expect": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.1.tgz", - "integrity": "sha512-BRfxIBHagghMmr1D2MRY0Qv5d3Nc8HCqgbDwNXw/9izmM5eBb42a2YjLKSbsqle76ozGkAEPELQX4IdNHAKRNA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz", + "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==", "dev": true, "requires": { - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "ansi-styles": "^4.0.0", "jest-get-type": "^26.3.0", - "jest-matcher-utils": "^26.6.1", - "jest-message-util": "^26.6.1", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", "jest-regex-util": "^26.0.0" }, "dependencies": { @@ -2703,12 +2669,12 @@ } }, "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", + "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", "dev": true, "requires": { - "flat-cache": "^2.0.1" + "flat-cache": "^3.0.4" } }, "fill-range": { @@ -2760,29 +2726,28 @@ } }, "find-versions": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", - "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", + "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", "dev": true, "requires": { - "semver-regex": "^2.0.0" + "semver-regex": "^3.1.2" } }, "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" } }, "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", "dev": true }, "fn.name": { @@ -2791,6 +2756,12 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", "dev": true }, + "follow-redirects": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz", + "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==", + "dev": true + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -2834,15 +2805,15 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "fs-extra": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", - "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, "requires": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", - "universalify": "^1.0.0" + "universalify": "^2.0.0" } }, "fs.realpath": { @@ -2852,9 +2823,9 @@ "dev": true }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.0.tgz", + "integrity": "sha512-SmvpCnCbknBKrMhodrIdwGBhn8kAEp8VUyrcH13clA5cq1C5fyN2+b3lQBdjpO1X/yJrTNySaggyYA62h+28ug==", "dev": true, "optional": true }, @@ -2871,9 +2842,9 @@ "dev": true }, "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, "get-caller-file": { @@ -2894,12 +2865,6 @@ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true }, - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true - }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -2956,6 +2921,17 @@ "type-fest": "^0.8.1" } }, + "globule": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", + "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", @@ -3103,21 +3079,69 @@ "dev": true }, "husky": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz", - "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==", + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz", + "integrity": "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==", "dev": true, "requires": { "chalk": "^4.0.0", "ci-info": "^2.0.0", "compare-versions": "^3.6.0", "cosmiconfig": "^7.0.0", - "find-versions": "^3.2.0", + "find-versions": "^4.0.0", "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^4.2.0", + "pkg-dir": "^5.0.0", "please-upgrade-node": "^3.2.0", "slash": "^3.0.0", "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + } + } } }, "iconv-lite": { @@ -3234,9 +3258,9 @@ } }, "is-core-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz", - "integrity": "sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", "dev": true, "requires": { "has": "^1.0.3" @@ -3301,9 +3325,9 @@ "dev": true }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "is-generator-fn": { @@ -3488,33 +3512,33 @@ } }, "jest": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.1.tgz", - "integrity": "sha512-f+ahfqw3Ffy+9vA7sWFGpTmhtKEMsNAZiWBVXDkrpIO73zIz22iimjirnV78kh/eWlylmvLh/0WxHN6fZraZdA==", + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz", + "integrity": "sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==", "dev": true, "requires": { - "@jest/core": "^26.6.1", + "@jest/core": "^26.6.3", "import-local": "^3.0.2", - "jest-cli": "^26.6.1" + "jest-cli": "^26.6.3" }, "dependencies": { "jest-cli": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.1.tgz", - "integrity": "sha512-aPLoEjlwFrCWhiPpW5NUxQA1X1kWsAnQcQ0SO/fHsCvczL3W75iVAcH9kP6NN+BNqZcHNEvkhxT5cDmBfEAh+w==", + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz", + "integrity": "sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==", "dev": true, "requires": { - "@jest/core": "^26.6.1", - "@jest/test-result": "^26.6.1", - "@jest/types": "^26.6.1", + "@jest/core": "^26.6.3", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.4", "import-local": "^3.0.2", "is-ci": "^2.0.0", - "jest-config": "^26.6.1", - "jest-util": "^26.6.1", - "jest-validate": "^26.6.1", + "jest-config": "^26.6.3", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", "prompts": "^2.0.1", "yargs": "^15.4.1" } @@ -3522,20 +3546,20 @@ } }, "jest-changed-files": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.1.tgz", - "integrity": "sha512-NhSdZ5F6b/rIN5V46x1l31vrmukD/bJUXgYAY8VtP1SknYdJwjYDRxuLt7Z8QryIdqCjMIn2C0Cd98EZ4umo8Q==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.2.tgz", + "integrity": "sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==", "dev": true, "requires": { - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "execa": "^4.0.0", "throat": "^5.0.0" }, "dependencies": { "execa": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", - "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, "requires": { "cross-spawn": "^7.0.0", @@ -3576,41 +3600,41 @@ } }, "jest-config": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.1.tgz", - "integrity": "sha512-mtJzIynIwW1d1nMlKCNCQiSgWaqFn8cH/fOSNY97xG7Y9tBCZbCSuW2GTX0RPmceSJGO7l27JgwC18LEg0Vg+g==", + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz", + "integrity": "sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^26.6.1", - "@jest/types": "^26.6.1", - "babel-jest": "^26.6.1", + "@jest/test-sequencer": "^26.6.3", + "@jest/types": "^26.6.2", + "babel-jest": "^26.6.3", "chalk": "^4.0.0", "deepmerge": "^4.2.2", "glob": "^7.1.1", "graceful-fs": "^4.2.4", - "jest-environment-jsdom": "^26.6.1", - "jest-environment-node": "^26.6.1", + "jest-environment-jsdom": "^26.6.2", + "jest-environment-node": "^26.6.2", "jest-get-type": "^26.3.0", - "jest-jasmine2": "^26.6.1", + "jest-jasmine2": "^26.6.3", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.6.1", - "jest-util": "^26.6.1", - "jest-validate": "^26.6.1", + "jest-resolve": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", "micromatch": "^4.0.2", - "pretty-format": "^26.6.1" + "pretty-format": "^26.6.2" } }, "jest-diff": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.1.tgz", - "integrity": "sha512-BBNy/zin2m4kG5In126O8chOBxLLS/XMTuuM2+YhgyHk87ewPzKTuTJcqj3lOWOi03NNgrl+DkMeV/exdvG9gg==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", + "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^26.5.0", + "diff-sequences": "^26.6.2", "jest-get-type": "^26.3.0", - "pretty-format": "^26.6.1" + "pretty-format": "^26.6.2" } }, "jest-docblock": { @@ -3623,45 +3647,45 @@ } }, "jest-each": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.1.tgz", - "integrity": "sha512-gSn8eB3buchuq45SU7pLB7qmCGax1ZSxfaWuEFblCyNMtyokYaKFh9dRhYPujK6xYL57dLIPhLKatjmB5XWzGA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz", + "integrity": "sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==", "dev": true, "requires": { - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "chalk": "^4.0.0", "jest-get-type": "^26.3.0", - "jest-util": "^26.6.1", - "pretty-format": "^26.6.1" + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2" } }, "jest-environment-jsdom": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.1.tgz", - "integrity": "sha512-A17RiXuHYNVlkM+3QNcQ6n5EZyAc6eld8ra9TW26luounGWpku4tj03uqRgHJCI1d4uHr5rJiuCH5JFRtdmrcA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz", + "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==", "dev": true, "requires": { - "@jest/environment": "^26.6.1", - "@jest/fake-timers": "^26.6.1", - "@jest/types": "^26.6.1", + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", "@types/node": "*", - "jest-mock": "^26.6.1", - "jest-util": "^26.6.1", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2", "jsdom": "^16.4.0" } }, "jest-environment-node": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.1.tgz", - "integrity": "sha512-YffaCp6h0j1kbcf1NVZ7umC6CPgD67YS+G1BeornfuSkx5s3xdhuwG0DCxSiHPXyT81FfJzA1L7nXvhq50OWIg==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz", + "integrity": "sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==", "dev": true, "requires": { - "@jest/environment": "^26.6.1", - "@jest/fake-timers": "^26.6.1", - "@jest/types": "^26.6.1", + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", "@types/node": "*", - "jest-mock": "^26.6.1", - "jest-util": "^26.6.1" + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" } }, "jest-get-type": { @@ -3671,12 +3695,12 @@ "dev": true }, "jest-haste-map": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.1.tgz", - "integrity": "sha512-9kPafkv0nX6ta1PrshnkiyhhoQoFWncrU/uUBt3/AP1r78WSCU5iLceYRTwDvJl67H3RrXqSlSVDDa/AsUB7OQ==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz", + "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==", "dev": true, "requires": { - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "@types/graceful-fs": "^4.1.2", "@types/node": "*", "anymatch": "^3.0.3", @@ -3684,85 +3708,86 @@ "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", "jest-regex-util": "^26.0.0", - "jest-serializer": "^26.5.0", - "jest-util": "^26.6.1", - "jest-worker": "^26.6.1", + "jest-serializer": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", "micromatch": "^4.0.2", "sane": "^4.0.3", "walker": "^1.0.7" } }, "jest-jasmine2": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.1.tgz", - "integrity": "sha512-2uYdT32o/ZzSxYAPduAgokO8OlAL1YdG/9oxcEY138EDNpIK5XRRJDaGzTZdIBWSxk0aR8XxN44FvfXtHB+Fiw==", + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz", + "integrity": "sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^26.6.1", - "@jest/source-map": "^26.5.0", - "@jest/test-result": "^26.6.1", - "@jest/types": "^26.6.1", + "@jest/environment": "^26.6.2", + "@jest/source-map": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "expect": "^26.6.1", + "expect": "^26.6.2", "is-generator-fn": "^2.0.0", - "jest-each": "^26.6.1", - "jest-matcher-utils": "^26.6.1", - "jest-message-util": "^26.6.1", - "jest-runtime": "^26.6.1", - "jest-snapshot": "^26.6.1", - "jest-util": "^26.6.1", - "pretty-format": "^26.6.1", + "jest-each": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2", "throat": "^5.0.0" } }, "jest-leak-detector": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.1.tgz", - "integrity": "sha512-j9ZOtJSJKlHjrs4aIxWjiQUjyrffPdiAQn2Iw0916w7qZE5Lk0T2KhIH6E9vfhzP6sw0Q0jtnLLb4vQ71o1HlA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz", + "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==", "dev": true, "requires": { "jest-get-type": "^26.3.0", - "pretty-format": "^26.6.1" + "pretty-format": "^26.6.2" } }, "jest-matcher-utils": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.1.tgz", - "integrity": "sha512-9iu3zrsYlUnl8pByhREF9rr5eYoiEb1F7ymNKg6lJr/0qD37LWS5FSW/JcoDl8UdMX2+zAzabDs7sTO+QFKjCg==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz", + "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^26.6.1", + "jest-diff": "^26.6.2", "jest-get-type": "^26.3.0", - "pretty-format": "^26.6.1" + "pretty-format": "^26.6.2" } }, "jest-message-util": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.1.tgz", - "integrity": "sha512-cqM4HnqncIebBNdTKrBoWR/4ufHTll0pK/FWwX0YasK+TlBQEMqw3IEdynuuOTjDPFO3ONlFn37280X48beByw==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz", + "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "micromatch": "^4.0.2", + "pretty-format": "^26.6.2", "slash": "^3.0.0", "stack-utils": "^2.0.2" } }, "jest-mock": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.1.tgz", - "integrity": "sha512-my0lPTBu1awY8iVG62sB2sx9qf8zxNDVX+5aFgoB8Vbqjb6LqIOsfyFA8P1z6H2IsqMbvOX9oCJnK67Y3yUIMA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", "dev": true, "requires": { - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "@types/node": "*" } }, @@ -3779,99 +3804,99 @@ "dev": true }, "jest-resolve": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.1.tgz", - "integrity": "sha512-hiHfQH6rrcpAmw9xCQ0vD66SDuU+7ZulOuKwc4jpbmFFsz0bQG/Ib92K+9/489u5rVw0btr/ZhiHqBpmkbCvuQ==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz", + "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==", "dev": true, "requires": { - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^26.6.1", + "jest-util": "^26.6.2", "read-pkg-up": "^7.0.1", "resolve": "^1.18.1", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.1.tgz", - "integrity": "sha512-MN6lufbZJ3RBfTnJesZtHu3hUCBqPdHRe2+FhIt0yiqJ3fMgzWRqMRQyN/d/QwOE7KXwAG2ekZutbPhuD7s51A==", + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz", + "integrity": "sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==", "dev": true, "requires": { - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "jest-regex-util": "^26.0.0", - "jest-snapshot": "^26.6.1" + "jest-snapshot": "^26.6.2" } }, "jest-runner": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.1.tgz", - "integrity": "sha512-DmpNGdgsbl5s0FGkmsInmqnmqCtliCSnjWA2TFAJS1m1mL5atwfPsf+uoZ8uYQ2X0uDj4NM+nPcDnUpbNTRMBA==", + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz", + "integrity": "sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==", "dev": true, "requires": { - "@jest/console": "^26.6.1", - "@jest/environment": "^26.6.1", - "@jest/test-result": "^26.6.1", - "@jest/types": "^26.6.1", + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.7.1", "exit": "^0.1.2", "graceful-fs": "^4.2.4", - "jest-config": "^26.6.1", + "jest-config": "^26.6.3", "jest-docblock": "^26.0.0", - "jest-haste-map": "^26.6.1", - "jest-leak-detector": "^26.6.1", - "jest-message-util": "^26.6.1", - "jest-resolve": "^26.6.1", - "jest-runtime": "^26.6.1", - "jest-util": "^26.6.1", - "jest-worker": "^26.6.1", + "jest-haste-map": "^26.6.2", + "jest-leak-detector": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", "source-map-support": "^0.5.6", "throat": "^5.0.0" } }, "jest-runtime": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.1.tgz", - "integrity": "sha512-7uOCNeezXDWgjEyzYbRN2ViY7xNZzusNVGAMmU0UHRUNXuY4j4GBHKGMqPo/cBPZA9bSYp+lwK2DRRBU5Dv6YQ==", - "dev": true, - "requires": { - "@jest/console": "^26.6.1", - "@jest/environment": "^26.6.1", - "@jest/fake-timers": "^26.6.1", - "@jest/globals": "^26.6.1", - "@jest/source-map": "^26.5.0", - "@jest/test-result": "^26.6.1", - "@jest/transform": "^26.6.1", - "@jest/types": "^26.6.1", + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz", + "integrity": "sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==", + "dev": true, + "requires": { + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/globals": "^26.6.2", + "@jest/source-map": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", "@types/yargs": "^15.0.0", "chalk": "^4.0.0", - "cjs-module-lexer": "^0.4.2", + "cjs-module-lexer": "^0.6.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.4", - "jest-config": "^26.6.1", - "jest-haste-map": "^26.6.1", - "jest-message-util": "^26.6.1", - "jest-mock": "^26.6.1", + "jest-config": "^26.6.3", + "jest-haste-map": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.6.1", - "jest-snapshot": "^26.6.1", - "jest-util": "^26.6.1", - "jest-validate": "^26.6.1", + "jest-resolve": "^26.6.2", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", "slash": "^3.0.0", "strip-bom": "^4.0.0", "yargs": "^15.4.1" } }, "jest-serializer": { - "version": "26.5.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.5.0.tgz", - "integrity": "sha512-+h3Gf5CDRlSLdgTv7y0vPIAoLgX/SI7T4v6hy+TEXMgYbv+ztzbg5PSN6mUXAT/hXYHvZRWm+MaObVfqkhCGxA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz", + "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==", "dev": true, "requires": { "@types/node": "*", @@ -3879,36 +3904,36 @@ } }, "jest-snapshot": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.1.tgz", - "integrity": "sha512-JA7bZp7HRTIJYAi85pJ/OZ2eur2dqmwIToA5/6d7Mn90isGEfeF9FvuhDLLEczgKP1ihreBzrJ6Vr7zteP5JNA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz", + "integrity": "sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==", "dev": true, "requires": { "@babel/types": "^7.0.0", - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "@types/babel__traverse": "^7.0.4", "@types/prettier": "^2.0.0", "chalk": "^4.0.0", - "expect": "^26.6.1", + "expect": "^26.6.2", "graceful-fs": "^4.2.4", - "jest-diff": "^26.6.1", + "jest-diff": "^26.6.2", "jest-get-type": "^26.3.0", - "jest-haste-map": "^26.6.1", - "jest-matcher-utils": "^26.6.1", - "jest-message-util": "^26.6.1", - "jest-resolve": "^26.6.1", + "jest-haste-map": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", "natural-compare": "^1.4.0", - "pretty-format": "^26.6.1", + "pretty-format": "^26.6.2", "semver": "^7.3.2" } }, "jest-util": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.1.tgz", - "integrity": "sha512-xCLZUqVoqhquyPLuDXmH7ogceGctbW8SMyQVjD9o+1+NPWI7t0vO08udcFLVPLgKWcvc+zotaUv/RuaR6l8HIA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", + "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", "dev": true, "requires": { - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -3917,46 +3942,46 @@ } }, "jest-validate": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.1.tgz", - "integrity": "sha512-BEFpGbylKocnNPZULcnk+TGaz1oFZQH/wcaXlaXABbu0zBwkOGczuWgdLucUouuQqn7VadHZZeTvo8VSFDLMOA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz", + "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==", "dev": true, "requires": { - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "camelcase": "^6.0.0", "chalk": "^4.0.0", "jest-get-type": "^26.3.0", "leven": "^3.1.0", - "pretty-format": "^26.6.1" + "pretty-format": "^26.6.2" }, "dependencies": { "camelcase": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.1.0.tgz", - "integrity": "sha512-WCMml9ivU60+8rEJgELlFp1gxFcEGxwYleE3bziHEDeqsqAWGHdimB7beBFGjLzVNgPGyDsfgXLQEYMpmIFnVQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", "dev": true } } }, "jest-watcher": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.1.tgz", - "integrity": "sha512-0LBIPPncNi9CaLKK15bnxyd2E8OMl4kJg0PTiNOI+MXztXw1zVdtX/x9Pr6pXaQYps+eS/ts43O4+HByZ7yJSw==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz", + "integrity": "sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==", "dev": true, "requires": { - "@jest/test-result": "^26.6.1", - "@jest/types": "^26.6.1", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-util": "^26.6.1", + "jest-util": "^26.6.2", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.1.tgz", - "integrity": "sha512-R5IE3qSGz+QynJx8y+ICEkdI2OJ3RJjRQVEyCcFAd3yVhQSEtquziPO29Mlzgn07LOVE8u8jhJ1FqcwegiXWOw==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", "dev": true, "requires": { "@types/node": "*", @@ -3981,6 +4006,19 @@ } } }, + "joi": { + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.0.tgz", + "integrity": "sha512-F4WiW2xaV6wc1jxete70Rw4V/VuMd6IN+a5ilZsxG4uYtUXWu2kq9W5P2dz30e7Gmw8RCbY/u/uk+dMPma9tAg==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.0", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4096,13 +4134,13 @@ } }, "jsonfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", - "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, "requires": { "graceful-fs": "^4.1.6", - "universalify": "^1.0.0" + "universalify": "^2.0.0" } }, "jsprim": { @@ -4164,20 +4202,20 @@ "dev": true }, "lint-staged": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.5.0.tgz", - "integrity": "sha512-gjC9+HGkBubOF+Yyoj9pd52Qfm/kYB+dRX1UOgWjHKvSDYl+VHkZXlBMlqSZa2cH3Kp5/uNL480sV6e2dTgXSg==", + "version": "10.5.4", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.5.4.tgz", + "integrity": "sha512-EechC3DdFic/TdOPgj/RB3FicqE6932LTHCUm0Y2fsD9KGlLB+RwJl2q1IYBIvEsKzDOgn0D4gll+YxG5RsrKg==", "dev": true, "requires": { "chalk": "^4.1.0", "cli-truncate": "^2.1.0", - "commander": "^6.0.0", + "commander": "^6.2.0", "cosmiconfig": "^7.0.0", - "debug": "^4.1.1", + "debug": "^4.2.0", "dedent": "^0.7.0", "enquirer": "^2.3.6", - "execa": "^4.0.3", - "listr2": "^2.6.0", + "execa": "^4.1.0", + "listr2": "^3.2.2", "log-symbols": "^4.0.0", "micromatch": "^4.0.2", "normalize-path": "^3.0.0", @@ -4187,9 +4225,9 @@ }, "dependencies": { "execa": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", - "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, "requires": { "cross-spawn": "^7.0.0", @@ -4230,9 +4268,9 @@ } }, "listr2": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-2.6.2.tgz", - "integrity": "sha512-6x6pKEMs8DSIpA/tixiYY2m/GcbgMplMVmhQAaLFxEtNSKLeWTGjtmU57xvv6QCm2XcqzyNXL/cTSVf4IChCRA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.3.1.tgz", + "integrity": "sha512-8Zoxe7s/8nNr4bJ8bdAduHD8uJce+exmMmUWTXlq0WuUdffnH3muisHPHPFtW2vvOfohIsq7FGCaguUxN/h3Iw==", "dev": true, "requires": { "chalk": "^4.1.0", @@ -4241,8 +4279,46 @@ "indent-string": "^4.0.0", "log-update": "^4.0.0", "p-map": "^4.0.0", - "rxjs": "^6.6.2", - "through": "^2.3.8" + "rxjs": "^6.6.3", + "through": "^2.3.8", + "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" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } } }, "locate-path": { @@ -4291,55 +4367,6 @@ "cli-cursor": "^3.1.0", "slice-ansi": "^4.0.0", "wrap-ansi": "^6.2.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" - } - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - } } }, "logform": { @@ -4500,15 +4527,6 @@ } } }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -4563,6 +4581,12 @@ "path-to-regexp": "^1.7.0" } }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -4576,9 +4600,9 @@ "dev": true }, "node-notifier": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.0.tgz", - "integrity": "sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.1.tgz", + "integrity": "sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA==", "dev": true, "optional": true, "requires": { @@ -4591,18 +4615,18 @@ }, "dependencies": { "uuid": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", - "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, "optional": true } } }, "node-watch": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.0.tgz", - "integrity": "sha512-OOBiglke5SlRQT5WYfwXTmYqTfXjcTNBHpalyHLtLxDpQYVpVRkJqabcch1kmwJsjV/J4OZuzEafeb4soqtFZA==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.1.tgz", + "integrity": "sha512-UWblPYuZYrkCQCW5PxAwYSxaELNBLUckrTBBk8xr1/bUgyOkYYTsUcV4e3ytcazFEOyiRyiUrsG37pu6I0I05g==", "dev": true }, "normalize-package-data": { @@ -4771,9 +4795,9 @@ } }, "p-each-series": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz", - "integrity": "sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", + "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", "dev": true }, "p-finally": { @@ -4952,9 +4976,9 @@ "dev": true }, "prettier": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", - "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", "dev": true }, "prettier-linter-helpers": { @@ -4967,12 +4991,12 @@ } }, "pretty-format": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.1.tgz", - "integrity": "sha512-MeqqsP5PYcRBbGMvwzsyBdmAJ4EFX7pWFyl7x4+dMVg5pE0ZDdBIvEH2ergvIO+Gvwv1wh64YuOY9y5LuyY/GA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", "dev": true, "requires": { - "@jest/types": "^26.6.1", + "@jest/types": "^26.6.2", "ansi-regex": "^5.0.0", "ansi-styles": "^4.0.0", "react-is": "^17.0.1" @@ -5207,35 +5231,6 @@ } } }, - "request-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", - "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.0", - "request-promise-core": "1.1.4", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - }, - "dependencies": { - "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", - "dev": true - }, - "request-promise-core": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", - "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", - "dev": true, - "requires": { - "lodash": "^4.17.19" - } - } - } - }, "request-promise-core": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", @@ -5243,14 +5238,6 @@ "dev": true, "requires": { "lodash": "^4.17.19" - }, - "dependencies": { - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - } } }, "request-promise-native": { @@ -5276,6 +5263,12 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", @@ -5283,12 +5276,12 @@ "dev": true }, "resolve": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", - "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", "dev": true, "requires": { - "is-core-module": "^2.0.0", + "is-core-module": "^2.1.0", "path-parse": "^1.0.6" } }, @@ -5338,9 +5331,9 @@ "dev": true }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { "glob": "^7.1.3" @@ -5549,9 +5542,9 @@ "dev": true }, "semver-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", - "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.2.tgz", + "integrity": "sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA==", "dev": true }, "send": { @@ -5682,15 +5675,14 @@ } }, "sinon": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.0.tgz", - "integrity": "sha512-eSNXz1XMcGEMHw08NJXSyTHIu6qTCOiN8x9ODACmZpNQpr0aXTBXBnI4xTzQzR+TEpOmLiKowGf9flCuKIzsbw==", + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", + "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", "dev": true, "requires": { "@sinonjs/commons": "^1.8.1", "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.2.0", + "@sinonjs/samsam": "^5.3.1", "diff": "^4.0.2", "nise": "^4.0.4", "supports-color": "^7.1.0" @@ -5726,14 +5718,40 @@ "dev": true }, "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.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" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } } }, "snapdragon": { @@ -5926,9 +5944,9 @@ } }, "spdx-license-ids": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", - "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", "dev": true }, "split-string": { @@ -5970,9 +5988,9 @@ "dev": true }, "stack-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.2.tgz", - "integrity": "sha512-0H7QK2ECz3fyZMzQ8rH0j2ykpfbnd20BFtfg/SqVC2+sCTtcw0aDTGB7dk+de4U4uUeuz6nOtJcrkFFLG1B0Rg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", "dev": true, "requires": { "escape-string-regexp": "^2.0.0" @@ -6035,25 +6053,14 @@ } }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "dependencies": { - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "string_decoder": { @@ -6168,15 +6175,41 @@ "dev": true }, "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", + "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", "dev": true, "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" + "ajv": "^7.0.2", + "lodash": "^4.17.20", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0" + }, + "dependencies": { + "ajv": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.4.tgz", + "integrity": "sha512-xzzzaqgEQfmuhbhAoqjJ8T/1okb6gAzXn/eQRNpAN1AEUoHJTNF9xCDRTtf/s3SKldtZfa+RJeTs+BQq+eZ/sw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } } }, "terminal-link": { @@ -6309,12 +6342,6 @@ "punycode": "^2.1.1" } }, - "tree-kill-sync": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tree-kill-sync/-/tree-kill-sync-1.0.0.tgz", - "integrity": "sha1-1LrZklYR55KXmjrcFetgBMHVqa0=", - "dev": true - }, "triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", @@ -6409,9 +6436,9 @@ } }, "universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true }, "unpipe": { @@ -6504,9 +6531,9 @@ "dev": true }, "v8-to-istanbul": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-6.0.1.tgz", - "integrity": "sha512-PzM1WlqquhBvsV+Gco6WSFeg1AGdD53ccMRkFeyHRE/KRZaVacPOmQYP3EeVgDBtKD2BJ8kgynBQ5OtKiHCH+w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.0.tgz", + "integrity": "sha512-uXUVqNUCLa0AH1vuVxzi+MI4RfxEOKt9pBgKwHbgH7st8Kv2P1m+jvWNnektzBh5QShF3ODgKmUFCf38LnVz1g==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.1", @@ -6566,6 +6593,19 @@ "xml-name-validator": "^3.0.0" } }, + "wait-on": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-5.2.1.tgz", + "integrity": "sha512-H2F986kNWMU9hKlI9l/ppO6tN8ZSJd35yBljMLa1/vjzWP++Qh6aXyt77/u7ySJFZQqBtQxnvm/xgG48AObXcw==", + "dev": true, + "requires": { + "axios": "^0.21.1", + "joi": "^17.3.0", + "lodash": "^4.17.20", + "minimist": "^1.2.5", + "rxjs": "^6.6.3" + } + }, "walker": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", @@ -6653,6 +6693,15 @@ } } }, + "winston-array-transport": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/winston-array-transport/-/winston-array-transport-1.0.1.tgz", + "integrity": "sha512-LfDPpViBtbO8N54YigOTTvPjr9ZESianNv5h2WT9Tr5U1O7bqEr8qhLZhHUhK5XJVWGINpQq/FubY1HlnZRjjQ==", + "dev": true, + "requires": { + "winston-transport": "^4.3.0" + } + }, "winston-transport": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", @@ -6729,29 +6778,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } } } }, @@ -6761,15 +6787,6 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, "write-file-atomic": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", @@ -6783,9 +6800,9 @@ } }, "ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.2.tgz", + "integrity": "sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA==", "dev": true }, "xml-name-validator": { @@ -6801,9 +6818,9 @@ "dev": true }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", "dev": true }, "yaml": { @@ -6829,31 +6846,6 @@ "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - } } }, "yargs-parser": { @@ -6865,6 +6857,12 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index 3153f4e..5251094 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@mocks-server/plugin-admin-api", - "version": "1.5.0", - "description": "Plugin for Mocks Server. Provides a REST API for administrating settings, fixtures and behaviors", + "version": "2.0.0", + "description": "Mocks Server plugin providing a REST API for administration", "keywords": [ "mocks-server-plugin", "administration", @@ -26,35 +26,29 @@ "scripts": { "lint": "eslint *.js src test", "lint-staged": "lint-staged", - "test": "jest", - "test:e2e": "jest --config=jest.e2e.config.js --runInBand", - "test:unit": "npm run test" + "test:e2e": "jest --runInBand" }, "peerDependencies": { - "@mocks-server/core": ">=1.3.0" + "@mocks-server/core": "2.x" }, "dependencies": { - "@mocks-server/admin-api-paths": "1.1.0", + "@mocks-server/admin-api-paths": "2.0.0", "@hapi/boom": "9.1.0", "express": "4.17.1" }, "devDependencies": { - "@mocks-server/core": "1.6.0", - "eslint": "7.12.1", + "@mocks-server/core": "2.0.0", + "cross-fetch": "3.0.6", + "eslint": "7.20.0", "eslint-plugin-no-only-tests": "2.4.0", - "eslint-config-prettier": "6.15.0", - "eslint-plugin-prettier": "3.1.4", - "fs-extra": "9.0.1", - "husky": "4.3.0", - "is-promise": "4.0.0", - "jest": "26.6.1", - "lint-staged": "10.5.0", - "prettier": "2.1.2", - "request": "2.88.2", - "request-promise": "4.2.6", - "sinon": "9.2.0", - "strip-ansi": "6.0.0", - "tree-kill-sync": "1.0.0" + "eslint-config-prettier": "7.2.0", + "eslint-plugin-prettier": "3.3.1", + "husky": "4.3.8", + "jest": "26.6.3", + "lint-staged": "10.5.4", + "prettier": "2.2.1", + "sinon": "9.2.4", + "wait-on": "5.2.1" }, "lint-staged": { "src/**/*.js": "eslint", diff --git a/sonar-project.properties b/sonar-project.properties index fb6c46d..6521a51 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,10 +1,10 @@ sonar.organization=mocks-server sonar.projectKey=mocks-server-plugin-admin-api -sonar.projectVersion=1.5.0 +sonar.projectVersion=2.0.0 sonar.javascript.file.suffixes=.js sonar.sourceEncoding=UTF-8 -sonar.exclusions=node_modules/**,*.config.js +sonar.exclusions=node_modules/**,*.config.js,test/e2e/fixtures/** sonar.test.exclusions=test/**/* sonar.coverage.exclusions=test/**/* sonar.cpd.exclusions=test/** diff --git a/src/About.js b/src/About.js index 3f7476f..da1a2be 100644 --- a/src/About.js +++ b/src/About.js @@ -13,14 +13,13 @@ Unless required by applicable law or agreed to in writing, software distributed const express = require("express"); -const { PLUGIN_NAME } = require("./constants"); +const { PLUGIN_NAME } = require("./support/constants"); const { version } = require("../package.json"); class AboutApi { constructor(core) { this._core = core; this._tracer = core.tracer; - this._fixtures = this._core.fixtures; this._router = express.Router(); this._router.get("/", this.getAbout.bind(this)); } diff --git a/src/Alerts.js b/src/Alerts.js index 3e309d1..467bea8 100644 --- a/src/Alerts.js +++ b/src/Alerts.js @@ -12,17 +12,26 @@ Unless required by applicable law or agreed to in writing, software distributed "use strict"; const express = require("express"); -const Boom = require("@hapi/boom"); -const { PLUGIN_NAME } = require("./constants"); +const { addCollectionMiddleware, addModelMiddleware } = require("./support/middlewares"); class AlertsApi { constructor(core) { this._core = core; this._tracer = core.tracer; this._router = express.Router(); - this._router.get("/", this.getCollection.bind(this)); - this._router.get("/:id", this.getModel.bind(this)); + addCollectionMiddleware(this._router, { + name: "alerts", + getItems: this._parseCollection.bind(this), + tracer: core.tracer, + }); + addModelMiddleware(this._router, { + name: "alert", + getItems: this._getCollection.bind(this), + parseItem: this._parseModel.bind(this), + tracer: core.tracer, + finder: (context) => (item) => item.context === context, + }); } _parseModel(alert) { @@ -44,22 +53,8 @@ class AlertsApi { return this._core.alerts.map(this._parseModel); } - getCollection(req, res) { - this._tracer.verbose(`${PLUGIN_NAME}: Sending alerts | ${req.id}`); - res.status(200); - res.send(this._parseCollection()); - } - - getModel(req, res, next) { - const id = req.params.id; - this._tracer.verbose(`${PLUGIN_NAME}: Sending alert ${id} | ${req.id}`); - const foundAlert = this._core.alerts.find((alert) => alert.context === id); - if (foundAlert) { - res.status(200); - res.send(this._parseModel(foundAlert)); - } else { - next(Boom.notFound(`Alert with id "${id}" was not found`)); - } + _getCollection() { + return this._core.alerts; } get router() { diff --git a/src/Behaviors.js b/src/Behaviors.js deleted file mode 100644 index 3991bcf..0000000 --- a/src/Behaviors.js +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -"use strict"; - -const express = require("express"); -const Boom = require("@hapi/boom"); - -const { PLUGIN_NAME } = require("./constants"); - -class BehaviorsApi { - constructor(core) { - this._core = core; - this._tracer = core.tracer; - this._behaviors = this._core.behaviors; - this._router = express.Router(); - this._router.get("/", this.getCollection.bind(this)); - this._router.get("/:id", this.getModel.bind(this)); - } - - _parseModel(behavior) { - return { - id: behavior.id, - name: behavior.name, // TODO, deprecate name property - fixtures: behavior.fixtures.map((fixture) => fixture.id), - extendedFrom: behavior.extendedFrom, - }; - } - - _parseCollection() { - return this._behaviors.collection.map(this._parseModel); - } - - getCollection(req, res) { - this._tracer.verbose(`${PLUGIN_NAME}: Sending behaviors | ${req.id}`); - res.status(200); - res.send(this._parseCollection()); - } - - getModel(req, res, next) { - const id = req.params.id; - this._tracer.verbose(`${PLUGIN_NAME}: Sending behavior ${id} | ${req.id}`); - const foundBehavior = this._behaviors.collection.find((behavior) => behavior.id === id); - if (foundBehavior) { - res.status(200); - res.send(this._parseModel(foundBehavior)); - } else { - next(Boom.notFound(`Behavior with id "${id}" was not found`)); - } - } - - get router() { - return this._router; - } -} - -module.exports = BehaviorsApi; diff --git a/src/CustomRoutesVariants.js b/src/CustomRoutesVariants.js new file mode 100644 index 0000000..b4e4853 --- /dev/null +++ b/src/CustomRoutesVariants.js @@ -0,0 +1,63 @@ +/* +Copyright 2020 Javier Brea +Copyright 2019 XbyOrange + +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. +*/ + +"use strict"; + +const express = require("express"); +const Boom = require("@hapi/boom"); + +const { addCollectionMiddleware } = require("./support/middlewares"); + +class CustomRoutesVariants { + constructor(core) { + this._core = core; + this._tracer = core.tracer; + this._router = express.Router(); + addCollectionMiddleware(this._router, { + name: "custom routes variants", + getItems: this._getCollection.bind(this), + tracer: core.tracer, + }); + + this._router.post("/", this.add.bind(this)); + this._router.delete("/", this.delete.bind(this)); + } + + _getCollection() { + return this._core.mocks.customRoutesVariants; + } + + add(req, res, next) { + const id = req.body.id; + const routeVariant = this._core.mocks.plainRoutesVariants.find( + (routeVariantCandidate) => routeVariantCandidate.id === id + ); + if (routeVariant) { + this._core.mocks.useRouteVariant(id); + res.status(204); + res.send(); + } else { + next(Boom.badRequest(`Route variant with id "${id}" was not found`)); + } + } + + delete(req, res) { + this._core.mocks.restoreRoutesVariants(); + res.status(204); + res.send(); + } + + get router() { + return this._router; + } +} + +module.exports = CustomRoutesVariants; diff --git a/src/Plugin.js b/src/Plugin.js index 0606b86..bdd6cad 100644 --- a/src/Plugin.js +++ b/src/Plugin.js @@ -13,39 +13,59 @@ const express = require("express"); const { DEFAULT_BASE_PATH, SETTINGS, - BEHAVIORS, + MOCKS, ABOUT, - FIXTURES, + ROUTES, + ROUTES_VARIANTS, + MOCK_CUSTOM_ROUTES_VARIANTS, ALERTS, + LEGACY, } = require("@mocks-server/admin-api-paths"); const packageInfo = require("../package.json"); const DeprecatedApi = require("./deprecated/Api"); +const About = require("./About"); const Settings = require("./Settings"); -const Behaviors = require("./Behaviors"); const Alerts = require("./Alerts"); -const Fixtures = require("./Fixtures"); -const About = require("./About"); +const CustomRoutesVariants = require("./CustomRoutesVariants"); -const { - ADMIN_API_PATH_OPTION, - ADMIN_API_DEPRECATED_PATHS_OPTION, - PLUGIN_NAME, - DEPRECATED_API_PATH, -} = require("./constants"); +const { ADMIN_API_PATH_OPTION, PLUGIN_NAME } = require("./support/constants"); +const { readCollectionAndModelRouter } = require("./support/routers"); class Plugin { - constructor(core) { + constructor(core, { addAlert }) { this._core = core; this._tracer = core.tracer; this._settings = this._core.settings; - this._deprecatedApi = new DeprecatedApi(core); + + this._legacyApi = new DeprecatedApi(core, { addAlert }); this._settingsApi = new Settings(this._core); - this._behaviorsApi = new Behaviors(this._core); this._alertsApi = new Alerts(this._core); this._aboutApi = new About(this._core); - this._fixturesApi = new Fixtures(this._core); + this._customRoutesVariantsApi = new CustomRoutesVariants(this._core); + + this._mocksApi = readCollectionAndModelRouter({ + collectionName: "mocks", + modelName: "mock", + getItems: () => this._core.mocks.plainMocks, + tracer: core.tracer, + }); + + this._routesApi = readCollectionAndModelRouter({ + collectionName: "routes", + modelName: "route", + getItems: () => this._core.mocks.plainRoutes, + tracer: core.tracer, + }); + + this._routesVariantsApi = readCollectionAndModelRouter({ + collectionName: "routes variants", + modelName: "route variant", + getItems: () => this._core.mocks.plainRoutesVariants, + tracer: core.tracer, + }); + core.addSetting({ name: ADMIN_API_PATH_OPTION, type: "string", @@ -53,13 +73,6 @@ class Plugin { default: DEFAULT_BASE_PATH, }); - core.addSetting({ - name: ADMIN_API_DEPRECATED_PATHS_OPTION, - type: "boolean", - description: `Disable deprecated paths of ${PLUGIN_NAME}`, - default: true, - }); - this._onChangeSettings = this._onChangeSettings.bind(this); } @@ -68,49 +81,32 @@ class Plugin { } init() { - this._deprecatedApi.init(); + this._legacyApi.init(); this._initRouter(); } start() { this._stopListeningOnChangeSettings = this._core.onChangeSettings(this._onChangeSettings); - this._addDeprecatedRouter(); this._addRouter(); } stop() { - if (this._stopListeningOnChangeSettings) { - this._stopListeningOnChangeSettings(); - } - this._removeDeprecatedRouter(); + this._stopListeningOnChangeSettings(); this._removeRouter(); } _initRouter() { this._router = express.Router(); - this._router.use(SETTINGS, this._settingsApi.router); - this._router.use(BEHAVIORS, this._behaviorsApi.router); this._router.use(ABOUT, this._aboutApi.router); - this._router.use(FIXTURES, this._fixturesApi.router); + this._router.use(SETTINGS, this._settingsApi.router); this._router.use(ALERTS, this._alertsApi.router); - } - _addDeprecatedRouter() { - this._removeDeprecatedRouter(); - if ( - this._settings.get(ADMIN_API_DEPRECATED_PATHS_OPTION) === true && - !this._addedDeprecatedRouter - ) { - this._core.addRouter(DEPRECATED_API_PATH, this._deprecatedApi.router); - this._addedDeprecatedRouter = true; - } - } + this._router.use(MOCKS, this._mocksApi); + this._router.use(ROUTES, this._routesApi); + this._router.use(ROUTES_VARIANTS, this._routesVariantsApi); + this._router.use(MOCK_CUSTOM_ROUTES_VARIANTS, this._customRoutesVariantsApi.router); - _removeDeprecatedRouter() { - if (this._addedDeprecatedRouter) { - this._core.removeRouter(DEPRECATED_API_PATH, this._deprecatedApi.router); - this._addedDeprecatedRouter = false; - } + this._router.use(LEGACY, this._legacyApi.router); } _addRouter() { @@ -127,9 +123,6 @@ class Plugin { } _onChangeSettings(newSettings) { - if (newSettings.hasOwnProperty(ADMIN_API_DEPRECATED_PATHS_OPTION)) { - this._addDeprecatedRouter(); - } if (newSettings.hasOwnProperty(ADMIN_API_PATH_OPTION)) { this._addRouter(); } diff --git a/src/Settings.js b/src/Settings.js index 75d6f24..d7dd6a3 100644 --- a/src/Settings.js +++ b/src/Settings.js @@ -14,7 +14,7 @@ Unless required by applicable law or agreed to in writing, software distributed const express = require("express"); const Boom = require("@hapi/boom"); -const { PLUGIN_NAME } = require("./constants"); +const { PLUGIN_NAME } = require("./support/constants"); class SettingsApi { constructor(core) { diff --git a/src/deprecated/Api.js b/src/deprecated/Api.js index fc46d6b..33dd03d 100644 --- a/src/deprecated/Api.js +++ b/src/deprecated/Api.js @@ -10,35 +10,38 @@ Unless required by applicable law or agreed to in writing, software distributed */ const express = require("express"); -const { DEFAULT_BASE_PATH } = require("@mocks-server/admin-api-paths"); +const { + DEFAULT_BASE_PATH, + BEHAVIORS, + FIXTURES, + LEGACY, +} = require("@mocks-server/admin-api-paths"); const Behaviors = require("./Behaviors"); -const Settings = require("./Settings"); +const Fixtures = require("./Fixtures"); -const { DEPRECATED_API_PATH, PLUGIN_NAME } = require("../constants"); +const { PLUGIN_NAME } = require("../support/constants"); // TODO, deprecate mocks router class Api { - constructor(core) { + constructor(core, { addAlert }) { this._core = core; this._tracer = core.tracer; + this._addAlert = addAlert; } init() { const behaviorsRouter = new Behaviors(this._core).router; + const fixturesRouter = new Fixtures(this._core).router; this._router = express.Router(); this._router.use((req, res, next) => { - this._core.tracer.deprecationWarn( - `"${DEPRECATED_API_PATH}" ${PLUGIN_NAME} path`, - DEFAULT_BASE_PATH - ); + this._addAlert("legacy", `Detected usage of deprecated api path "${LEGACY}"`); + this._core.tracer.deprecationWarn(`"${LEGACY}" ${PLUGIN_NAME} path`, DEFAULT_BASE_PATH); next(); }); - - this._router.use("/features", behaviorsRouter); - this._router.use("/behaviors", behaviorsRouter); - this._router.use("/settings", new Settings(this._core.settings, this._tracer).router); + this._router.use(FIXTURES, fixturesRouter); + this._router.use(BEHAVIORS, behaviorsRouter); } get router() { diff --git a/src/deprecated/Behaviors.js b/src/deprecated/Behaviors.js index a6c50e1..a799a7e 100644 --- a/src/deprecated/Behaviors.js +++ b/src/deprecated/Behaviors.js @@ -12,38 +12,49 @@ Unless required by applicable law or agreed to in writing, software distributed "use strict"; const express = require("express"); +const Boom = require("@hapi/boom"); -const { PLUGIN_NAME } = require("../constants"); +const { PLUGIN_NAME } = require("../support/constants"); class BehaviorsApi { constructor(core) { - this._tracer = core.tracer; this._core = core; + this._tracer = core.tracer; + this._behaviors = this._core.behaviors; this._router = express.Router(); this._router.get("/", this.getCollection.bind(this)); - this._router.get("/current", this.getCurrent.bind(this)); - this._router.put("/current", this.putCurrent.bind(this)); + this._router.get("/:id", this.getModel.bind(this)); } - getCurrent(req, res) { - this._tracer.verbose(`${PLUGIN_NAME}: Sending current behavior | ${req.id}`); - res.status(200); - res.send(this._core.behaviors.currentFromCollection); + _parseModel(behavior) { + return { + id: behavior.id, + name: behavior.name, // TODO, deprecate name property + fixtures: behavior.fixtures.map((fixture) => fixture.id), + extendedFrom: behavior.extendedFrom, + }; } - putCurrent(req, res) { - const newCurrent = req.body.name; - this._tracer.verbose( - `${PLUGIN_NAME}: Changing current behavior to "${newCurrent}" | ${req.id}` - ); - this._core.settings.set("behavior", newCurrent); - this.getCurrent(req, res); + _parseCollection() { + return this._behaviors.collection.map(this._parseModel); } getCollection(req, res) { - this._tracer.verbose(`${PLUGIN_NAME}: Sending behaviors collection | ${req.id}`); + this._tracer.verbose(`${PLUGIN_NAME}: Sending behaviors | ${req.id}`); res.status(200); - res.send(this._core.behaviors.collection); + res.send(this._parseCollection()); + } + + getModel(req, res, next) { + const id = req.params.id; + this._tracer.verbose(`${PLUGIN_NAME}: Sending behavior ${id} | ${req.id}`); + const foundBehavior = this._behaviors.collection.find((behavior) => behavior.id === id); + if (foundBehavior) { + res.status(200); + res.send(this._parseModel(foundBehavior)); + } else { + next(Boom.notFound(`Behavior with id "${id}" was not found`)); + } } get router() { diff --git a/src/Fixtures.js b/src/deprecated/Fixtures.js similarity index 97% rename from src/Fixtures.js rename to src/deprecated/Fixtures.js index a272255..4d4dd9d 100644 --- a/src/Fixtures.js +++ b/src/deprecated/Fixtures.js @@ -14,7 +14,7 @@ Unless required by applicable law or agreed to in writing, software distributed const express = require("express"); const Boom = require("@hapi/boom"); -const { PLUGIN_NAME } = require("./constants"); +const { PLUGIN_NAME } = require("../support/constants"); class FixturesApi { constructor(core) { diff --git a/src/deprecated/Settings.js b/src/deprecated/Settings.js deleted file mode 100644 index a1d2e24..0000000 --- a/src/deprecated/Settings.js +++ /dev/null @@ -1,47 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -"use strict"; - -const express = require("express"); - -const { PLUGIN_NAME } = require("../constants"); - -class SettingsApi { - constructor(settings, tracer) { - this._tracer = tracer; - this._settings = settings; - this._router = express.Router(); - this._router.put("/", this.put.bind(this)); - this._router.get("/", this.get.bind(this)); - } - - put(req, res) { - const newDelay = req.body.delay; - this._tracer.verbose(`${PLUGIN_NAME}: Changing delay to "${newDelay}" | ${req.id}`); - this._settings.set("delay", newDelay); - this.get(req, res); - } - - get(req, res) { - this._tracer.verbose(`${PLUGIN_NAME}: Sending delay to | ${req.id}`); - res.status(200); - res.send({ - delay: this._settings.get("delay"), - }); - } - - get router() { - return this._router; - } -} - -module.exports = SettingsApi; diff --git a/src/constants.js b/src/support/constants.js similarity index 95% rename from src/constants.js rename to src/support/constants.js index ac826da..a55ad3b 100644 --- a/src/constants.js +++ b/src/support/constants.js @@ -12,5 +12,4 @@ module.exports = { ADMIN_API_PATH_OPTION: "adminApiPath", ADMIN_API_DEPRECATED_PATHS_OPTION: "adminApiDeprecatedPaths", PLUGIN_NAME: "plugin-admin-api", - DEPRECATED_API_PATH: "/mocks", }; diff --git a/src/support/middlewares.js b/src/support/middlewares.js new file mode 100644 index 0000000..4ac8a36 --- /dev/null +++ b/src/support/middlewares.js @@ -0,0 +1,54 @@ +/* +Copyright 2021 Javier Brea + +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. +*/ + +const Boom = require("@hapi/boom"); +const { PLUGIN_NAME } = require("./constants"); + +function capitalize(str) { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +function collectionMiddleware({ name, getItems, tracer }) { + return function (req, res) { + tracer.verbose(`${PLUGIN_NAME}: Sending ${name} | ${req.id}`); + res.status(200); + res.send(getItems()); + }; +} + +function modelMiddleware({ name, getItems, parseItem, tracer, finder }) { + const capitalizedName = capitalize(name); + const returnItem = parseItem ? (item) => parseItem(item) : (item) => item; + const finderMethod = finder ? finder : (id) => (item) => item.id === id; + return function (req, res, next) { + const id = req.params.id; + tracer.verbose(`${PLUGIN_NAME}: Sending ${name} ${id} | ${req.id}`); + const foundItem = getItems().find(finderMethod(id)); + if (foundItem) { + res.status(200); + res.send(returnItem(foundItem)); + } else { + next(Boom.notFound(`${capitalizedName} with id "${id}" was not found`)); + } + }; +} + +function addCollectionMiddleware(router, options) { + router.get("/", collectionMiddleware(options)); +} + +function addModelMiddleware(router, options) { + router.get("/:id", modelMiddleware(options)); +} + +module.exports = { + addCollectionMiddleware, + addModelMiddleware, +}; diff --git a/test/unit/Libs.mocks.js b/src/support/routers.js similarity index 52% rename from test/unit/Libs.mocks.js rename to src/support/routers.js index ef4d17e..683229b 100644 --- a/test/unit/Libs.mocks.js +++ b/src/support/routers.js @@ -1,6 +1,5 @@ /* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange +Copyright 2021 Javier Brea 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 @@ -9,32 +8,25 @@ 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. */ -const sinon = require("sinon"); - const express = require("express"); -class Mock { - constructor() { - this._sandbox = sinon.createSandbox(); - - this._stubs = { - express: { - use: this._sandbox.stub(), - patch: this._sandbox.stub(), - get: this._sandbox.stub(), - }, - }; - - this._sandbox.stub(express, "Router").returns(this._stubs.express); - } - - get stubs() { - return this._stubs; - } - - restore() { - this._sandbox.restore(); - } +const { addCollectionMiddleware, addModelMiddleware } = require("./middlewares"); + +function readCollectionAndModelRouter({ collectionName, modelName, getItems, tracer }) { + const router = express.Router(); + addCollectionMiddleware(router, { + name: collectionName, + getItems, + tracer, + }); + addModelMiddleware(router, { + name: modelName, + getItems, + tracer, + }); + return router; } -module.exports = Mock; +module.exports = { + readCollectionAndModelRouter, +}; diff --git a/test/e2e/about-api.spec.js b/test/e2e/about-api.spec.js index 7e06abb..9414abf 100644 --- a/test/e2e/about-api.spec.js +++ b/test/e2e/about-api.spec.js @@ -8,23 +8,24 @@ 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. */ -const { startServer, stopServer, request } = require("./support/utils"); +const { startServer, fetch, waitForServer } = require("./support/helpers"); const { version } = require("../../package.json"); describe("about api", () => { let server; beforeAll(async () => { server = await startServer("web-tutorial"); + await waitForServer(); }); afterAll(async () => { - await stopServer(server); + await server.stop(); }); describe("get /", () => { it("should return current version", async () => { - const response = await request("/admin/about"); - expect(response).toEqual({ + const response = await fetch("/admin/about"); + expect(response.body).toEqual({ version, }); }); diff --git a/test/e2e/alerts-api.spec.js b/test/e2e/alerts-api.spec.js index d71179d..168479d 100644 --- a/test/e2e/alerts-api.spec.js +++ b/test/e2e/alerts-api.spec.js @@ -7,110 +7,81 @@ 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. */ -const path = require("path"); -const fsExtra = require("fs-extra"); -const { CliRunner, request, fixturesFolder, wait } = require("./support/utils"); +const { startServer, fetch, waitForServer, wait, fixturesFolder } = require("./support/helpers"); describe("alerts api", () => { - let cli; + let server; beforeAll(async () => { - fsExtra.removeSync(fixturesFolder("files-watch")); - fsExtra.copySync(fixturesFolder("web-tutorial"), fixturesFolder("files-watch")); - cli = new CliRunner(["node", "start.js", "--path=files-watch", "--behavior=foo"], { - cwd: path.resolve(__dirname, "fixtures"), + server = await startServer("web-tutorial", { + mock: "foo", }); - await wait(2000); + await waitForServer(); }); afterAll(async () => { - await cli.kill(); + await server.stop(); }); describe("when started", () => { - it("should return behavior not found alert", async () => { - const response = await request("/admin/alerts"); - expect(response.length).toEqual(1); + it("should return mock not found alert", async () => { + const response = await fetch("/admin/alerts"); + expect(response.body.length).toEqual(1); }); it("should return specific alert when requested by id", async () => { - const response = await request("/admin/alerts/mocks%3Abehaviors%3Acurrent"); - expect(response).toEqual({ - id: "mocks:behaviors:current", - context: "mocks:behaviors:current", - message: 'Defined behavior "foo" was not found. The first one found was used instead', + const response = await fetch("/admin/alerts/mocks%3Acurrent%3Asettings"); + expect(response.body).toEqual({ + id: "mocks:current:settings", + context: "mocks:current:settings", + message: 'Mock "foo" was not found. Using the first one found', error: null, }); }); it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ + const users = await fetch("/api/users"); + expect(users.body).toEqual([ { id: 1, name: "John Doe" }, { id: 2, name: "Jane Doe" }, ]); }); }); - describe("when behavior is modified", () => { + describe("when mock is modified", () => { beforeAll(async () => { - await request("/admin/settings", { + await fetch("/admin/settings", { method: "PATCH", body: { - behavior: "dynamic", + mock: "base", }, }); await wait(); }, 10000); it("should return no alerts", async () => { - const response = await request("/admin/alerts"); - expect(response.length).toEqual(0); + const response = await fetch("/admin/alerts"); + expect(response.body.length).toEqual(0); }); }); - describe("when files contain an error", () => { + describe("when there is an error loading files", () => { beforeAll(async () => { - fsExtra.copySync(fixturesFolder("files-error"), fixturesFolder("files-watch")); - await wait(6000); + await fetch("/admin/settings", { + method: "PATCH", + body: { + path: fixturesFolder("files-error-routes"), + }, + }); + await wait(); }, 10000); - it("should return one alert", async () => { - const response = await request("/admin/alerts"); - expect(response.length).toEqual(1); - }); - - it("should return specific alert when requested by id", async () => { - const response = await request( - "/admin/alerts/plugins%3A%40mocks-server%2Fcore%2Fplugin-files-loader%3Aload" - ); - expect(response.id).toEqual("plugins:@mocks-server/core/plugin-files-loader:load"); - expect(response.message).toEqual(expect.stringContaining("test/e2e/fixtures/files-watch")); - expect(response.error.name).toEqual("ReferenceError"); - expect(response.error.message).toEqual("FOO is not defined"); - expect(response.error.stack).toEqual( - expect.stringContaining("test/e2e/fixtures/files-watch/fixtures/users.js:2:18") + it("should return alert containing error", async () => { + const response = await fetch("/admin/alerts"); + expect(response.body.length).toEqual(1); + expect(response.body[0].error.message).toEqual( + expect.stringContaining("Cannot find module '../db/users'") ); }); }); - - describe("when files error is fixed", () => { - beforeAll(async () => { - fsExtra.copySync(fixturesFolder("web-tutorial"), fixturesFolder("files-watch")); - await wait(6000); - }, 10000); - - it("should return no alerts", async () => { - const response = await request("/admin/alerts"); - expect(response.length).toEqual(0); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe" }, - { id: 2, name: "Jane Doe" }, - ]); - }); - }); }); diff --git a/test/e2e/change-behavior.spec.js b/test/e2e/change-behavior.spec.js deleted file mode 100644 index d00f117..0000000 --- a/test/e2e/change-behavior.spec.js +++ /dev/null @@ -1,114 +0,0 @@ -/* -Copyright 2019 Javier Brea - -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. -*/ - -const { startServer, stopServer, request } = require("./support/utils"); - -describe("API for changing current behavior", () => { - let server; - - beforeAll(async () => { - server = await startServer("web-tutorial-json"); - }); - - afterAll(async () => { - await stopServer(server); - }); - - describe("When started", () => { - it("should have 3 behaviors available", async () => { - const behaviors = await request("/admin/behaviors"); - expect(behaviors.length).toEqual(3); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe" }, - { id: 2, name: "Jane Doe" }, - ]); - }); - - it("should serve user 1 under the /api/users/1 path", async () => { - const users = await request("/api/users/1"); - expect(users).toEqual({ id: 1, name: "John Doe" }); - }); - - it("should serve user 1 under the /api/users/2 path", async () => { - const users = await request("/api/users/2"); - expect(users).toEqual({ id: 1, name: "John Doe" }); - }); - }); - - describe('When changing current behavior to "user2"', () => { - beforeAll(async () => { - await request("/admin/settings", { - method: "PATCH", - body: { - behavior: "user2", - }, - }); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe" }, - { id: 2, name: "Jane Doe" }, - ]); - }); - - it("should serve user 2 under the /api/users/1 path", async () => { - const users = await request("/api/users/1"); - expect(users).toEqual({ id: 2, name: "Jane Doe" }); - }); - - it("should serve user 2 under the /api/users/2 path", async () => { - const users = await request("/api/users/2"); - expect(users).toEqual({ id: 2, name: "Jane Doe" }); - }); - }); - - describe('When changing current behavior to "dynamic"', () => { - beforeAll(async () => { - await request("/admin/settings", { - method: "PATCH", - body: { - behavior: "dynamic", - }, - }); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe" }, - { id: 2, name: "Jane Doe" }, - ]); - }); - - it("should serve user 1 under the /api/users/1 path", async () => { - const users = await request("/api/users/1"); - expect(users).toEqual({ id: 1, name: "John Doe" }); - }); - - it("should serve user 2 under the /api/users/2 path", async () => { - const users = await request("/api/users/2"); - expect(users).toEqual({ id: 2, name: "Jane Doe" }); - }); - - it("should return not found for /api/users/3 path", async () => { - const usersResponse = await request("/api/users/3", { - resolveWithFullResponse: true, - simple: false, - }); - expect(usersResponse.statusCode).toEqual(404); - }); - }); -}); diff --git a/test/e2e/deprecated-change-behavior.spec.js b/test/e2e/deprecated-change-behavior.spec.js deleted file mode 100644 index 36f3632..0000000 --- a/test/e2e/deprecated-change-behavior.spec.js +++ /dev/null @@ -1,110 +0,0 @@ -/* -Copyright 2019 Javier Brea - -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. -*/ - -const { - startServer, - stopServer, - request, - deprecatedChangeBehavior, - deprecatedGetBehaviors, -} = require("./support/utils"); - -describe("deprecated API for changing current behavior", () => { - let server; - - beforeAll(async () => { - server = await startServer(); - }); - - afterAll(async () => { - await stopServer(server); - }); - - describe("When started", () => { - it("should have 3 behaviors available", async () => { - const behaviors = await deprecatedGetBehaviors(); - expect(behaviors.length).toEqual(3); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe" }, - { id: 2, name: "Jane Doe" }, - ]); - }); - - it("should serve user 1 under the /api/users/1 path", async () => { - const users = await request("/api/users/1"); - expect(users).toEqual({ id: 1, name: "John Doe" }); - }); - - it("should serve user 1 under the /api/users/2 path", async () => { - const users = await request("/api/users/2"); - expect(users).toEqual({ id: 1, name: "John Doe" }); - }); - }); - - describe('When changing current behavior to "user2"', () => { - beforeAll(async () => { - await deprecatedChangeBehavior("user2"); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe" }, - { id: 2, name: "Jane Doe" }, - ]); - }); - - it("should serve user 2 under the /api/users/1 path", async () => { - const users = await request("/api/users/1"); - expect(users).toEqual({ id: 2, name: "Jane Doe" }); - }); - - it("should serve user 2 under the /api/users/2 path", async () => { - const users = await request("/api/users/2"); - expect(users).toEqual({ id: 2, name: "Jane Doe" }); - }); - }); - - describe('When changing current behavior to "dynamic"', () => { - beforeAll(async () => { - await deprecatedChangeBehavior("dynamic"); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe" }, - { id: 2, name: "Jane Doe" }, - ]); - }); - - it("should serve user 1 under the /api/users/1 path", async () => { - const users = await request("/api/users/1"); - expect(users).toEqual({ id: 1, name: "John Doe" }); - }); - - it("should serve user 2 under the /api/users/2 path", async () => { - const users = await request("/api/users/2"); - expect(users).toEqual({ id: 2, name: "Jane Doe" }); - }); - - it("should return not found for /api/users/3 path", async () => { - const usersResponse = await request("/api/users/3", { - resolveWithFullResponse: true, - simple: false, - }); - expect(usersResponse.statusCode).toEqual(404); - }); - }); -}); diff --git a/test/e2e/deprecated-core-events.spec.js b/test/e2e/deprecated-core-events.spec.js deleted file mode 100644 index 6008300..0000000 --- a/test/e2e/deprecated-core-events.spec.js +++ /dev/null @@ -1,166 +0,0 @@ -/* -Copyright 2019 Javier Brea - -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. -*/ - -const path = require("path"); -const fsExtra = require("fs-extra"); -const { - request, - deprecatedChangeBehavior, - deprecatedGetBehaviors, - fixturesFolder, - wait, - CliRunner, -} = require("./support/utils"); - -describe("Plugin listening to core events", () => { - let cli; - - beforeAll(async () => { - fsExtra.removeSync(fixturesFolder("files-watch")); - fsExtra.copySync(fixturesFolder("web-tutorial"), fixturesFolder("files-watch")); - cli = new CliRunner(["node", "start-files-watch.js"], { - cwd: path.resolve(__dirname, "fixtures"), - }); - await wait(2000); - }); - - afterAll(async () => { - await cli.kill(); - }); - - describe("When server is started", () => { - it("should have 3 behaviors available", async () => { - const behaviors = await deprecatedGetBehaviors(); - expect(behaviors.length).toEqual(3); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe" }, - { id: 2, name: "Jane Doe" }, - ]); - }); - - it("should serve user 1 under the /api/users/1 path", async () => { - const users = await request("/api/users/1"); - expect(users).toEqual({ id: 1, name: "John Doe" }); - }); - - it("should serve user 1 under the /api/users/2 path", async () => { - const users = await request("/api/users/2"); - expect(users).toEqual({ id: 1, name: "John Doe" }); - }); - }); - - describe("When files are modified", () => { - beforeAll(async () => { - fsExtra.copySync(fixturesFolder("files-modification"), fixturesFolder("files-watch")); - await wait(2000); - }); - - describe("without changing current behavior", () => { - it("should have 4 behaviors available", async () => { - const behaviors = await deprecatedGetBehaviors(); - expect(behaviors.length).toEqual(4); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe modified" }, - { id: 2, name: "Jane Doe modified" }, - ]); - }); - - it("should serve user 1 under the /api/users/1 path", async () => { - const users = await request("/api/users/1"); - expect(users).toEqual({ id: 1, name: "John Doe modified" }); - }); - - it("should serve user 1 under the /api/users/2 path", async () => { - const users = await request("/api/users/2"); - expect(users).toEqual({ id: 1, name: "John Doe modified" }); - }); - }); - - describe('When changing current behavior to "user2"', () => { - beforeAll(async () => { - await deprecatedChangeBehavior("user2"); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe modified" }, - { id: 2, name: "Jane Doe modified" }, - ]); - }); - - it("should serve user 2 under the /api/users/1 path", async () => { - const users = await request("/api/users/1"); - expect(users).toEqual({ id: 2, name: "Jane Doe modified" }); - }); - - it("should serve user 2 under the /api/users/2 path", async () => { - const users = await request("/api/users/2"); - expect(users).toEqual({ id: 2, name: "Jane Doe modified" }); - }); - }); - - describe('When changing current behavior to "dynamic"', () => { - beforeAll(async () => { - await deprecatedChangeBehavior("dynamic"); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe modified" }, - { id: 2, name: "Jane Doe modified" }, - ]); - }); - - it("should serve user 1 under the /api/users/1 path", async () => { - const users = await request("/api/users/1"); - expect(users).toEqual({ id: 1, name: "John Doe modified" }); - }); - - it("should serve user 2 under the /api/users/2 path", async () => { - const users = await request("/api/users/2"); - expect(users).toEqual({ id: 2, name: "Jane Doe modified" }); - }); - }); - - describe('When changing current behavior to "newOne"', () => { - beforeAll(async () => { - await deprecatedChangeBehavior("newOne"); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/new-users"); - expect(users).toEqual([ - { id: 1, name: "John Doe new" }, - { id: 2, name: "Jane Doe new" }, - ]); - }); - - it("should serve user 1 under the /api/new-users/1 path", async () => { - const users = await request("/api/new-users/1"); - expect(users).toEqual({ id: 1, name: "John Doe new" }); - }); - - it("should serve user 1 under the /api/new-users/2 path", async () => { - const users = await request("/api/new-users/2"); - expect(users).toEqual({ id: 1, name: "John Doe new" }); - }); - }); - }); -}); diff --git a/test/e2e/fixtures/files-error-routes/mocks.js b/test/e2e/fixtures/files-error-routes/mocks.js new file mode 100644 index 0000000..82511e6 --- /dev/null +++ b/test/e2e/fixtures/files-error-routes/mocks.js @@ -0,0 +1,26 @@ +/* +Copyright 2021 Javier Brea + +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. +*/ + +module.exports = [ + { + id: "base", + routesVariants: ["get-users:success", "get-user:1"], + }, + { + id: "user-2", + from: "base", + routesVariants: ["get-user:2"], + }, + { + id: "user-real", + from: "base", + routesVariants: ["get-user:real"], + }, +]; diff --git a/test/e2e/fixtures/files-error-routes/routes/user.js b/test/e2e/fixtures/files-error-routes/routes/user.js new file mode 100644 index 0000000..ac18756 --- /dev/null +++ b/test/e2e/fixtures/files-error-routes/routes/user.js @@ -0,0 +1,51 @@ +/* +Copyright 2021 Javier Brea + +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. +*/ + +const { USERS } = require("../db/users"); + +module.exports = [ + { + id: "get-user", + url: "/api/users/:id", + method: "GET", + variants: [ + { + id: "1", + response: { + status: 200, + body: USERS[0], + }, + }, + { + id: "2", + response: { + status: 200, + body: USERS[1], + }, + }, + { + id: "real", + response: (req, res) => { + const userId = req.params.id; + const user = USERS.find((userData) => userData.id === Number(userId)); + if (user) { + res.status(200); + res.send(user); + } else { + res.status(404); + res.send({ + message: "User not found", + }); + } + }, + }, + ], + }, +]; diff --git a/test/unit/index.spec.js b/test/e2e/fixtures/files-error-routes/routes/users.js similarity index 67% rename from test/unit/index.spec.js rename to test/e2e/fixtures/files-error-routes/routes/users.js index 094b1e3..d3e2586 100644 --- a/test/unit/index.spec.js +++ b/test/e2e/fixtures/files-error-routes/routes/users.js @@ -1,6 +1,5 @@ /* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange +Copyright 2021 Javier Brea 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 @@ -8,12 +7,8 @@ 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. */ +/* eslint-disable */ -const index = require("../../index"); -const Plugin = require("../../src/Plugin"); +const { USERS } = require("../db/users"); -describe("index", () => { - it("should export the Plugin constructor", () => { - expect(index).toEqual(Plugin); - }); -}); +module.foo; diff --git a/test/e2e/fixtures/files-error/fixtures/users.js b/test/e2e/fixtures/files-error/fixtures/users.js deleted file mode 100644 index 3cb2db1..0000000 --- a/test/e2e/fixtures/files-error/fixtures/users.js +++ /dev/null @@ -1,2 +0,0 @@ -//eslint-disable-next-line -module.exports = FOO; diff --git a/test/e2e/fixtures/files-modification/fixtures/users.js b/test/e2e/fixtures/files-modification/fixtures/users.js deleted file mode 100644 index 50d25b2..0000000 --- a/test/e2e/fixtures/files-modification/fixtures/users.js +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 2019 Javier Brea - -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. -*/ - -const INITIAL_USERS = [ - { - id: 1, - name: "John Doe modified", - }, - { - id: 2, - name: "Jane Doe modified", - }, -]; - -const getUsers = { - url: "/api/users", - method: "GET", - response: { - status: 200, - body: INITIAL_USERS, - }, -}; - -const getUser = { - url: "/api/users/:id", - method: "GET", - response: { - status: 200, - body: { - id: 1, - name: "John Doe modified", - }, - }, -}; - -const getUser2 = { - url: "/api/users/:id", - method: "GET", - response: { - status: 200, - body: { - id: 2, - name: "Jane Doe modified", - }, - }, -}; - -const getRealUser = { - url: "/api/users/:id", - method: "GET", - response: (req, res) => { - const userId = req.params.id; - const user = INITIAL_USERS.find((userData) => userData.id === Number(userId)); - if (user) { - res.status(200); - res.send(user); - } else { - res.status(404); - res.send({ - message: "User not found", - }); - } - }, -}; - -module.exports = { - getUsers, - getUser, - getUser2, - getRealUser, -}; diff --git a/test/e2e/fixtures/files-modification/standard.js b/test/e2e/fixtures/files-modification/standard.js deleted file mode 100644 index 382416d..0000000 --- a/test/e2e/fixtures/files-modification/standard.js +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright 2019 Javier Brea - -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. -*/ - -// /mocks/behaviors.js - -const { Behavior } = require("@mocks-server/core"); - -const { getUsers, getUser, getUser2, getRealUser } = require("./fixtures/users"); -const { getNewUsers, getNewUser } = require("./new-fixtures/users"); - -const standard = new Behavior([getUsers, getUser]); - -// Extends the standard behavior adding "getUser2" fixture. -const user2 = standard.extend([getUser2]); - -// Extends the standard behavior adding "getRealUser" dynamic fixture. -const dynamic = standard.extend([getRealUser]); - -// New one created while server is running -const newOne = standard.extend([getNewUsers, getNewUser]); - -module.exports = { - standard, - user2, - dynamic, - newOne, -}; diff --git a/test/e2e/fixtures/web-tutorial/fixtures/users.js b/test/e2e/fixtures/legacy-web-tutorial/fixtures/users.js similarity index 100% rename from test/e2e/fixtures/web-tutorial/fixtures/users.js rename to test/e2e/fixtures/legacy-web-tutorial/fixtures/users.js diff --git a/test/e2e/fixtures/web-tutorial/standard.js b/test/e2e/fixtures/legacy-web-tutorial/standard.js similarity index 75% rename from test/e2e/fixtures/web-tutorial/standard.js rename to test/e2e/fixtures/legacy-web-tutorial/standard.js index 8cf2fa1..710f251 100644 --- a/test/e2e/fixtures/web-tutorial/standard.js +++ b/test/e2e/fixtures/legacy-web-tutorial/standard.js @@ -14,16 +14,18 @@ const { Behavior } = require("@mocks-server/core"); const { getUsers, getUser, getUser2, getRealUser } = require("./fixtures/users"); -const standard = new Behavior([getUsers, getUser]); +const behavior1 = new Behavior([getUsers, getUser], { + id: "standard", +}); // Extends the standard behavior adding "getUser2" fixture. -const user2 = standard.extend([getUser2]); +const behavior2 = behavior1.extend([getUser2], { + id: "user2", +}); // Extends the standard behavior adding "getRealUser" dynamic fixture. -const dynamic = standard.extend([getRealUser]); +const behavior3 = behavior1.extend([getRealUser], { + id: "dynamic", +}); -module.exports = { - standard, - user2, - dynamic, -}; +module.exports = [behavior1, behavior2, behavior3]; diff --git a/test/e2e/fixtures/start-files-watch.js b/test/e2e/fixtures/start-files-watch.js deleted file mode 100644 index 4a3cc65..0000000 --- a/test/e2e/fixtures/start-files-watch.js +++ /dev/null @@ -1,6 +0,0 @@ -const path = require("path"); -const { startServer } = require("../support/utils"); - -startServer(path.resolve(__dirname, "files-watch"), { - watch: true, -}); diff --git a/test/e2e/fixtures/start.js b/test/e2e/fixtures/start.js deleted file mode 100755 index 655e692..0000000 --- a/test/e2e/fixtures/start.js +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -"use strict"; - -const { Core } = require("@mocks-server/core"); -const AdminApi = require("../../../index"); - -const handleError = (error) => { - console.error(`Error: ${error.message}`); - process.exitCode = 1; -}; - -const start = () => { - try { - const mocksServer = new Core({ - plugins: [AdminApi], - }); - return mocksServer - .init() - .then(() => { - console.log(mocksServer.settings.all); - return mocksServer.start(); - }) - .catch(handleError); - } catch (error) { - return handleError(error); - } -}; - -start(); diff --git a/test/e2e/fixtures/web-tutorial-json/behaviors.json b/test/e2e/fixtures/web-tutorial-json/behaviors.json deleted file mode 100644 index 868a4a7..0000000 --- a/test/e2e/fixtures/web-tutorial-json/behaviors.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "id": "standard", - "fixtures": ["get-users", "get-user"] - }, - { - "id": "user2", - "from": "standard", - "fixtures": ["get-user-2"] - }, - { - "id": "dynamic", - "from": "standard", - "fixtures": ["get-user-real"] - } -] diff --git a/test/e2e/fixtures/web-tutorial-json/fixtures/dynamic.js b/test/e2e/fixtures/web-tutorial-json/fixtures/dynamic.js deleted file mode 100644 index 74bfb7f..0000000 --- a/test/e2e/fixtures/web-tutorial-json/fixtures/dynamic.js +++ /dev/null @@ -1,33 +0,0 @@ -const INITIAL_USERS = [ - { - id: 1, - name: "John Doe", - }, - { - id: 2, - name: "Jane Doe", - }, -]; - -const getUserReal = { - id: "get-user-real", - url: "/api/users/:id", - method: "GET", - response: (req, res) => { - const userId = req.params.id; - const user = INITIAL_USERS.find((userData) => userData.id === Number(userId)); - if (user) { - res.status(200); - res.send(user); - } else { - res.status(404); - res.send({ - message: "User not found", - }); - } - }, -}; - -module.exports = { - getUserReal, -}; diff --git a/test/e2e/fixtures/web-tutorial-json/fixtures/fixtures.json b/test/e2e/fixtures/web-tutorial-json/fixtures/fixtures.json deleted file mode 100644 index fe1adc4..0000000 --- a/test/e2e/fixtures/web-tutorial-json/fixtures/fixtures.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "id": "get-users", - "url": "/api/users", - "method": "GET", - "response": { - "status": 200, - "body": [ - { - "id": 1, - "name": "John Doe" - }, - { - "id": 2, - "name": "Jane Doe" - } - ] - } - }, - { - "id": "get-user", - "url": "/api/users/:id", - "method": "GET", - "response": { - "status": 200, - "body": { - "id": 1, - "name": "John Doe" - } - } - }, - { - "id": "get-user-2", - "url": "/api/users/:id", - "method": "GET", - "response": { - "status": 200, - "body": { - "id": 2, - "name": "Jane Doe" - } - } - } -] diff --git a/test/e2e/fixtures/files-modification/new-fixtures/users.js b/test/e2e/fixtures/web-tutorial-modified/db/users.js similarity index 60% rename from test/e2e/fixtures/files-modification/new-fixtures/users.js rename to test/e2e/fixtures/web-tutorial-modified/db/users.js index e764ff9..627c6a7 100644 --- a/test/e2e/fixtures/files-modification/new-fixtures/users.js +++ b/test/e2e/fixtures/web-tutorial-modified/db/users.js @@ -1,5 +1,5 @@ /* -Copyright 2019 Javier Brea +Copyright 2021 Javier Brea 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 @@ -8,36 +8,17 @@ 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. */ -const INITIAL_USERS = [ +const USERS = [ { id: 1, - name: "John Doe new", + name: "John Doe modified", }, { id: 2, - name: "Jane Doe new", + name: "Jane Doe modified", }, ]; -const getNewUsers = { - url: "/api/new-users", - method: "GET", - response: { - status: 200, - body: INITIAL_USERS, - }, -}; - -const getNewUser = { - url: "/api/new-users/:id", - method: "GET", - response: { - status: 200, - body: INITIAL_USERS[0], - }, -}; - module.exports = { - getNewUsers, - getNewUser, + USERS, }; diff --git a/test/e2e/fixtures/web-tutorial-modified/mocks.js b/test/e2e/fixtures/web-tutorial-modified/mocks.js new file mode 100644 index 0000000..0141b77 --- /dev/null +++ b/test/e2e/fixtures/web-tutorial-modified/mocks.js @@ -0,0 +1,31 @@ +/* +Copyright 2021 Javier Brea + +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. +*/ + +module.exports = [ + { + id: "base", + routesVariants: ["get-users:success", "get-user:1", "get-users-new:success"], + }, + { + id: "user-2", + from: "base", + routesVariants: ["get-user:2"], + }, + { + id: "user-real", + from: "base", + routesVariants: ["get-user:real"], + }, + { + id: "users-error", + from: "base", + routesVariants: ["get-users:error"], + }, +]; diff --git a/test/e2e/fixtures/web-tutorial-modified/routes/user.js b/test/e2e/fixtures/web-tutorial-modified/routes/user.js new file mode 100644 index 0000000..ac18756 --- /dev/null +++ b/test/e2e/fixtures/web-tutorial-modified/routes/user.js @@ -0,0 +1,51 @@ +/* +Copyright 2021 Javier Brea + +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. +*/ + +const { USERS } = require("../db/users"); + +module.exports = [ + { + id: "get-user", + url: "/api/users/:id", + method: "GET", + variants: [ + { + id: "1", + response: { + status: 200, + body: USERS[0], + }, + }, + { + id: "2", + response: { + status: 200, + body: USERS[1], + }, + }, + { + id: "real", + response: (req, res) => { + const userId = req.params.id; + const user = USERS.find((userData) => userData.id === Number(userId)); + if (user) { + res.status(200); + res.send(user); + } else { + res.status(404); + res.send({ + message: "User not found", + }); + } + }, + }, + ], + }, +]; diff --git a/test/e2e/fixtures/web-tutorial-modified/routes/users.js b/test/e2e/fixtures/web-tutorial-modified/routes/users.js new file mode 100644 index 0000000..afedb5f --- /dev/null +++ b/test/e2e/fixtures/web-tutorial-modified/routes/users.js @@ -0,0 +1,61 @@ +/* +Copyright 2021 Javier Brea + +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. +*/ + +const { USERS } = require("../db/users"); + +module.exports = [ + { + id: "get-users", + url: "/api/users", + method: "GET", + variants: [ + { + id: "success", + response: { + headers: { + "x-custom-header": "foo-header", + "x-another-header": "another-header", + }, + status: 200, + body: USERS, + }, + }, + { + id: "error", + response: { + status: 403, + body: { + message: "Bad data", + }, + }, + }, + ], + }, + { + id: "get-users-new", + url: "/api/new-users", + method: "GET", + variants: [ + { + id: "success", + response: { + status: 200, + body: [ + ...USERS, + { + id: 3, + name: "Brand new user", + }, + ], + }, + }, + ], + }, +]; diff --git a/test/e2e/fixtures/web-tutorial/db/users.js b/test/e2e/fixtures/web-tutorial/db/users.js new file mode 100644 index 0000000..f05a501 --- /dev/null +++ b/test/e2e/fixtures/web-tutorial/db/users.js @@ -0,0 +1,24 @@ +/* +Copyright 2021 Javier Brea + +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. +*/ + +const USERS = [ + { + id: 1, + name: "John Doe", + }, + { + id: 2, + name: "Jane Doe", + }, +]; + +module.exports = { + USERS, +}; diff --git a/test/e2e/fixtures/web-tutorial/mocks.js b/test/e2e/fixtures/web-tutorial/mocks.js new file mode 100644 index 0000000..82511e6 --- /dev/null +++ b/test/e2e/fixtures/web-tutorial/mocks.js @@ -0,0 +1,26 @@ +/* +Copyright 2021 Javier Brea + +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. +*/ + +module.exports = [ + { + id: "base", + routesVariants: ["get-users:success", "get-user:1"], + }, + { + id: "user-2", + from: "base", + routesVariants: ["get-user:2"], + }, + { + id: "user-real", + from: "base", + routesVariants: ["get-user:real"], + }, +]; diff --git a/test/e2e/fixtures/web-tutorial/routes/user.js b/test/e2e/fixtures/web-tutorial/routes/user.js new file mode 100644 index 0000000..ac18756 --- /dev/null +++ b/test/e2e/fixtures/web-tutorial/routes/user.js @@ -0,0 +1,51 @@ +/* +Copyright 2021 Javier Brea + +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. +*/ + +const { USERS } = require("../db/users"); + +module.exports = [ + { + id: "get-user", + url: "/api/users/:id", + method: "GET", + variants: [ + { + id: "1", + response: { + status: 200, + body: USERS[0], + }, + }, + { + id: "2", + response: { + status: 200, + body: USERS[1], + }, + }, + { + id: "real", + response: (req, res) => { + const userId = req.params.id; + const user = USERS.find((userData) => userData.id === Number(userId)); + if (user) { + res.status(200); + res.send(user); + } else { + res.status(404); + res.send({ + message: "User not found", + }); + } + }, + }, + ], + }, +]; diff --git a/test/e2e/fixtures/web-tutorial/routes/users.js b/test/e2e/fixtures/web-tutorial/routes/users.js new file mode 100644 index 0000000..6c1d2ae --- /dev/null +++ b/test/e2e/fixtures/web-tutorial/routes/users.js @@ -0,0 +1,37 @@ +/* +Copyright 2021 Javier Brea + +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. +*/ + +const { USERS } = require("../db/users"); + +module.exports = [ + { + id: "get-users", + url: "/api/users", + method: "GET", + variants: [ + { + id: "success", + response: { + status: 200, + body: USERS, + }, + }, + { + id: "error", + response: { + status: 403, + body: { + message: "Bad data", + }, + }, + }, + ], + }, +]; diff --git a/test/e2e/behaviors-api.spec.js b/test/e2e/legacy-behaviors-api.spec.js similarity index 76% rename from test/e2e/behaviors-api.spec.js rename to test/e2e/legacy-behaviors-api.spec.js index eb0894b..3afcbaa 100644 --- a/test/e2e/behaviors-api.spec.js +++ b/test/e2e/legacy-behaviors-api.spec.js @@ -8,22 +8,26 @@ 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. */ -const { startServer, stopServer, request } = require("./support/utils"); +const { startServer, fetch, waitForServer, fixturesFolder } = require("./support/helpers"); -describe("behaviors api", () => { +describe("legacy behaviors api", () => { let server; + beforeAll(async () => { - server = await startServer("web-tutorial"); + server = await startServer("web-tutorial", { + pathLegacy: fixturesFolder("legacy-web-tutorial"), + }); + await waitForServer(); }); afterAll(async () => { - await stopServer(server); + await server.stop(); }); describe("get /", () => { it("should return current behaviors", async () => { - const response = await request("/admin/behaviors"); - expect(response).toEqual([ + const response = await fetch("/admin/legacy/behaviors"); + expect(response.body).toEqual([ { extendedFrom: null, fixtures: ["12e5f429b92f67d4ec2bf90940ec1135", "0dbc954f9d9c9f3f7996c60e63384c9e"], @@ -56,8 +60,8 @@ describe("behaviors api", () => { describe("get /standard", () => { it("should return standard behavior", async () => { - const response = await request("/admin/behaviors/standard"); - expect(response).toEqual({ + const response = await fetch("/admin/legacy/behaviors/standard"); + expect(response.body).toEqual({ extendedFrom: null, fixtures: ["12e5f429b92f67d4ec2bf90940ec1135", "0dbc954f9d9c9f3f7996c60e63384c9e"], name: "standard", @@ -68,8 +72,8 @@ describe("behaviors api", () => { describe("get /dynamic", () => { it("should return standard behavior", async () => { - const response = await request("/admin/behaviors/dynamic"); - expect(response).toEqual({ + const response = await fetch("/admin/legacy/behaviors/dynamic"); + expect(response.body).toEqual({ extendedFrom: "standard", fixtures: [ "e82af88532da929b0592925899eb056e", @@ -84,11 +88,8 @@ describe("behaviors api", () => { describe("get unexistant behavior", () => { it("should return a not found error", async () => { - const response = await request("/admin/behaviors/foo", { - resolveWithFullResponse: true, - simple: false, - }); - expect(response.statusCode).toEqual(404); + const response = await fetch("/admin/legacy/behaviors/foo"); + expect(response.status).toEqual(404); expect(response.body.message).toEqual('Behavior with id "foo" was not found'); }); }); diff --git a/test/e2e/fixtures-api.spec.js b/test/e2e/legacy-fixtures-api.spec.js similarity index 83% rename from test/e2e/fixtures-api.spec.js rename to test/e2e/legacy-fixtures-api.spec.js index 21ae4cf..f52f107 100644 --- a/test/e2e/fixtures-api.spec.js +++ b/test/e2e/legacy-fixtures-api.spec.js @@ -8,22 +8,26 @@ 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. */ -const { startServer, stopServer, request } = require("./support/utils"); +const { startServer, fetch, waitForServer, fixturesFolder } = require("./support/helpers"); -describe("alerts api", () => { +describe("legacy fixtures api", () => { let server; + beforeAll(async () => { - server = await startServer("web-tutorial"); + server = await startServer("web-tutorial", { + pathLegacy: fixturesFolder("legacy-web-tutorial"), + }); + await waitForServer(); }); afterAll(async () => { - await stopServer(server); + await server.stop(); }); describe("get /", () => { it("should return current fixtures", async () => { - const response = await request("/admin/fixtures"); - expect(response).toEqual([ + const response = await fetch("/admin/legacy/fixtures"); + expect(response.body).toEqual([ { id: "e82af88532da929b0592925899eb056e", requestMatchId: "9989c8c9766561cd432c625deabca48b", @@ -69,8 +73,8 @@ describe("alerts api", () => { describe("get /e82af88532da929b0592925899eb056e", () => { it("should return fixture with id e82af88532da929b0592925899eb056e", async () => { - const response = await request("/admin/fixtures/e82af88532da929b0592925899eb056e"); - expect(response).toEqual({ + const response = await fetch("/admin/legacy/fixtures/e82af88532da929b0592925899eb056e"); + expect(response.body).toEqual({ id: "e82af88532da929b0592925899eb056e", requestMatchId: "9989c8c9766561cd432c625deabca48b", handler: "mocks-server-fixture", @@ -86,8 +90,8 @@ describe("alerts api", () => { describe("get /bd5292849ee3fda9fa8383837bb908e7", () => { it("should return fixture with id bd5292849ee3fda9fa8383837bb908e7", async () => { - const response = await request("/admin/fixtures/bd5292849ee3fda9fa8383837bb908e7"); - expect(response).toEqual({ + const response = await fetch("/admin/legacy/fixtures/bd5292849ee3fda9fa8383837bb908e7"); + expect(response.body).toEqual({ id: "bd5292849ee3fda9fa8383837bb908e7", requestMatchId: "9989c8c9766561cd432c625deabca48b", handler: "mocks-server-fixture", @@ -99,11 +103,8 @@ describe("alerts api", () => { describe("get unexistant fixture", () => { it("should return a not found error", async () => { - const response = await request("/admin/fixtures/foo", { - resolveWithFullResponse: true, - simple: false, - }); - expect(response.statusCode).toEqual(404); + const response = await fetch("/admin/legacy/fixtures/foo"); + expect(response.status).toEqual(404); expect(response.body.message).toEqual('Fixture with id "foo" was not found'); }); }); diff --git a/test/e2e/mock-custom-routes-variants-api.spec.js b/test/e2e/mock-custom-routes-variants-api.spec.js new file mode 100644 index 0000000..dd4cf06 --- /dev/null +++ b/test/e2e/mock-custom-routes-variants-api.spec.js @@ -0,0 +1,82 @@ +/* +Copyright 2019 Javier Brea + +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. +*/ + +const { startServer, fetch, waitForServer } = require("./support/helpers"); + +describe("mock custom routes variants api", () => { + let server; + + beforeAll(async () => { + server = await startServer("web-tutorial"); + await waitForServer(); + }); + + afterAll(async () => { + await server.stop(); + }); + + describe("get /", () => { + it("should return mock custom routes variants", async () => { + const response = await fetch("/admin/mock-custom-routes-variants"); + expect(response.body).toEqual([]); + }); + }); + + describe("post /", () => { + it("should add mock custom route variant", async () => { + await fetch("/admin/mock-custom-routes-variants", { + method: "POST", + body: { + id: "get-user:2", + }, + }); + const response = await fetch("/admin/mock-custom-routes-variants"); + expect(response.body).toEqual(["get-user:2"]); + }); + + it("should have changed user response", async () => { + const response = await fetch("/api/users/1"); + expect(response.body).toEqual({ id: 2, name: "Jane Doe" }); + }); + }); + + describe("delete /", () => { + it("should restore mock routes variants", async () => { + await fetch("/admin/mock-custom-routes-variants", { + method: "DELETE", + }); + const response = await fetch("/admin/mock-custom-routes-variants"); + expect(response.body).toEqual([]); + }); + + it("should have changed user response", async () => { + const response = await fetch("/api/users/1"); + expect(response.body).toEqual({ id: 1, name: "John Doe" }); + }); + }); + + describe("when trying to set an unexistent route variant", () => { + it("should not add mock custom route variant", async () => { + await fetch("/admin/mock-custom-routes-variants", { + method: "POST", + body: { + id: "foo", + }, + }); + const response = await fetch("/admin/mock-custom-routes-variants"); + expect(response.body).toEqual([]); + }); + + it("should not have changed user response", async () => { + const response = await fetch("/api/users/1"); + expect(response.body).toEqual({ id: 1, name: "John Doe" }); + }); + }); +}); diff --git a/test/e2e/mocks-api.spec.js b/test/e2e/mocks-api.spec.js new file mode 100644 index 0000000..9c3e1c0 --- /dev/null +++ b/test/e2e/mocks-api.spec.js @@ -0,0 +1,82 @@ +/* +Copyright 2019 Javier Brea + +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. +*/ + +const { startServer, fetch, waitForServer } = require("./support/helpers"); + +describe("mocks api", () => { + let server; + + beforeAll(async () => { + server = await startServer("web-tutorial"); + await waitForServer(); + }); + + afterAll(async () => { + await server.stop(); + }); + + describe("get /", () => { + it("should return current mocks", async () => { + const response = await fetch("/admin/mocks"); + expect(response.body).toEqual([ + { + id: "base", + from: null, + routesVariants: ["get-users:success", "get-user:1"], + appliedRoutesVariants: ["get-users:success", "get-user:1"], + }, + { + id: "user-2", + from: "base", + routesVariants: ["get-user:2"], + appliedRoutesVariants: ["get-users:success", "get-user:2"], + }, + { + id: "user-real", + from: "base", + routesVariants: ["get-user:real"], + appliedRoutesVariants: ["get-users:success", "get-user:real"], + }, + ]); + }); + }); + + describe("get /base", () => { + it("should return base mock", async () => { + const response = await fetch("/admin/mocks/base"); + expect(response.body).toEqual({ + id: "base", + from: null, + routesVariants: ["get-users:success", "get-user:1"], + appliedRoutesVariants: ["get-users:success", "get-user:1"], + }); + }); + }); + + describe("get /user-2", () => { + it("should return user-2 mock", async () => { + const response = await fetch("/admin/mocks/user-2"); + expect(response.body).toEqual({ + id: "user-2", + from: "base", + routesVariants: ["get-user:2"], + appliedRoutesVariants: ["get-users:success", "get-user:2"], + }); + }); + }); + + describe("get unexistant mock", () => { + it("should return a not found error", async () => { + const response = await fetch("/admin/mocks/foo"); + expect(response.status).toEqual(404); + expect(response.body.message).toEqual('Mock with id "foo" was not found'); + }); + }); +}); diff --git a/test/e2e/plugin-options.spec.js b/test/e2e/plugin-options.spec.js index b414519..d72818d 100644 --- a/test/e2e/plugin-options.spec.js +++ b/test/e2e/plugin-options.spec.js @@ -7,120 +7,37 @@ 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. */ -const path = require("path"); -const { - startServer, - stopServer, - request, - CliRunner, - wait, - fixturesFolder, -} = require("./support/utils"); +const { startServer, fetch, fixturesFolder, waitForServer } = require("./support/helpers"); describe("plugin options", () => { let server; - let cli; - - describe("adminApiDeprecatedPaths option", () => { - beforeAll(async () => { - server = await startServer("web-tutorial", { - adminApiDeprecatedPaths: false, - }); - }); - - afterAll(async () => { - await stopServer(server); - }); - - it("should disable deprecated behaviors api path", async () => { - const behaviorsResponse = await request("/mocks/behaviors", { - resolveWithFullResponse: true, - simple: false, - }); - expect(behaviorsResponse.statusCode).toEqual(404); - }); - - it("should disable deprecated features api path", async () => { - const behaviorsResponse = await request("/mocks/features", { - resolveWithFullResponse: true, - simple: false, - }); - expect(behaviorsResponse.statusCode).toEqual(404); - }); - - it("should disable deprecated settings api path", async () => { - const behaviorsResponse = await request("/mocks/settings", { - resolveWithFullResponse: true, - simple: false, - }); - expect(behaviorsResponse.statusCode).toEqual(404); - }); - }); - - describe("adminApiDeprecatedPaths option used from CLI", () => { - beforeAll(async () => { - cli = new CliRunner( - ["node", "start.js", "--path=web-tutorial", "--no-adminApiDeprecatedPaths"], - { - cwd: path.resolve(__dirname, "fixtures"), - } - ); - await wait(2000); - }); - - afterAll(async () => { - await cli.kill(); - }); - - it("should disable deprecated behaviors api path", async () => { - console.log(cli.logs); - const behaviorsResponse = await request("/mocks/behaviors", { - resolveWithFullResponse: true, - simple: false, - }); - expect(behaviorsResponse.statusCode).toEqual(404); - }); - - it("should disable deprecated features api path", async () => { - const behaviorsResponse = await request("/mocks/features", { - resolveWithFullResponse: true, - simple: false, - }); - expect(behaviorsResponse.statusCode).toEqual(404); - }); - - it("should disable deprecated settings api path", async () => { - const behaviorsResponse = await request("/mocks/settings", { - resolveWithFullResponse: true, - simple: false, - }); - expect(behaviorsResponse.statusCode).toEqual(404); - }); - }); describe("adminApiPath option", () => { beforeAll(async () => { server = await startServer("web-tutorial", { adminApiPath: "/foo", }); + await waitForServer(); }); - afterAll(() => { - stopServer(server); + afterAll(async () => { + await server.stop(); }); it("should change the administration api path", async () => { - const adminResponse = await request("/foo/settings"); - expect(adminResponse).toEqual({ - behavior: "standard", + const adminResponse = await fetch("/foo/settings"); + expect(adminResponse.body).toEqual({ + behavior: null, path: fixturesFolder("web-tutorial"), delay: 0, host: "0.0.0.0", port: 3100, watch: false, - log: "silly", + log: "silent", adminApiPath: "/foo", - adminApiDeprecatedPaths: true, + pathLegacy: null, + watchLegacy: true, + mock: null, }); }); }); diff --git a/test/e2e/routes-api.spec.js b/test/e2e/routes-api.spec.js new file mode 100644 index 0000000..42fa0f9 --- /dev/null +++ b/test/e2e/routes-api.spec.js @@ -0,0 +1,80 @@ +/* +Copyright 2019 Javier Brea + +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. +*/ + +const { startServer, fetch, waitForServer } = require("./support/helpers"); + +describe("routes api", () => { + let server; + + beforeAll(async () => { + server = await startServer("web-tutorial"); + await waitForServer(); + }); + + afterAll(async () => { + await server.stop(); + }); + + describe("get /", () => { + it("should return current routes", async () => { + const response = await fetch("/admin/routes"); + expect(response.body).toEqual([ + { + id: "get-user", + delay: null, + url: "/api/users/:id", + method: "GET", + variants: ["get-user:1", "get-user:2", "get-user:real"], + }, + { + id: "get-users", + delay: null, + url: "/api/users", + method: "GET", + variants: ["get-users:success", "get-users:error"], + }, + ]); + }); + }); + + describe("get /get-user", () => { + it("should return route with id get-user", async () => { + const response = await fetch("/admin/routes/get-user"); + expect(response.body).toEqual({ + id: "get-user", + delay: null, + url: "/api/users/:id", + method: "GET", + variants: ["get-user:1", "get-user:2", "get-user:real"], + }); + }); + }); + + describe("get /get-users", () => { + it("should return route with id get-users", async () => { + const response = await fetch("/admin/routes/get-users"); + expect(response.body).toEqual({ + id: "get-users", + delay: null, + url: "/api/users", + method: "GET", + variants: ["get-users:success", "get-users:error"], + }); + }); + }); + + describe("get unexistant route", () => { + it("should return a not found error", async () => { + const response = await fetch("/admin/routes/foo"); + expect(response.status).toEqual(404); + expect(response.body.message).toEqual('Route with id "foo" was not found'); + }); + }); +}); diff --git a/test/e2e/routes-variants-api.spec.js b/test/e2e/routes-variants-api.spec.js new file mode 100644 index 0000000..05429c3 --- /dev/null +++ b/test/e2e/routes-variants-api.spec.js @@ -0,0 +1,107 @@ +/* +Copyright 2019 Javier Brea + +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. +*/ + +const { startServer, fetch, waitForServer } = require("./support/helpers"); + +describe("routes variants api", () => { + let server; + + beforeAll(async () => { + server = await startServer("web-tutorial"); + await waitForServer(); + }); + + afterAll(async () => { + await server.stop(); + }); + + describe("get /", () => { + it("should return routes variants", async () => { + const response = await fetch("/admin/routes-variants"); + expect(response.body).toEqual([ + { + id: "get-user:1", + routeId: "get-user", + handler: "default", + response: { body: { id: 1, name: "John Doe" }, status: 200 }, + delay: null, + }, + { + id: "get-user:2", + routeId: "get-user", + handler: "default", + response: { body: { id: 2, name: "Jane Doe" }, status: 200 }, + delay: null, + }, + { + id: "get-user:real", + routeId: "get-user", + handler: "default", + response: "function", + delay: null, + }, + { + id: "get-users:success", + routeId: "get-users", + handler: "default", + response: { + body: [ + { id: 1, name: "John Doe" }, + { id: 2, name: "Jane Doe" }, + ], + status: 200, + }, + delay: null, + }, + { + id: "get-users:error", + routeId: "get-users", + handler: "default", + response: { body: { message: "Bad data" }, status: 403 }, + delay: null, + }, + ]); + }); + }); + + describe("get /get-user:1", () => { + it("should return route variant with id get-user:1", async () => { + const response = await fetch("/admin/routes-variants/get-user:1"); + expect(response.body).toEqual({ + id: "get-user:1", + routeId: "get-user", + handler: "default", + response: { body: { id: 1, name: "John Doe" }, status: 200 }, + delay: null, + }); + }); + }); + + describe("get /get-user:2", () => { + it("should return route variant with id get-user:2", async () => { + const response = await fetch("/admin/routes-variants/get-user:2"); + expect(response.body).toEqual({ + id: "get-user:2", + routeId: "get-user", + handler: "default", + response: { body: { id: 2, name: "Jane Doe" }, status: 200 }, + delay: null, + }); + }); + }); + + describe("get unexistant route variant", () => { + it("should return a not found error", async () => { + const response = await fetch("/admin/routes-variants/foo"); + expect(response.status).toEqual(404); + expect(response.body.message).toEqual('Route variant with id "foo" was not found'); + }); + }); +}); diff --git a/test/e2e/settings-api.spec.js b/test/e2e/settings-api.spec.js index f405cb3..e5098ba 100644 --- a/test/e2e/settings-api.spec.js +++ b/test/e2e/settings-api.spec.js @@ -10,36 +10,39 @@ Unless required by applicable law or agreed to in writing, software distributed const { startServer, - stopServer, - request, + fetch, fixturesFolder, TimeCounter, wait, -} = require("./support/utils"); + waitForServer, +} = require("./support/helpers"); describe("settings api", () => { let server; beforeAll(async () => { server = await startServer("web-tutorial"); + await waitForServer(); }); afterAll(async () => { - await stopServer(server); + await server.stop(); }); describe("get", () => { it("should return current settings", async () => { - const settingsResponse = await request("/admin/settings"); - expect(settingsResponse).toEqual({ - behavior: "standard", + const settingsResponse = await fetch("/admin/settings"); + expect(settingsResponse.body).toEqual({ + behavior: null, + mock: null, path: fixturesFolder("web-tutorial"), delay: 0, host: "0.0.0.0", port: 3100, watch: false, - log: "silly", + log: "silent", adminApiPath: "/admin", - adminApiDeprecatedPaths: true, + watchLegacy: true, + pathLegacy: null, }); }); }); @@ -48,7 +51,7 @@ describe("settings api", () => { describe("when changing an unexistant option", () => { it("should response with a bad request containing errors", async () => { expect.assertions(2); - const settingsResponse = await request("/admin/settings", { + const settingsResponse = await fetch("/admin/settings", { method: "PATCH", body: { foo: "foo-value", @@ -57,10 +60,8 @@ describe("settings api", () => { foo: "foo", }, }, - resolveWithFullResponse: true, - simple: false, }); - expect(settingsResponse.statusCode).toEqual(400); + expect(settingsResponse.status).toEqual(400); expect(settingsResponse.body.message).toEqual( 'Invalid option name "foo". Invalid option name "anotherFoo". Invalid option name "third"' ); @@ -68,110 +69,108 @@ describe("settings api", () => { it("should not apply any change if request contains any error", async () => { expect.assertions(3); - const settingsUpdateResponse = await request("/admin/settings", { + const settingsUpdateResponse = await fetch("/admin/settings", { method: "PATCH", body: { foo: "foo-value", delay: 1000, }, - resolveWithFullResponse: true, - simple: false, }); - const settingsResponse = await request("/admin/settings"); - expect(settingsUpdateResponse.statusCode).toEqual(400); + const settingsResponse = await fetch("/admin/settings"); + expect(settingsUpdateResponse.status).toEqual(400); expect(settingsUpdateResponse.body.message).toEqual('Invalid option name "foo"'); - expect(settingsResponse.delay).toEqual(0); + expect(settingsResponse.body.delay).toEqual(0); }); }); describe("when changing delay option", () => { it("should respond with no delay", async () => { const timeCounter = new TimeCounter(); - await request("/api/users"); + await fetch("/api/users"); timeCounter.stop(); expect(timeCounter.total).toBeLessThan(200); }); it("should set delay option and have effect on server response time", async () => { const timeCounter = new TimeCounter(); - await request("/admin/settings", { + await fetch("/admin/settings", { method: "PATCH", body: { delay: 2000, }, }); - await request("/api/users"); + await fetch("/api/users"); timeCounter.stop(); expect(timeCounter.total).toBeGreaterThan(2000); }); it("should set delay option to 0", async () => { const timeCounter = new TimeCounter(); - await request("/admin/settings", { + await fetch("/admin/settings", { method: "PATCH", body: { delay: 0, }, }); - await request("/api/users"); + await fetch("/api/users"); timeCounter.stop(); expect(timeCounter.total).toBeLessThan(200); }); }); - describe("when changing behavior option", () => { + describe("when changing mock option", () => { describe("without changing it", () => { it("should serve user 1 under the /api/users/1 path", async () => { - const users = await request("/api/users/1"); - expect(users).toEqual({ id: 1, name: "John Doe" }); + const users = await fetch("/api/users/1"); + expect(users.body).toEqual({ id: 1, name: "John Doe" }); }); it("should serve user 1 under the /api/users/2 path", async () => { - const users = await request("/api/users/2"); - expect(users).toEqual({ id: 1, name: "John Doe" }); + const users = await fetch("/api/users/2"); + expect(users.body).toEqual({ id: 1, name: "John Doe" }); }); }); - describe('changing it to "user2"', () => { + describe('changing it to "user-2"', () => { beforeAll(async () => { - await request("/admin/settings", { + await fetch("/admin/settings", { method: "PATCH", body: { - behavior: "user2", + mock: "user-2", }, }); }); - it("should return new behavior when getting settings", async () => { - const settingsResponse = await request("/admin/settings"); - expect(settingsResponse.behavior).toEqual("user2"); + it("should return new mock when getting settings", async () => { + const settingsResponse = await fetch("/admin/settings"); + expect(settingsResponse.body.mock).toEqual("user-2"); }); it("should serve user 2 under the /api/users/1 path", async () => { - const users = await request("/api/users/1"); - expect(users).toEqual({ id: 2, name: "Jane Doe" }); + const users = await fetch("/api/users/1"); + expect(users.body).toEqual({ id: 2, name: "Jane Doe" }); }); it("should serve user 2 under the /api/users/2 path", async () => { - const users = await request("/api/users/2"); - expect(users).toEqual({ id: 2, name: "Jane Doe" }); + const users = await fetch("/api/users/2"); + expect(users.body).toEqual({ id: 2, name: "Jane Doe" }); }); }); }); describe("when changing path option", () => { beforeAll(async () => { - await request("/admin/settings", { + await fetch("/admin/settings", { method: "PATCH", body: { - path: fixturesFolder("files-modification"), + path: fixturesFolder("web-tutorial-modified"), }, }); await wait(1000); }); afterAll(async () => { - await request("/admin/settings", { + await fetch("/admin/settings", { method: "PATCH", body: { path: fixturesFolder("web-tutorial"), @@ -181,13 +180,13 @@ describe("settings api", () => { }); it("should return new path option when getting settings", async () => { - const settingsResponse = await request("/admin/settings"); - expect(settingsResponse.path).toEqual(fixturesFolder("files-modification")); + const settingsResponse = await fetch("/admin/settings"); + expect(settingsResponse.body.path).toEqual(fixturesFolder("web-tutorial-modified")); }); it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ + const users = await fetch("/api/users"); + expect(users.body).toEqual([ { id: 1, name: "John Doe modified" }, { id: 2, name: "Jane Doe modified" }, ]); @@ -196,7 +195,7 @@ describe("settings api", () => { describe("when changing port option", () => { beforeAll(async () => { - await request("/admin/settings", { + await fetch("/admin/settings", { method: "PATCH", body: { port: 3101, @@ -206,7 +205,7 @@ describe("settings api", () => { }); afterAll(async () => { - await request("/admin/settings", { + await fetch("/admin/settings", { port: 3101, method: "PATCH", body: { @@ -217,23 +216,23 @@ describe("settings api", () => { }); it("should return new port option when getting settings, using new port", async () => { - const settingsResponse = await request("/admin/settings", { + const settingsResponse = await fetch("/admin/settings", { port: 3101, }); - expect(settingsResponse.port).toEqual(3101); + expect(settingsResponse.body.port).toEqual(3101); }); it("should serve user 2 under the /api/users/1 path using new port", async () => { - const users = await request("/api/users/1", { + const users = await fetch("/api/users/1", { port: 3101, }); - expect(users).toEqual({ id: 2, name: "Jane Doe" }); + expect(users.body).toEqual({ id: 2, name: "Jane Doe" }); }); }); describe("when changing adminApiPath option", () => { beforeAll(async () => { - await request("/admin/settings", { + await fetch("/admin/settings", { method: "PATCH", body: { adminApiPath: "/administration", @@ -243,7 +242,7 @@ describe("settings api", () => { }); afterAll(async () => { - await request("/administration/settings", { + await fetch("/administration/settings", { method: "PATCH", body: { adminApiPath: "/admin", @@ -253,45 +252,13 @@ describe("settings api", () => { }); it("should return new port adminApiPath when getting settings, using new admin api path", async () => { - const settingsResponse = await request("/administration/settings"); - expect(settingsResponse.adminApiPath).toEqual("/administration"); + const settingsResponse = await fetch("/administration/settings"); + expect(settingsResponse.body.adminApiPath).toEqual("/administration"); }); it("should return not found adminApiPath when getting settings in old admin api path", async () => { - const settingsResponse = await request("/admin/settings", { - resolveWithFullResponse: true, - simple: false, - }); - expect(settingsResponse.statusCode).toEqual(404); - }); - }); - - describe("without changing adminApiDeprecatedPaths option", () => { - it("should return current delay option in deprecated api path", async () => { - const settingsResponse = await request("/mocks/settings"); - expect(settingsResponse).toEqual({ - delay: 0, - }); - }); - }); - - describe("when changing adminApiDeprecatedPaths option", () => { - beforeAll(async () => { - await request("/admin/settings", { - method: "PATCH", - body: { - adminApiDeprecatedPaths: false, - }, - }); - await wait(1000); - }); - - it("should return not found when getting settings in deprecated admin api path", async () => { - const settingsResponse = await request("/mocks/settings", { - resolveWithFullResponse: true, - simple: false, - }); - expect(settingsResponse.statusCode).toEqual(404); + const settingsResponse = await fetch("/admin/settings"); + expect(settingsResponse.status).toEqual(404); }); }); }); diff --git a/test/e2e/settings-logs-api.spec.js b/test/e2e/settings-logs-api.spec.js deleted file mode 100644 index 46bb567..0000000 --- a/test/e2e/settings-logs-api.spec.js +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright 2019 Javier Brea - -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. -*/ -const path = require("path"); -const fsExtra = require("fs-extra"); - -const { CliRunner, request, fixturesFolder, wait } = require("./support/utils"); - -describe("log option modified through api", () => { - let cli; - beforeAll(async () => { - cli = new CliRunner(["node", "start.js", "--path=web-tutorial", "--log=info"], { - cwd: path.resolve(__dirname, "fixtures"), - }); - await wait(2000); - }); - - afterAll(async () => { - await cli.kill(); - }); - - describe("when started", () => { - it("should return log level when getting settings", async () => { - const settingsResponse = await request("/admin/settings"); - expect(settingsResponse.log).toEqual("info"); - }); - - it("should not have logged any log with verbose level", async () => { - expect(cli.logs).toEqual(expect.not.stringContaining("Mocks verbose")); - }); - }); - - describe("when log level is changed to verbose", () => { - beforeAll(async () => { - await request("/admin/settings", { - method: "PATCH", - body: { - log: "verbose", - }, - }); - fsExtra.copySync(fixturesFolder("files-modification"), fixturesFolder("files-watch")); - await wait(1000); - }); - - it("should return new log level when getting settings", async () => { - const settingsResponse = await request("/admin/settings"); - expect(settingsResponse.log).toEqual("verbose"); - }); - - it("should have logged logs with verbose level", async () => { - expect(cli.logs).toEqual(expect.stringContaining("Mocks verbose")); - }); - }); -}); diff --git a/test/e2e/settings-watch-api.spec.js b/test/e2e/settings-watch-api.spec.js deleted file mode 100644 index bb40898..0000000 --- a/test/e2e/settings-watch-api.spec.js +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright 2019 Javier Brea - -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. -*/ -const path = require("path"); -const fsExtra = require("fs-extra"); - -const { CliRunner, request, fixturesFolder, wait } = require("./support/utils"); - -describe("watch option modified through api", () => { - let cli; - beforeAll(async () => { - fsExtra.removeSync(fixturesFolder("files-watch")); - fsExtra.copySync(fixturesFolder("web-tutorial"), fixturesFolder("files-watch")); - cli = new CliRunner(["node", "start.js", "--path=files-watch", "--watch=false"], { - cwd: path.resolve(__dirname, "fixtures"), - }); - await wait(2000); - }); - - afterAll(async () => { - await cli.kill(); - }); - - describe("when started", () => { - it("should return watch disabled when getting settings", async () => { - const settingsResponse = await request("/admin/settings"); - expect(settingsResponse.watch).toEqual(false); - }); - - it("should serve users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe" }, - { id: 2, name: "Jane Doe" }, - ]); - }); - }); - - describe("when watch is enabled and files are modified", () => { - beforeAll(async () => { - await request("/admin/settings", { - method: "PATCH", - body: { - watch: true, - }, - }); - await wait(); - fsExtra.copySync(fixturesFolder("files-modification"), fixturesFolder("files-watch")); - await wait(6000); - }, 10000); - - it("should return watch enabled when getting settings", async () => { - const settingsResponse = await request("/admin/settings"); - expect(settingsResponse.watch).toEqual(true); - }); - - it("should serve new users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe modified" }, - { id: 2, name: "Jane Doe modified" }, - ]); - }); - }); - - describe("when watch is disabled and files are modified", () => { - beforeAll(async () => { - await request("/admin/settings", { - method: "PATCH", - body: { - watch: false, - }, - }); - await wait(); - fsExtra.copySync(fixturesFolder("web-tutorial"), fixturesFolder("files-watch")); - await wait(6000); - }, 10000); - - it("should return watch disabled when getting settings", async () => { - const settingsResponse = await request("/admin/settings"); - expect(settingsResponse.watch).toEqual(false); - }); - - it("should serve new users collection mock under the /api/users path", async () => { - const users = await request("/api/users"); - expect(users).toEqual([ - { id: 1, name: "John Doe modified" }, - { id: 2, name: "Jane Doe modified" }, - ]); - }); - }); -}); diff --git a/test/e2e/stop-plugin.spec.js b/test/e2e/stop-plugin.spec.js index 0de4243..24aeb1b 100644 --- a/test/e2e/stop-plugin.spec.js +++ b/test/e2e/stop-plugin.spec.js @@ -8,49 +8,37 @@ 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. */ -const { startServer, stopServer, request, fixturesFolder, wait } = require("./support/utils"); +const { startServer, fetch, fixturesFolder, wait, waitForServer } = require("./support/helpers"); -describe("stop plugin", () => { +describe("when stopping plugin", () => { let server; beforeAll(async () => { server = await startServer("web-tutorial"); + await waitForServer(); }); afterAll(async () => { - await stopServer(server); + await server.stop(); }); describe("when started", () => { it("should return current settings", async () => { - const response = await request("/admin/settings"); - expect(response).toEqual({ - behavior: "standard", - path: fixturesFolder("web-tutorial"), - delay: 0, - host: "0.0.0.0", - port: 3100, - watch: false, - log: "silly", - adminApiPath: "/admin", - adminApiDeprecatedPaths: true, - }); + const response = await fetch("/admin/settings"); + expect(response.body.path).toEqual(fixturesFolder("web-tutorial")); }); }); describe("when stopped", () => { it("should respond not found when requesting setting", async () => { await server._stopPlugins(); - const response = await request("/admin/settings", { - resolveWithFullResponse: true, - simple: false, - }); - expect(response.statusCode).toEqual(404); + const response = await fetch("/admin/settings"); + expect(response.status).toEqual(404); }); it("should respond to mocks requests", async () => { await server._stopPlugins(); - const response = await request("/api/users"); - expect(response).toEqual([ + const response = await fetch("/api/users"); + expect(response.body).toEqual([ { id: 1, name: "John Doe", @@ -63,12 +51,12 @@ describe("stop plugin", () => { }); }); - describe("when behavior is changed", () => { - it("should respond with new behavior", async () => { - server.settings.set("behavior", "user2"); + describe("when mock is changed", () => { + it("should respond with new mock", async () => { + server.settings.set("mock", "user-2"); await wait(1000); - const response = await request("/api/users/2"); - expect(response).toEqual({ + const response = await fetch("/api/users/2"); + expect(response.body).toEqual({ id: 2, name: "Jane Doe", }); @@ -76,37 +64,24 @@ describe("stop plugin", () => { it("should have not started the plugin", async () => { await server._stopPlugins(); - const response = await request("/admin/settings", { - resolveWithFullResponse: true, - simple: false, - }); - expect(response.statusCode).toEqual(404); + const response = await fetch("/admin/settings"); + expect(response.status).toEqual(404); }); }); describe("when plugins are started", () => { - it("should respond with same behavior", async () => { + it("should respond with same mock", async () => { await server._startPlugins(); - const response = await request("/api/users/2"); - expect(response).toEqual({ + const response = await fetch("/api/users/2"); + expect(response.body).toEqual({ id: 2, name: "Jane Doe", }); }); it("should have started the plugin", async () => { - const response = await request("/admin/settings"); - expect(response).toEqual({ - behavior: "user2", - path: fixturesFolder("web-tutorial"), - delay: 0, - host: "0.0.0.0", - port: 3100, - watch: false, - log: "silly", - adminApiPath: "/admin", - adminApiDeprecatedPaths: true, - }); + const response = await fetch("/admin/settings"); + expect(response.body.path).toEqual(fixturesFolder("web-tutorial")); }); }); }); diff --git a/test/e2e/support/CliRunner.js b/test/e2e/support/CliRunner.js deleted file mode 100644 index 273f993..0000000 --- a/test/e2e/support/CliRunner.js +++ /dev/null @@ -1,92 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -"use strict"; - -const childProcess = require("child_process"); - -const treeKillSync = require("tree-kill-sync"); -const stripAnsi = require("strip-ansi"); - -const ENCODING_TYPE = "utf8"; - -module.exports = class CliRunner { - constructor(commandToExecute, options = {}) { - this._command = this.getCommandToExecute(commandToExecute); - this._cwd = options.cwd || process.cwd(); - this._logs = []; - - this._exitPromise = new Promise((resolve) => { - this._resolveExitPromise = resolve; - }); - - this.logData = this.logData.bind(this); - - this.run(); - } - - getCommandToExecute(command) { - return { - name: command[0], - params: command.splice(1, command.length - 1), - }; - } - - logData(data) { - const cleanData = stripAnsi(data.replace(/\x1Bc/, "")); - if (cleanData.length) { - this._logs.push(cleanData); - } - } - - run() { - if (this._cliProcess) { - throw new Error("Cli is already running"); - } else { - this._cliProcess = childProcess.spawn(this._command.name, this._command.params, { - cwd: this._cwd, - }); - this._cliProcess.stdin.setEncoding(ENCODING_TYPE); - - this._cliProcess.stdout.setEncoding(ENCODING_TYPE); - this._cliProcess.stderr.setEncoding(ENCODING_TYPE); - - this._cliProcess.stdout.on("data", this.logData); - this._cliProcess.stderr.on("data", this.logData); - - this._cliProcess.on("close", (code) => { - this._exitCode = code; - this._resolveExitPromise(true); - }); - } - } - - async kill() { - treeKillSync(this._cliProcess.pid); - return this._exitPromise; - } - - async hasExit() { - return this._exitPromise; - } - - flush() { - this._logs = []; - } - - get logs() { - return this._logs.join(""); - } - - get exitCode() { - return this._exitCode; - } -}; diff --git a/test/e2e/support/helpers.js b/test/e2e/support/helpers.js new file mode 100644 index 0000000..21497af --- /dev/null +++ b/test/e2e/support/helpers.js @@ -0,0 +1,148 @@ +/* +Copyright 2019 Javier Brea + +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. +*/ + +const path = require("path"); + +const crossFetch = require("cross-fetch"); +const waitOn = require("wait-on"); + +const { Core } = require("@mocks-server/core"); +const AdminApiPlugin = require("../../../index"); + +const SERVER_PORT = 3100; + +const defaultOptions = { + port: SERVER_PORT, + log: "silent", + watch: false, +}; + +const defaultRequestOptions = { + method: "GET", + headers: { + "Content-Type": "application/json", + }, +}; + +const fixturesFolder = (folderName) => { + return path.resolve(__dirname, "..", "fixtures", folderName); +}; + +const createCore = () => { + return new Core({ + onlyProgrammaticOptions: true, + plugins: [AdminApiPlugin], + }); +}; + +const startExistingCore = (core, mocksPath, options = {}) => { + const mocks = mocksPath || "web-tutorial"; + return core + .init({ + ...defaultOptions, + path: fixturesFolder(mocks), + ...options, + }) + .then(() => { + return core.start().then(() => { + return Promise.resolve(core); + }); + }); +}; + +const startServer = (mocksPath, options = {}) => { + return startExistingCore(createCore(), mocksPath, options); +}; + +const serverUrl = (port) => { + return `http://localhost:${port || SERVER_PORT}`; +}; + +const fetch = (uri, options = {}) => { + const requestOptions = { + ...defaultRequestOptions, + ...options, + }; + if (requestOptions.body) { + requestOptions.body = JSON.stringify(requestOptions.body); + } + + return crossFetch(`${serverUrl(options.port)}${uri}`, { + ...requestOptions, + }).then((res) => { + return res + .json() + .then((processedRes) => ({ + body: processedRes, + status: res.status, + headers: res.headers, + })) + .catch(() => { + return { status: res.status, headers: res.headers }; + }); + }); +}; + +class TimeCounter { + constructor() { + this._startTime = new Date(); + } + + _getMiliseconds() { + this._miliseconds = this._endTime - this._startTime; + } + + get total() { + return this._miliseconds; + } + + stop() { + this._endTime = new Date(); + this._getMiliseconds(); + } +} + +const wait = (time = 1000) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(); + }, time); + }); +}; + +const waitForServer = (port) => { + return waitOn({ resources: [`tcp:localhost:${port || SERVER_PORT}`] }); +}; + +const waitForServerUrl = (url) => { + return waitOn({ resources: [`${serverUrl()}${url}`] }); +}; + +const findAlert = (alertContextFragment, alerts) => { + return alerts.find((alert) => alert.context.includes(alertContextFragment)); +}; + +const findTrace = (traceFragment, traces) => { + return traces.find((trace) => trace.includes(traceFragment)); +}; + +module.exports = { + createCore, + startExistingCore, + startServer, + fetch, + TimeCounter, + wait, + waitForServer, + waitForServerUrl, + fixturesFolder, + findAlert, + findTrace, +}; diff --git a/test/e2e/support/utils.js b/test/e2e/support/utils.js deleted file mode 100644 index e6ed274..0000000 --- a/test/e2e/support/utils.js +++ /dev/null @@ -1,130 +0,0 @@ -/* -Copyright 2019 Javier Brea - -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. -*/ - -const path = require("path"); -const { Core } = require("@mocks-server/core"); - -const requestPromise = require("request-promise"); -const CliRunner = require("./CliRunner"); - -const PluginAdminApi = require("../../../index"); - -const SERVER_PORT = 3100; - -const defaultOptions = { - port: SERVER_PORT, - log: "silly", - watch: false, -}; - -const defaultRequestOptions = { - method: "GET", -}; - -const fixturesFolder = (folderName) => { - return path.resolve(__dirname, "..", "fixtures", folderName); -}; - -const startServer = (mocksPath, opts = {}) => { - const mocks = mocksPath || "web-tutorial"; - const options = { - path: fixturesFolder(mocks), - ...defaultOptions, - ...opts, - }; - const server = new Core({ - onlyProgrammaticOptions: true, - plugins: [PluginAdminApi], - }); - return server.init(options).then(() => { - return server.start().then(() => { - return Promise.resolve(server); - }); - }); -}; - -const stopServer = (server) => { - return server.stop(); -}; - -const request = (uri, options = {}) => { - const requestOptions = { - ...defaultRequestOptions, - ...options, - }; - - return requestPromise({ - uri: `http://localhost:${options.port || SERVER_PORT}${uri}`, - json: true, - ...requestOptions, - }); -}; - -const deprecatedChangeBehavior = (behavior) => { - return request("/mocks/behaviors/current", { - method: "PUT", - body: { - name: behavior, - }, - }); -}; - -const deprecatedGetBehaviors = () => { - return request("/mocks/behaviors"); -}; - -const deprecatedChangeDelay = (delay) => { - return request("/mocks/settings", { - method: "PUT", - body: { - delay, - }, - }); -}; - -class TimeCounter { - constructor() { - this._startTime = new Date(); - } - - _getMiliseconds() { - this._miliseconds = this._endTime - this._startTime; - } - - get total() { - return this._miliseconds; - } - - stop() { - this._endTime = new Date(); - this._getMiliseconds(); - } -} - -const wait = (time = 1000) => { - return new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, time); - }); -}; - -module.exports = { - startServer, - stopServer, - request, - deprecatedChangeBehavior, - deprecatedGetBehaviors, - deprecatedChangeDelay, - TimeCounter, - wait, - fixturesFolder, - CliRunner, -}; diff --git a/test/unit/Core.mocks.js b/test/unit/Core.mocks.js deleted file mode 100644 index ce4a2a0..0000000 --- a/test/unit/Core.mocks.js +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright 2019 Javier Brea - -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. -*/ - -const sinon = require("sinon"); - -jest.mock("@mocks-server/core"); - -const { Core } = require("@mocks-server/core"); - -class CoreMock { - constructor() { - this._sandbox = sinon.createSandbox(); - - this._stubs = { - init: this._sandbox.stub().resolves(), - start: this._sandbox.stub().resolves(), - stop: this._sandbox.stub().resolves(), - restart: this._sandbox.stub().resolves(), - settings: { - getValidOptionName: this._sandbox.stub(), - get: this._sandbox.stub(), - set: this._sandbox.stub(), - all: {}, - }, - tracer: { - silly: this._sandbox.stub(), - debug: this._sandbox.stub(), - verbose: this._sandbox.stub(), - info: this._sandbox.stub(), - warn: this._sandbox.stub(), - deprecationWarn: this._sandbox.stub(), - error: this._sandbox.stub(), - }, - onChangeSettings: this._sandbox.stub(), - onLoadMocks: this._sandbox.stub(), - addCustomRouter: this._sandbox.stub(), - addCustomSetting: this._sandbox.stub(), - addSetting: this._sandbox.stub(), - addRouter: this._sandbox.stub(), - removeRouter: this._sandbox.stub(), - behaviors: { - count: 0, - collection: "foo-behaviors-collection", - ids: [], - current: {}, - currentId: "foo", - }, - alerts: [], - serverError: null, - _eventEmitter: { - on: this._sandbox.stub(), - removeListener: this._sandbox.stub(), - emit: this._sandbox.stub(), - }, - }; - - Core.mockImplementation(() => this._stubs); - } - - get stubs() { - return { - Constructor: Core, - instance: this._stubs, - }; - } - - restore() { - this._sandbox.restore(); - } - - reset() { - this._sandbox.reset(); - } -} - -module.exports = CoreMock; diff --git a/test/unit/src/About.mocks.js b/test/unit/src/About.mocks.js deleted file mode 100644 index a6cd59e..0000000 --- a/test/unit/src/About.mocks.js +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const sinon = require("sinon"); - -jest.mock("../../../src/About"); - -const About = require("../../../src/About"); - -const Mock = class Mock { - constructor() { - this._sandbox = sinon.createSandbox(); - - this._stubs = { - init: this._sandbox.stub(), - }; - - About.mockImplementation(() => this._stubs); - } - - get stubs() { - return { - Constructor: About, - instance: this._stubs, - }; - } - - restore() { - this._sandbox.restore(); - } -}; - -module.exports = Mock; diff --git a/test/unit/src/About.spec.js b/test/unit/src/About.spec.js deleted file mode 100644 index a4ede59..0000000 --- a/test/unit/src/About.spec.js +++ /dev/null @@ -1,72 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const express = require("express"); -const sinon = require("sinon"); - -const LibMocks = require("../Libs.mocks"); -const CoreMocks = require("../Core.mocks"); - -const About = require("../../../src/About"); -const { version } = require("../../../package.json"); - -describe("About", () => { - let sandbox; - let libMocks; - let coreMock; - let coreInstance; - let resMock; - let about; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - resMock = { - status: sandbox.stub(), - send: sandbox.stub(), - }; - libMocks = new LibMocks(); - coreMock = new CoreMocks(); - coreInstance = coreMock.stubs.instance; - about = new About(coreInstance); - expect.assertions(1); - }); - - afterEach(() => { - sandbox.restore(); - libMocks.restore(); - coreMock.restore(); - }); - - describe("when created", () => { - it("should create an express Router", async () => { - expect(express.Router.calledOnce).toEqual(true); - }); - - it("should have added get router at /", async () => { - expect(libMocks.stubs.express.get.getCall(0).args[0]).toEqual("/"); - }); - }); - - describe("getAbout router", () => { - it("should return current package version", () => { - about.getAbout({}, resMock); - expect(resMock.send.getCall(0).args[0]).toEqual({ - version, - }); - }); - }); - - describe("router getter", () => { - it("should return express created router", async () => { - expect(about.router).toEqual(libMocks.stubs.express); - }); - }); -}); diff --git a/test/unit/src/Alerts.mocks.js b/test/unit/src/Alerts.mocks.js deleted file mode 100644 index 1016f97..0000000 --- a/test/unit/src/Alerts.mocks.js +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2020 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const sinon = require("sinon"); - -jest.mock("../../../src/Alerts"); - -const Alerts = require("../../../src/Alerts"); - -const Mock = class Mock { - constructor() { - this._sandbox = sinon.createSandbox(); - - this._stubs = { - init: this._sandbox.stub(), - }; - - Alerts.mockImplementation(() => this._stubs); - } - - get stubs() { - return { - Constructor: Alerts, - instance: this._stubs, - }; - } - - restore() { - this._sandbox.restore(); - } -}; - -module.exports = Mock; diff --git a/test/unit/src/Alerts.spec.js b/test/unit/src/Alerts.spec.js deleted file mode 100644 index e74ff25..0000000 --- a/test/unit/src/Alerts.spec.js +++ /dev/null @@ -1,152 +0,0 @@ -/* -Copyright 2020 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const express = require("express"); -const sinon = require("sinon"); -const Boom = require("@hapi/boom"); - -const LibMocks = require("../Libs.mocks"); -const CoreMocks = require("../Core.mocks"); - -const Alerts = require("../../../src/Alerts"); - -describe("Alerts", () => { - let sandbox; - let libMocks; - let coreMock; - let coreInstance; - let resMock; - let alerts; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - resMock = { - status: sandbox.stub(), - send: sandbox.stub(), - }; - libMocks = new LibMocks(); - coreMock = new CoreMocks(); - coreInstance = coreMock.stubs.instance; - alerts = new Alerts(coreInstance); - expect.assertions(1); - }); - - afterEach(() => { - sandbox.restore(); - libMocks.restore(); - coreMock.restore(); - }); - - describe("when created", () => { - it("should create an express Router", async () => { - expect(express.Router.calledOnce).toEqual(true); - }); - - it("should have added get router at /", async () => { - expect(libMocks.stubs.express.get.getCall(0).args[0]).toEqual("/"); - }); - - it("should register a get router for alert ids", async () => { - expect(libMocks.stubs.express.get.getCall(1).args[0]).toEqual("/:id"); - }); - }); - - describe("getCollection router", () => { - it("should return the alerts parsed", () => { - expect.assertions(6); - coreInstance.alerts = [ - { - context: "plugins:foo:start", - message: "Foo warning starting plugin", - }, - { - context: "plugins:foo2:stop", - message: "Foo error stopping plugin 2", - error: new Error("Foo error message"), - }, - ]; - alerts = new Alerts(coreInstance); - alerts.getCollection({}, resMock); - expect(resMock.send.getCall(0).args[0][0]).toEqual({ - id: "plugins:foo:start", - context: "plugins:foo:start", - message: "Foo warning starting plugin", - error: null, - }); - expect(resMock.send.getCall(0).args[0][1].id).toEqual("plugins:foo2:stop"); - expect(resMock.send.getCall(0).args[0][1].context).toEqual("plugins:foo2:stop"); - expect(resMock.send.getCall(0).args[0][1].message).toEqual("Foo error stopping plugin 2"); - expect(resMock.send.getCall(0).args[0][1].error.message).toEqual("Foo error message"); - expect(resMock.send.getCall(0).args[0][1].error.stack).toEqual( - expect.stringContaining("test/unit/src/Alerts.spec.js:73:18") - ); - }); - }); - - describe("getModel router", () => { - it("should return the requested alert model parsed", () => { - coreInstance.alerts = [ - { - context: "plugins:foo:start", - message: "Foo warning starting plugin", - }, - { - context: "plugins:foo2:stop", - message: "Foo error stopping plugin 2", - error: new Error("Foo error message"), - }, - ]; - alerts = new Alerts(coreInstance); - alerts.getModel( - { - params: { - id: "plugins:foo:start", - }, - }, - resMock - ); - expect(resMock.send.getCall(0).args[0]).toEqual({ - id: "plugins:foo:start", - context: "plugins:foo:start", - message: "Foo warning starting plugin", - error: null, - }); - }); - - it("should return a not found error if alert is not found", () => { - const nextStub = sandbox.stub(); - sandbox.stub(Boom, "notFound").returns("foo-error"); - coreInstance.alerts = [ - { - context: "plugins:foo:start", - message: "Foo warning starting plugin", - }, - ]; - alerts = new Alerts(coreInstance); - alerts.getModel( - { - params: { - id: "foo", - }, - }, - resMock, - nextStub - ); - expect(nextStub.getCall(0).args[0]).toEqual("foo-error"); - }); - }); - - describe("router getter", () => { - it("should return express created router", async () => { - expect(alerts.router).toEqual(libMocks.stubs.express); - }); - }); -}); diff --git a/test/unit/src/Behaviors.mocks.js b/test/unit/src/Behaviors.mocks.js deleted file mode 100644 index cc2fcf2..0000000 --- a/test/unit/src/Behaviors.mocks.js +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const sinon = require("sinon"); - -jest.mock("../../../src/Behaviors"); - -const Behaviors = require("../../../src/Behaviors"); - -const Mock = class Mock { - constructor() { - this._sandbox = sinon.createSandbox(); - - this._stubs = { - init: this._sandbox.stub(), - }; - - Behaviors.mockImplementation(() => this._stubs); - } - - get stubs() { - return { - Constructor: Behaviors, - instance: this._stubs, - }; - } - - restore() { - this._sandbox.restore(); - } -}; - -module.exports = Mock; diff --git a/test/unit/src/Behaviors.spec.js b/test/unit/src/Behaviors.spec.js deleted file mode 100644 index f71e13b..0000000 --- a/test/unit/src/Behaviors.spec.js +++ /dev/null @@ -1,172 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const express = require("express"); -const sinon = require("sinon"); -const Boom = require("@hapi/boom"); - -const LibMocks = require("../Libs.mocks"); -const CoreMocks = require("../Core.mocks"); - -const Behaviors = require("../../../src/Behaviors"); - -describe("Behavior", () => { - let sandbox; - let libMocks; - let coreMock; - let coreInstance; - let resMock; - let behaviors; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - resMock = { - status: sandbox.stub(), - send: sandbox.stub(), - }; - libMocks = new LibMocks(); - coreMock = new CoreMocks(); - coreInstance = coreMock.stubs.instance; - behaviors = new Behaviors(coreInstance); - expect.assertions(1); - }); - - afterEach(() => { - sandbox.restore(); - libMocks.restore(); - coreMock.restore(); - }); - - describe("when created", () => { - it("should create an express Router", async () => { - expect(express.Router.calledOnce).toEqual(true); - }); - - it("should have added get router at /", async () => { - expect(libMocks.stubs.express.get.getCall(0).args[0]).toEqual("/"); - }); - - it("should register a get router for behavior names", async () => { - expect(libMocks.stubs.express.get.getCall(1).args[0]).toEqual("/:id"); - }); - }); - - describe("getCollection router", () => { - it("should return the behaviors collection parsed", () => { - coreInstance.behaviors = { - collection: [ - { - id: "foo", - name: "foo", - fixtures: [{ id: "foo-fixture-id-1" }, { id: "foo-fixture-id-2" }], - extendedFrom: "foo-base-behavior", - }, - { - id: "foo2", - name: "foo2", - fixtures: [{ id: "foo-fixture-id-3" }], - extendedFrom: null, - }, - ], - }; - behaviors = new Behaviors(coreInstance); - behaviors.getCollection({}, resMock); - expect(resMock.send.getCall(0).args[0]).toEqual([ - { - id: "foo", - name: "foo", - fixtures: ["foo-fixture-id-1", "foo-fixture-id-2"], - extendedFrom: "foo-base-behavior", - }, - { - id: "foo2", - name: "foo2", - fixtures: ["foo-fixture-id-3"], - extendedFrom: null, - }, - ]); - }); - }); - - describe("getModel router", () => { - it("should return the requested behavior model parsed", () => { - coreInstance.behaviors = { - collection: [ - { - id: "foo", - name: "foo", - fixtures: [{ id: "foo-fixture-id-1" }, { id: "foo-fixture-id-2" }], - extendedFrom: "foo-base-behavior", - }, - { - id: "foo2", - name: "foo2", - fixtures: [{ id: "foo-fixture-id-3" }], - extendedFrom: null, - }, - ], - }; - behaviors = new Behaviors(coreInstance); - behaviors.getModel( - { - params: { - id: "foo", - }, - }, - resMock - ); - expect(resMock.send.getCall(0).args[0]).toEqual({ - id: "foo", - name: "foo", - fixtures: ["foo-fixture-id-1", "foo-fixture-id-2"], - extendedFrom: "foo-base-behavior", - }); - }); - - it("should return a not found error if behavior is not found", () => { - const nextStub = sandbox.stub(); - sandbox.stub(Boom, "notFound").returns("foo-error"); - coreInstance.behaviors = { - collection: [ - { - id: "foo", - name: "foo", - fixtures: [{ id: "foo-fixture-id-1" }, { id: "foo-fixture-id-2" }], - extendedFrom: "foo-base-behavior", - }, - { - id: "foo2", - name: "foo2", - fixtures: [{ id: "foo-fixture-id-3" }], - extendedFrom: null, - }, - ], - }; - behaviors = new Behaviors(coreInstance); - behaviors.getModel( - { - params: { - id: "foo3", - }, - }, - resMock, - nextStub - ); - expect(nextStub.getCall(0).args[0]).toEqual("foo-error"); - }); - }); - - describe("router getter", () => { - it("should return express created router", async () => { - expect(behaviors.router).toEqual(libMocks.stubs.express); - }); - }); -}); diff --git a/test/unit/src/Fixtures.mocks.js b/test/unit/src/Fixtures.mocks.js deleted file mode 100644 index f479cca..0000000 --- a/test/unit/src/Fixtures.mocks.js +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const sinon = require("sinon"); - -jest.mock("../../../src/Fixtures"); - -const Fixtures = require("../../../src/Fixtures"); - -const Mock = class Mock { - constructor() { - this._sandbox = sinon.createSandbox(); - - this._stubs = { - init: this._sandbox.stub(), - }; - - Fixtures.mockImplementation(() => this._stubs); - } - - get stubs() { - return { - Constructor: Fixtures, - instance: this._stubs, - }; - } - - restore() { - this._sandbox.restore(); - } -}; - -module.exports = Mock; diff --git a/test/unit/src/Fixtures.spec.js b/test/unit/src/Fixtures.spec.js deleted file mode 100644 index 9645bad..0000000 --- a/test/unit/src/Fixtures.spec.js +++ /dev/null @@ -1,169 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const express = require("express"); -const sinon = require("sinon"); -const Boom = require("@hapi/boom"); - -const LibMocks = require("../Libs.mocks"); -const CoreMocks = require("../Core.mocks"); - -const Fixtures = require("../../../src/Fixtures"); - -describe("Fixtures", () => { - let sandbox; - let libMocks; - let coreMock; - let coreInstance; - let resMock; - let fixtures; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - resMock = { - status: sandbox.stub(), - send: sandbox.stub(), - }; - libMocks = new LibMocks(); - coreMock = new CoreMocks(); - coreInstance = coreMock.stubs.instance; - fixtures = new Fixtures(coreInstance); - expect.assertions(1); - }); - - afterEach(() => { - sandbox.restore(); - libMocks.restore(); - coreMock.restore(); - }); - - describe("when created", () => { - it("should create an express Router", async () => { - expect(express.Router.calledOnce).toEqual(true); - }); - - it("should have added get router at /", async () => { - expect(libMocks.stubs.express.get.getCall(0).args[0]).toEqual("/"); - }); - - it("should register a get router for fixtures ids", async () => { - expect(libMocks.stubs.express.get.getCall(1).args[0]).toEqual("/:id"); - }); - }); - - describe("getCollection router", () => { - it("should return the fixtures collection parsed", () => { - coreInstance.fixtures = { - collection: [ - { - id: "foo-id", - requestMatchId: "request-match-id", - request: "foo-request", - response: "foo-response", - }, - { - id: "foo-id-2", - requestMatchId: "request-match-id-2", - request: "foo-request-2", - response: "foo-response-2", - }, - ], - }; - fixtures = new Fixtures(coreInstance); - fixtures.getCollection({}, resMock); - expect(resMock.send.getCall(0).args[0]).toEqual([ - { - id: "foo-id", - requestMatchId: "request-match-id", - handler: undefined, - request: "foo-request", - response: "foo-response", - }, - { - id: "foo-id-2", - requestMatchId: "request-match-id-2", - handler: undefined, - request: "foo-request-2", - response: "foo-response-2", - }, - ]); - }); - }); - - describe("getModel router", () => { - it("should return the requested fixture model parsed", () => { - coreInstance.fixtures = { - collection: [ - { - id: "foo-id", - requestMatchId: "request-match-id", - request: "foo-request", - response: "foo-response", - }, - { - id: "foo-id-2", - requestMatchId: "request-match-id-2", - request: "foo-request-2", - response: "foo-response-2", - }, - ], - }; - fixtures = new Fixtures(coreInstance); - fixtures.getModel( - { - params: { - id: "foo-id", - }, - }, - resMock - ); - expect(resMock.send.getCall(0).args[0]).toEqual({ - id: "foo-id", - requestMatchId: "request-match-id", - handler: undefined, - request: "foo-request", - response: "foo-response", - }); - }); - - it("should return a not found error if fixture is not found", () => { - const nextStub = sandbox.stub(); - sandbox.stub(Boom, "notFound").returns("foo-error"); - coreInstance.fixtures = { - collection: [ - { - id: "foo-id", - requestMatchId: "request-match-id", - request: "foo-request", - response: "foo-response", - }, - ], - }; - fixtures = new Fixtures(coreInstance); - fixtures.getModel( - { - params: { - id: "foo3", - }, - }, - resMock, - nextStub - ); - expect(nextStub.getCall(0).args[0]).toEqual("foo-error"); - }); - }); - - describe("router getter", () => { - it("should return express created router", async () => { - expect(fixtures.router).toEqual(libMocks.stubs.express); - }); - }); -}); diff --git a/test/unit/src/Plugin.spec.js b/test/unit/src/Plugin.spec.js deleted file mode 100644 index 442e410..0000000 --- a/test/unit/src/Plugin.spec.js +++ /dev/null @@ -1,200 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const express = require("express"); -const sinon = require("sinon"); - -const LibMocks = require("../Libs.mocks"); -const CoreMocks = require("../Core.mocks"); -const DeprecatedApiMocks = require("./deprecated/Api.mocks"); -const SettingsMocks = require("./Settings.mocks"); -const BehaviorsMocks = require("./Behaviors.mocks"); -const AlertsMocks = require("./Alerts.mocks"); -const FixturesMock = require("./Fixtures.mocks"); -const AboutMock = require("./About.mocks"); - -const Plugin = require("../../../src/Plugin"); - -describe("Plugin", () => { - let sandbox; - let libMocks; - let settingsMocks; - let behaviorsMocks; - let alertsMocks; - let fixturesMock; - let deprecatedApiMock; - let deprecatedApiInstance; - let coreMock; - let coreInstance; - let aboutMock; - let plugin; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - libMocks = new LibMocks(); - settingsMocks = new SettingsMocks(); - behaviorsMocks = new BehaviorsMocks(); - alertsMocks = new AlertsMocks(); - aboutMock = new AboutMock(); - fixturesMock = new FixturesMock(); - deprecatedApiMock = new DeprecatedApiMocks(); - deprecatedApiInstance = deprecatedApiMock.stubs.instance; - coreMock = new CoreMocks(); - coreInstance = coreMock.stubs.instance; - plugin = new Plugin(coreInstance); - expect.assertions(1); - }); - - afterEach(() => { - sandbox.restore(); - libMocks.restore(); - settingsMocks.restore(); - behaviorsMocks.restore(); - alertsMocks.restore(); - fixturesMock.restore(); - coreMock.restore(); - aboutMock.restore(); - deprecatedApiMock.restore(); - }); - - describe("display name", () => { - it("should return package name", async () => { - expect(plugin.displayName).toEqual("@mocks-server/plugin-admin-api"); - }); - }); - - describe("when initializated", () => { - it("should create an express Router", async () => { - await plugin.init(); - expect(express.Router.calledOnce).toEqual(true); - }); - - it("should have added adminApiPath setting", async () => { - await plugin.init(); - expect(coreInstance.addSetting.getCall(0).args[0].name).toEqual("adminApiPath"); - }); - - it("should have added adminApiDeprecatedPaths setting", async () => { - await plugin.init(); - expect(coreInstance.addSetting.getCall(1).args[0].name).toEqual("adminApiDeprecatedPaths"); - }); - - it("should init deprecated api", async () => { - await plugin.init(); - expect(deprecatedApiInstance.init.callCount).toEqual(1); - }); - }); - - describe("when started", () => { - it("should add deprecated router if adminApiDeprecatedPaths setting returns true", async () => { - coreInstance.settings.get.withArgs("adminApiDeprecatedPaths").returns(true); - await plugin.init(); - plugin.start(); - expect(coreInstance.addRouter.callCount).toEqual(2); - }); - - it("should not add deprecated router if adminApiDeprecatedPaths setting returns false", async () => { - coreInstance.settings.get.withArgs("adminApiDeprecatedPaths").returns(false); - await plugin.init(); - plugin.start(); - expect(coreInstance.addRouter.callCount).toEqual(1); - }); - - it("should register Express router into the core under the path returned by settings", async () => { - coreInstance.settings.get.withArgs("adminApiPath").returns("/foo"); - await plugin.init(); - plugin.start(); - expect(coreInstance.addRouter.getCall(0).args).toEqual(["/foo", plugin._router]); - }); - }); - - describe("when stopped", () => { - it("should remove deprecated router if it was started", async () => { - expect.assertions(2); - coreInstance.settings.get.withArgs("adminApiDeprecatedPaths").returns(true); - await plugin.init(); - plugin.start(); - plugin.stop(); - expect(coreInstance.removeRouter.callCount).toEqual(1); - expect(coreInstance.removeRouter.getCall(0).args[0]).toEqual("/mocks"); - }); - - it("should remove router if it was started", async () => { - expect.assertions(2); - coreInstance.settings.get.withArgs("adminApiPath").returns("/admin"); - await plugin.init(); - plugin.start(); - plugin.stop(); - expect(coreInstance.removeRouter.callCount).toEqual(1); - expect(coreInstance.removeRouter.getCall(0).args[0]).toEqual("/admin"); - }); - - it("should stop listening to onChangeSettings events", async () => { - const removeListenerSpy = sandbox.spy(); - coreInstance.onChangeSettings.returns(removeListenerSpy); - coreInstance.settings.get.withArgs("adminApiPath").returns("/admin"); - await plugin.init(); - plugin.start(); - plugin.stop(); - expect(removeListenerSpy.callCount).toEqual(1); - }); - }); - - describe("when settings change", () => { - it("should remove deprecated router and add it again if it is enabled and was already registered", async () => { - expect.assertions(2); - coreInstance.settings.get.withArgs("adminApiDeprecatedPaths").returns(true); - await plugin.init(); - plugin.start(); - coreInstance.onChangeSettings.getCall(0).args[0]({ - adminApiDeprecatedPaths: true, - }); - expect(coreInstance.removeRouter.callCount).toEqual(1); - expect(coreInstance.addRouter.callCount).toEqual(3); - }); - - it("should remove deprecated router if it is disabled and was already enabled", async () => { - coreInstance.settings.get.withArgs("adminApiDeprecatedPaths").returns(true); - await plugin.init(); - plugin.start(); - coreInstance.settings.get.withArgs("adminApiDeprecatedPaths").returns(false); - coreInstance.onChangeSettings.getCall(0).args[0]({ - adminApiDeprecatedPaths: false, - }); - expect(coreInstance.removeRouter.callCount).toEqual(1); - }); - - it("should not remove deprecated router if it was not added", async () => { - coreInstance.settings.get.withArgs("adminApiDeprecatedPaths").returns(false); - await plugin.init(); - plugin.start(); - coreInstance.settings.get.withArgs("adminApiDeprecatedPaths").returns(false); - coreInstance.onChangeSettings.getCall(0).args[0]({ - adminApiDeprecatedPaths: false, - }); - expect(coreInstance.removeRouter.callCount).toEqual(0); - }); - - it("should remove and add router again if adminApiPath option changes", async () => { - expect.assertions(3); - coreInstance.settings.get.withArgs("adminApiPath").returns("/foo"); - await plugin.init(); - plugin.start(); - coreInstance.settings.get.withArgs("adminApiPath").returns("/foo2"); - coreInstance.onChangeSettings.getCall(0).args[0]({ - adminApiPath: "/foo2", - }); - expect(coreInstance.removeRouter.callCount).toEqual(1); - expect(coreInstance.addRouter.callCount).toEqual(2); - expect(coreInstance.addRouter.getCall(1).args).toEqual(["/foo2", plugin._router]); - }); - }); -}); diff --git a/test/unit/src/Settings.mocks.js b/test/unit/src/Settings.mocks.js deleted file mode 100644 index 9b2c971..0000000 --- a/test/unit/src/Settings.mocks.js +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const sinon = require("sinon"); - -jest.mock("../../../src/Settings"); - -const Settings = require("../../../src/Settings"); - -const Mock = class Mock { - constructor() { - this._sandbox = sinon.createSandbox(); - - this._stubs = { - init: this._sandbox.stub(), - }; - - Settings.mockImplementation(() => this._stubs); - } - - get stubs() { - return { - Constructor: Settings, - instance: this._stubs, - }; - } - - restore() { - this._sandbox.restore(); - } -}; - -module.exports = Mock; diff --git a/test/unit/src/Settings.spec.js b/test/unit/src/Settings.spec.js deleted file mode 100644 index f976a86..0000000 --- a/test/unit/src/Settings.spec.js +++ /dev/null @@ -1,136 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const express = require("express"); -const sinon = require("sinon"); -const Boom = require("@hapi/boom"); - -const LibMocks = require("../Libs.mocks"); -const CoreMocks = require("../Core.mocks"); - -const Settings = require("../../../src/Settings"); - -describe("Fixtures", () => { - let sandbox; - let libMocks; - let coreMock; - let coreInstance; - let resMock; - let nextStub; - let settings; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - nextStub = sandbox.stub(); - resMock = { - status: sandbox.stub(), - send: sandbox.stub(), - }; - libMocks = new LibMocks(); - coreMock = new CoreMocks(); - coreInstance = coreMock.stubs.instance; - settings = new Settings(coreInstance); - expect.assertions(1); - }); - - afterEach(() => { - sandbox.restore(); - libMocks.restore(); - coreMock.restore(); - }); - - describe("when created", () => { - it("should create an express Router", async () => { - expect(express.Router.calledOnce).toEqual(true); - }); - - it("should have added a patch router at /", async () => { - expect(libMocks.stubs.express.get.getCall(0).args[0]).toEqual("/"); - }); - - it("should have added a get router at /", async () => { - expect(libMocks.stubs.express.get.getCall(0).args[0]).toEqual("/"); - }); - }); - - describe("patch router", () => { - it("should set new settings", () => { - expect.assertions(4); - coreInstance.settings.getValidOptionName.withArgs("log").returns("log"); - coreInstance.settings.getValidOptionName.withArgs("delay").returns("delay"); - settings = new Settings(coreInstance); - settings.patch( - { - body: { - log: "foo", - delay: 4000, - }, - }, - resMock, - nextStub - ); - expect(coreInstance.settings.set.getCall(0).args[0]).toEqual("log"); - expect(coreInstance.settings.set.getCall(0).args[1]).toEqual("foo"); - expect(coreInstance.settings.set.getCall(1).args[0]).toEqual("delay"); - expect(coreInstance.settings.set.getCall(1).args[1]).toEqual(4000); - }); - - it("should send a badRequest error if there is any invalid option", () => { - sandbox.stub(Boom, "badRequest").returns("foo-error"); - coreInstance.settings.getValidOptionName.withArgs("log").returns(null); - coreInstance.settings.getValidOptionName.withArgs("delay").returns("delay"); - settings = new Settings(coreInstance); - settings.patch( - { - body: { - log: "foo", - delay: 4000, - }, - }, - resMock, - nextStub - ); - expect(nextStub.getCall(0).args[0]).toEqual("foo-error"); - }); - - it("should not set any option if one is invalid", () => { - sandbox.stub(Boom, "badRequest").returns("foo-error"); - coreInstance.settings.getValidOptionName.withArgs("log").returns("log"); - coreInstance.settings.getValidOptionName.withArgs("delay").returns(null); - settings = new Settings(coreInstance); - settings.patch( - { - body: { - log: "foo", - delay: 4000, - }, - }, - resMock, - nextStub - ); - expect(coreInstance.settings.set.callCount).toEqual(0); - }); - }); - - describe("get router", () => { - it("should return all settings", () => { - settings = new Settings(coreInstance); - settings.get({}, resMock, nextStub); - expect(resMock.send.getCall(0).args[0]).toEqual(coreInstance.settings.all); - }); - }); - - describe("router getter", () => { - it("should return express created router", async () => { - expect(settings.router).toEqual(libMocks.stubs.express); - }); - }); -}); diff --git a/test/unit/src/deprecated/Api.mocks.js b/test/unit/src/deprecated/Api.mocks.js deleted file mode 100644 index dc00145..0000000 --- a/test/unit/src/deprecated/Api.mocks.js +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const sinon = require("sinon"); - -jest.mock("../../../../src/deprecated/Api"); - -const Api = require("../../../../src/deprecated/Api"); - -const Mock = class Mock { - constructor() { - this._sandbox = sinon.createSandbox(); - - this._stubs = { - init: this._sandbox.stub(), - }; - - Api.mockImplementation(() => this._stubs); - } - - get stubs() { - return { - Constructor: Api, - instance: this._stubs, - }; - } - - restore() { - this._sandbox.restore(); - } -}; - -module.exports = Mock; diff --git a/test/unit/src/deprecated/Api.spec.js b/test/unit/src/deprecated/Api.spec.js deleted file mode 100644 index de24c5c..0000000 --- a/test/unit/src/deprecated/Api.spec.js +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const express = require("express"); -const sinon = require("sinon"); - -const LibsMocks = require("../../Libs.mocks"); -const CoreMocks = require("../../Core.mocks.js"); -const BehaviorsMocks = require("./Behaviors.mocks.js"); -const SettingsMocks = require("./Settings.mocks.js"); - -const Api = require("../../../../src/deprecated/Api"); - -describe("Api", () => { - let sandbox; - let libMocks; - let behaviorsMocks; - let settingsMocks; - let coreMock; - let coreMocks; - let api; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - libMocks = new LibsMocks(); - coreMock = new CoreMocks(); - coreMocks = coreMock.stubs.instance; - behaviorsMocks = new BehaviorsMocks(); - settingsMocks = new SettingsMocks(); - api = new Api(coreMocks); - expect.assertions(1); - }); - - afterEach(() => { - sandbox.restore(); - libMocks.restore(); - behaviorsMocks.restore(); - settingsMocks.restore(); - coreMock.restore(); - }); - - describe("when initializated", () => { - it("should create an express Router", async () => { - await api.init(); - expect(express.Router.calledOnce).toEqual(true); - }); - - it("should create Behaviors passing the core", async () => { - await api.init(); - expect(behaviorsMocks.stubs.Constructor).toHaveBeenCalledWith(coreMocks); - }); - - it('should trace a warning each time any path under "/mocks" is requested', async () => { - expect.assertions(2); - await api.init(); - const nextStub = sandbox.stub(); - libMocks.stubs.express.use.getCall(0).args[0](null, null, nextStub); - expect(nextStub.callCount).toEqual(1); - expect(coreMocks.tracer.deprecationWarn.getCall(0).args[0]).toEqual( - expect.stringContaining('"/mocks" plugin-admin-api path') - ); - }); - - it('should add an express path under "/features"', async () => { - await api.init(); - expect(libMocks.stubs.express.use.getCall(1).args[0]).toEqual("/features"); - }); - - it('should use the created behaviors under the "/features" router path', async () => { - await api.init(); - const fooBehaviorsRouter = "foo-behaviors-router"; - behaviorsMocks.stubs.instance.router = fooBehaviorsRouter; - expect(libMocks.stubs.express.use.getCall(1).args[1]).toEqual(fooBehaviorsRouter); - }); - - it('should add an express path under "/behaviors"', async () => { - await api.init(); - expect(libMocks.stubs.express.use.getCall(2).args[0]).toEqual("/behaviors"); - }); - - it('should use the created behaviors under the "/behaviors" router path', async () => { - await api.init(); - const fooBehaviorsRouter = "foo-behaviors-router"; - behaviorsMocks.stubs.instance.router = fooBehaviorsRouter; - expect(libMocks.stubs.express.use.getCall(2).args[1]).toEqual(fooBehaviorsRouter); - }); - }); - - describe("router getter", () => { - it("should return express created router", async () => { - await api.init(); - expect(api.router).toEqual(libMocks.stubs.express); - }); - }); -}); diff --git a/test/unit/src/deprecated/Behaviors.mocks.js b/test/unit/src/deprecated/Behaviors.mocks.js deleted file mode 100644 index 34c5c27..0000000 --- a/test/unit/src/deprecated/Behaviors.mocks.js +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const sinon = require("sinon"); - -jest.mock("../../../../src/deprecated/Behaviors"); - -const Behaviors = require("../../../../src/deprecated/Behaviors"); - -const Mock = class Mock { - constructor() { - this._sandbox = sinon.createSandbox(); - - this._stubs = { - getCurrent: this._sandbox.stub(), - putCurrent: this._sandbox.stub(), - getCollection: this._sandbox.stub(), - router: "foo-behaviors-router", - }; - - Behaviors.mockImplementation(() => this._stubs); - } - - get stubs() { - return { - Constructor: Behaviors, - instance: this._stubs, - }; - } - - restore() { - this._sandbox.restore(); - } -}; - -module.exports = Mock; diff --git a/test/unit/src/deprecated/Behaviors.spec.js b/test/unit/src/deprecated/Behaviors.spec.js deleted file mode 100644 index 91ccc1f..0000000 --- a/test/unit/src/deprecated/Behaviors.spec.js +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const express = require("express"); -const sinon = require("sinon"); - -const CoreMocks = require("../../Core.mocks.js"); - -const Behaviors = require("../../../../src/deprecated/Behaviors"); - -describe("Behaviors Api", () => { - let sandbox; - let routerStubs; - let resMock; - let statusSpy; - let sendSpy; - let coreMock; - let coreMocks; - let tracerMock; - let behaviors; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - routerStubs = { - get: sandbox.stub(), - put: sandbox.stub(), - }; - coreMock = new CoreMocks(); - coreMocks = coreMock.stubs.instance; - tracerMock = coreMocks.tracer; - sandbox.stub(express, "Router").returns(routerStubs); - statusSpy = sandbox.spy(); - sendSpy = sandbox.spy(); - resMock = { - status: statusSpy, - send: sendSpy, - }; - behaviors = new Behaviors(coreMocks, tracerMock); - expect.assertions(1); - }); - - afterEach(() => { - sandbox.restore(); - coreMock.restore(); - }); - - describe("when instanciated", () => { - it("should create an express Router", () => { - expect(express.Router.calledOnce).toEqual(true); - }); - }); - - describe("getCurrent route", () => { - it("should set response status as 200", () => { - behaviors.getCurrent({}, resMock); - expect(statusSpy.getCall(0).args[0]).toEqual(200); - }); - - it("should send current feature from collection", () => { - behaviors.getCurrent({}, resMock); - expect(sendSpy.getCall(0).args[0]).toEqual(coreMocks.behaviors.currentFromCollection); - }); - }); - - describe("putCurrent route", () => { - it("should set current feature", () => { - behaviors.putCurrent( - { - body: { - name: "foo-name", - }, - }, - resMock - ); - expect(coreMocks.settings.set.getCall(0).args).toEqual(["behavior", "foo-name"]); - }); - - it("should send current feature from collection", () => { - behaviors.putCurrent( - { - body: { - name: "foo-name", - }, - }, - resMock - ); - expect(sendSpy.getCall(0).args[0]).toEqual(coreMocks.behaviors.currentFromCollection); - }); - }); - - describe("getCollection route", () => { - it("should set response status as 200", () => { - behaviors.getCollection({}, resMock); - expect(statusSpy.getCall(0).args[0]).toEqual(200); - }); - - it("should send current behaviors collection", () => { - behaviors.getCollection({}, resMock); - expect(sendSpy.getCall(0).args[0]).toEqual(coreMocks.behaviors.collection); - }); - }); - - describe("router getter", () => { - it("should return the express router", () => { - expect(behaviors.router).toEqual(routerStubs); - }); - }); -}); diff --git a/test/unit/src/deprecated/Settings.mocks.js b/test/unit/src/deprecated/Settings.mocks.js deleted file mode 100644 index 3812528..0000000 --- a/test/unit/src/deprecated/Settings.mocks.js +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const sinon = require("sinon"); - -jest.mock("../../../../src/deprecated/Settings"); - -const Settings = require("../../../../src/deprecated/Settings"); - -const Mock = class Mock { - constructor() { - this._sandbox = sinon.createSandbox(); - - this._stubs = { - get: this._sandbox.stub(), - put: this._sandbox.stub(), - router: "foo-settings-router", - }; - - Settings.mockImplementation(() => this._stubs); - } - - get stubs() { - return { - Constructor: Settings, - instance: this._stubs, - }; - } - - restore() { - this._sandbox.restore(); - } -}; - -module.exports = Mock; diff --git a/test/unit/src/deprecated/Settings.spec.js b/test/unit/src/deprecated/Settings.spec.js deleted file mode 100644 index 6831e9a..0000000 --- a/test/unit/src/deprecated/Settings.spec.js +++ /dev/null @@ -1,114 +0,0 @@ -/* -Copyright 2019 Javier Brea -Copyright 2019 XbyOrange - -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. -*/ - -const express = require("express"); -const sinon = require("sinon"); - -const CoreMocks = require("../../Core.mocks.js"); - -const Settings = require("../../../../src/deprecated/Settings"); - -describe("Settings Api", () => { - let sandbox; - let routerStubs; - let resMock; - let statusSpy; - let sendSpy; - let coreMocks; - let settingsMock; - let tracerMock; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - routerStubs = { - get: sandbox.stub(), - put: sandbox.stub(), - }; - coreMocks = new CoreMocks(); - settingsMock = coreMocks.stubs.instance.settings; - tracerMock = coreMocks.stubs.instance.tracer; - sandbox.stub(express, "Router").returns(routerStubs); - statusSpy = sandbox.spy(); - sendSpy = sandbox.spy(); - resMock = { - status: statusSpy, - send: sendSpy, - }; - expect.assertions(1); - }); - - afterEach(() => { - sandbox.restore(); - coreMocks.restore(); - }); - - describe("when instanciated", () => { - it("should create an express Router", () => { - new Settings(settingsMock, tracerMock); - expect(express.Router.calledOnce).toEqual(true); - }); - }); - - describe("get route", () => { - it("should set response status as 200", () => { - const settings = new Settings(settingsMock, tracerMock); - settings.get({}, resMock); - expect(statusSpy.getCall(0).args[0]).toEqual(200); - }); - - it("should send current settings", () => { - settingsMock.get.withArgs("delay").returns(3000); - const settings = new Settings(settingsMock, tracerMock); - settings.get({}, resMock); - expect(sendSpy.getCall(0).args[0]).toEqual({ - delay: 3000, - }); - }); - }); - - describe("put route", () => { - it("should set current delay", () => { - const settings = new Settings(settingsMock, tracerMock); - settings.put( - { - body: { - delay: 5000, - }, - }, - resMock - ); - expect(settingsMock.set.getCall(0).args).toEqual(["delay", 5000]); - }); - - it("should send current settings", () => { - const settings = new Settings(settingsMock, tracerMock); - settingsMock.get.withArgs("delay").returns(2000); - settings.put( - { - body: { - delay: 2000, - }, - }, - resMock - ); - expect(sendSpy.getCall(0).args[0]).toEqual({ - delay: 2000, - }); - }); - }); - - describe("router getter", () => { - it("should return the express router", () => { - const settings = new Settings(settingsMock, tracerMock); - expect(settings.router).toEqual(routerStubs); - }); - }); -});