diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d87d5e2..7ec19dc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,10 +14,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v2 - - name: Extract branch name - shell: bash - run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF##*/})" - id: extract-branch - name: Use Node.js uses: actions/setup-node@v2 with: @@ -40,11 +36,6 @@ jobs: run: npm run lint - name: Test unit run: npm run test:unit - - name: Test mutation - run: npm run test:mutation - env: - BRANCH_NAME: ${{ steps.extract-branch.outputs.branch }} - STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_TOKEN }} - name: Test E2E run: npm run test:e2e:ci id: test-e2e diff --git a/.github/workflows/test-mutation.yml b/.github/workflows/test-mutation.yml new file mode 100644 index 0000000..ee31f50 --- /dev/null +++ b/.github/workflows/test-mutation.yml @@ -0,0 +1,38 @@ +name: test-mutation +on: + push: + branches: + - main + - release +jobs: + test-mutation: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Extract branch name + shell: bash + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF##*/})" + id: extract-branch + - uses: actions/setup-node@v2 + with: + node-version: '15.x' + registry-url: 'https://registry.npmjs.org/' + - name: Cache node modules + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + # npm cache files are stored in `~/.npm` on Linux/macOS + path: ~/.npm + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + - name: Install dependencies + run: npm ci + - name: Test mutation + run: npm run test:mutation + env: + BRANCH_NAME: ${{ steps.extract-branch.outputs.branch }} + STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index a6cc149..8332ffe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Removed ### BREAKING CHANGES +## [2.3.0] - 2021-04-04 + +### Added +- feat: Add FAIL_FAST_STRATEGY environment variable, allowing to skip tests only in current spec file, in current run or in parallel runs (#29) +- feat: Add configuration allowing to implement fail-fast in parallel runs (#33). + +### Changed +- chore(ci): Separate test mutation job to a new workflow +- chore(deps): Update devDependencies + ## [2.2.2] - 2021-03-30 ### Fixed diff --git a/README.md b/README.md index 3d9e296..e39bbfc 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,18 @@ Enables fail fast in Cypress, skipping the rest of tests on first failure. +It can be configured to skip all remaining tests in current spec file, in current run, or even in parallel runs. + +## Table of Contents + +- [Installation](#installation) +- [Configuration](#configuration) + * [Environment variables](#environment-variables) + * [Configuration by test](#configuration-by-test) + * [Configuration examples for usual scenarios](#configuration-examples-for-usual-scenarios) + * [Configuration for parallel runs](#configuration-for-parallel-runs) +- [Usage with TypeScript](#usage-with-typescript) + ## Installation Add the plugin to `devDependencies` @@ -39,6 +51,10 @@ From now, if one test fail after its last retry, the rest of tests will be skipp ### Environment variables +* __`FAIL_FAST_STRATEGY`__: `'spec'|'run'|'parallel'` + * If `spec`, only remaining tests in current spec file are skipped. + * If `run`, all remaining tests in all spec files are skipped (default value). + * Use `parallel` to [provide your own callbacks](#configuration-for-parallel-runs) allowing to notify from one run to the others when remaining tests should be skipped. * __`FAIL_FAST_ENABLED`__: `boolean = true` Allows disabling the "fail-fast" feature globally, but it could be still enabled for specific tests or describes using [configuration by test](#configuration-by-test). * __`FAIL_FAST_PLUGIN`__: `boolean = true` If `false`, it disables the "fail-fast" feature totally, ignoring even plugin [configurations by test](#configuration-by-test). @@ -54,7 +70,8 @@ or set the "env" key in the `cypress.json` configuration file: { "env": { - "FAIL_FAST_ENABLED": false + "FAIL_FAST_STRATEGY": "run", + "FAIL_FAST_ENABLED": true } } ``` @@ -130,6 +147,46 @@ Set the `FAIL_FAST_PLUGIN` key in your local `cypress.env.json` configuration fi } ``` +### Configuration for parallel runs + +The plugin configuration supports defining two callbacks that, used in combination, allow to skip tests in one run when other run starts skipping tests also. Where, or how do you store the "flag" that allows to communicate your runs is on your hand, the plugin does not care about it. + +To implement it, the plugin can receive an object with extra configuration as third argument when it is registered in the `cypress/plugins/index.js` file: + +* __`parallelCallbacks`__: Object containing next properties: + * __`onCancel`__: `function()` This callback is executed on first test failure that produces the plugin starts skipping tests. + * __`isCancelled`__: `function(): boolean` If this callback returns `true`, the plugin skips remaining tests. + +These callbacks are executed only when the environment variable `FAIL_FAST_STRATEGY` is set to `parallel`. + +Here is an example of configuration that would skip tests on many parallel runs when one of them starts skipping tests. It would only work if all parallel runs have access to the folder where the `isCancelled` flag is being stored as a file (easy to achieve if all of your parallel runs are being executed on Docker images on a same machine, for example). _Note that this is only an example, you could also implement it storing the flag in a REST API, etc._ + +```js +const fs = require("fs"); +const path = require("path"); + +// Flag file is stored in the cypress folder +const isCancelledFlagPath = path.resolve(__dirname, "..", ".run-is-cancelled"); + +module.exports = (on, config) => { + require("cypress-fail-fast/plugin")(on, config, { + parallelCallbacks: { + onCancel: () => { + // Create flag file when the plugin starts skipping tests + fs.writeFileSync(isCancelledFlagPath); + }, + isCancelled: () => { + // If any other run has created the file, start skipping tests + return fs.existsSync(isCancelledFlagPath); + }, + }, + }); + + return config; +}; +``` + +Note that this example requires to remove the created file when all of the runs has finished, or tests will always be skipped whenever any run starts again. So, the `FAIL_FAST_STRATEGY` environment variable should be set to `parallel` only on CI pipelines where the workspace is cleaned on finish, for example. ## Usage with TypeScript diff --git a/package-lock.json b/package-lock.json index 435825d..33f4e29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "cypress-fail-fast", - "version": "2.2.2", + "version": "2.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -13,6 +13,12 @@ "@babel/highlight": "^7.10.4" } }, + "@babel/compat-data": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.12.tgz", + "integrity": "sha512-3eJJ841uKxeV8dcN/2yGEUy+RfgQspPEgQat85umsE1rotuquQ2AbIub4S6j7c50a2d+4myc+zSlnXeIHrOnhQ==", + "dev": true + }, "@babel/core": { "version": "7.11.6", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", @@ -64,16 +70,36 @@ } } }, + "@babel/helper-compilation-targets": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.13.tgz", + "integrity": "sha512-q1kcdHNZehBwD9jYPh3WyXcsFERi39X4I59I3NadciWtNDyZ6x+GboOxncFK0kXlKIv6BJm5acncehXWUjWQMQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.12", + "@babel/helper-validator-option": "^7.12.17", + "browserslist": "^4.14.5", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "@babel/helper-create-class-features-plugin": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.17.tgz", - "integrity": "sha512-I/nurmTxIxHV0M+rIpfQBF1oN342+yvl2kwZUrQuOClMamHF1w5tknfZubgNOLRoA73SzBFAdFcpb4M9HwOeWQ==", + "version": "7.13.11", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.11.tgz", + "integrity": "sha512-ays0I7XYq9xbjCSvT+EvysLgfc3tOkwCULHjrnscGT3A9qD4sk3wXnJ3of0MAWsWGjdinFvajHU2smYuqXKMrw==", "dev": true, "requires": { "@babel/helper-function-name": "^7.12.13", - "@babel/helper-member-expression-to-functions": "^7.12.17", + "@babel/helper-member-expression-to-functions": "^7.13.0", "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/helper-replace-supers": "^7.12.13", + "@babel/helper-replace-supers": "^7.13.0", "@babel/helper-split-export-declaration": "^7.12.13" }, "dependencies": { @@ -87,12 +113,12 @@ } }, "@babel/generator": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.17.tgz", - "integrity": "sha512-DSA7ruZrY4WI8VxuS1jWSRezFnghEoYEFrZcw9BizQRmOZiUsiHl59+qEARGPqPikwA/GPTyRCi7isuCK/oyqg==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", "dev": true, "requires": { - "@babel/types": "^7.12.17", + "@babel/types": "^7.13.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" } @@ -118,12 +144,12 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.17.tgz", - "integrity": "sha512-Bzv4p3ODgS/qpBE0DiJ9qf5WxSmrQ8gVTe8ClMfwwsY2x/rhykxxy3bXzG7AGTnPB2ij37zGJ/Q/6FruxHxsxg==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz", + "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==", "dev": true, "requires": { - "@babel/types": "^7.12.17" + "@babel/types": "^7.13.12" } }, "@babel/helper-optimise-call-expression": { @@ -136,15 +162,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.13.tgz", - "integrity": "sha512-pctAOIAMVStI2TMLhozPKbf5yTEXc0OJa0eENheb4w09SrgOWEs+P4nTOZYJQCqs8JlErGLDPDJTiGIp3ygbLg==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz", + "integrity": "sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.12.13", + "@babel/helper-member-expression-to-functions": "^7.13.12", "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/traverse": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.12" } }, "@babel/helper-split-export-declaration": { @@ -163,9 +189,9 @@ "dev": true }, "@babel/highlight": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz", - "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==", + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", @@ -174,9 +200,9 @@ } }, "@babel/parser": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.17.tgz", - "integrity": "sha512-r1yKkiUTYMQ8LiEI0UcQx5ETw5dpTLn9wijn9hk6KkTtOK95FndDN10M+8/s6k/Ymlbivw0Av9q4SlgF80PtHg==", + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", "dev": true }, "@babel/template": { @@ -191,26 +217,25 @@ } }, "@babel/traverse": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.17.tgz", - "integrity": "sha512-LGkTqDqdiwC6Q7fWSwQoas/oyiEYw6Hqjve5KOSykXkmFJFqzvGMb9niaUEag3Rlve492Mkye3gLw9FTv94fdQ==", + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz", + "integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.12.17", + "@babel/generator": "^7.13.9", "@babel/helper-function-name": "^7.12.13", "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.12.17", - "@babel/types": "^7.12.17", + "@babel/parser": "^7.13.13", + "@babel/types": "^7.13.13", "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" + "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.17.tgz", - "integrity": "sha512-tNMDjcv/4DIcHxErTgwB9q2ZcYyN0sUfgGKUK/mm1FJK7Wz+KstoEekxrl/tBiNDgLK1HGi+sppj1An/1DR4fQ==", + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", @@ -391,56 +416,56 @@ "dev": true }, "@babel/plugin-proposal-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.13.tgz", - "integrity": "sha512-8SCJ0Ddrpwv4T7Gwb33EmW1V9PY5lggTO+A8WjyIwxrSHDUyBw4MtF96ifn1n8H806YlxbVCoKXbbmzD6RD+cA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.13.0.tgz", + "integrity": "sha512-KnTDjFNC1g+45ka0myZNvSBFLhNCLN+GeGYLDEA8Oq7MZ6yMgfLoIRh86GRT0FjtJhZw8JyUskP9uvj5pHM9Zg==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-create-class-features-plugin": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0" }, "dependencies": { "@babel/helper-plugin-utils": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz", - "integrity": "sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", + "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", "dev": true } } }, "@babel/plugin-proposal-decorators": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.12.13.tgz", - "integrity": "sha512-x2aOr5w4ARJoYHFKoG2iEUL/Xe99JAJXjAasHijXp3/KgaetJXGE62SmHgsW3Tia/XUT5AxF2YC0F+JyhPY/0Q==", + "version": "7.13.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.13.5.tgz", + "integrity": "sha512-i0GDfVNuoapwiheevUOuSW67mInqJ8qw7uWfpjNVeHMn143kXblEy/bmL9AdZ/0yf/4BMQeWXezK0tQIvNPqag==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-create-class-features-plugin": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/plugin-syntax-decorators": "^7.12.13" }, "dependencies": { "@babel/helper-plugin-utils": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz", - "integrity": "sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", + "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", "dev": true } } }, "@babel/plugin-proposal-private-methods": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.13.tgz", - "integrity": "sha512-sV0V57uUwpauixvR7s2o75LmwJI6JECwm5oPUY5beZB1nBl2i37hc7CJGqB5G+58fur5Y6ugvl3LRONk5x34rg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.13.0.tgz", + "integrity": "sha512-MXyyKQd9inhx1kDYPkFRVOBXQ20ES8Pto3T7UZ92xj2mY0EVD8oAVzeyYuVfy/mxAdTSIayOvg+aVzcHV2bn6Q==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-create-class-features-plugin": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0" }, "dependencies": { "@babel/helper-plugin-utils": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz", - "integrity": "sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", + "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", "dev": true } } @@ -482,9 +507,9 @@ }, "dependencies": { "@babel/helper-plugin-utils": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz", - "integrity": "sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", + "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", "dev": true } } @@ -580,47 +605,47 @@ }, "dependencies": { "@babel/helper-plugin-utils": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz", - "integrity": "sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", + "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", "dev": true } } }, "@babel/plugin-transform-typescript": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.17.tgz", - "integrity": "sha512-1bIYwnhRoetxkFonuZRtDZPFEjl1l5r+3ITkxLC3mlMaFja+GQFo94b/WHEPjqWLU9Bc+W4oFZbvCGe9eYMu1g==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.13.0.tgz", + "integrity": "sha512-elQEwluzaU8R8dbVuW2Q2Y8Nznf7hnjM7+DSCd14Lo5fF63C9qNLbwZYbmZrtV9/ySpSUpkRpQXvJb6xyu4hCQ==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.12.17", - "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-create-class-features-plugin": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/plugin-syntax-typescript": "^7.12.13" }, "dependencies": { "@babel/helper-plugin-utils": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz", - "integrity": "sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", + "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", "dev": true } } }, "@babel/preset-typescript": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.12.17.tgz", - "integrity": "sha512-T513uT4VSThRcmWeqcLkITKJ1oGQho9wfWuhQm10paClQkp1qyd0Wf8mvC8Se7UYssMyRSj4tZYpVTkCmAK/mA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.13.0.tgz", + "integrity": "sha512-LXJwxrHy0N3f6gIJlYbLta1D9BDtHpQeqwzM0LIfjDlr6UE/D5Mc7W4iDiQzaE+ks0sTjT26ArcHWnJVt0QiHw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/helper-validator-option": "^7.12.17", - "@babel/plugin-transform-typescript": "^7.12.17" + "@babel/plugin-transform-typescript": "^7.13.0" }, "dependencies": { "@babel/helper-plugin-utils": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz", - "integrity": "sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", + "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", "dev": true } } @@ -714,9 +739,9 @@ } }, "@eslint/eslintrc": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", - "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", + "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -726,7 +751,6 @@ "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^3.13.1", - "lodash": "^4.17.20", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, @@ -1027,9 +1051,9 @@ "dev": true }, "@stryker-mutator/api": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@stryker-mutator/api/-/api-4.4.1.tgz", - "integrity": "sha512-qjkkdsOepy0NEGyxU2hvqQ70JFBaukkCO1MoWdG1e2oWpPQaTYNF+1W38fOF0QWGO0FVm50cA0wbf7Apqp5wIA==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@stryker-mutator/api/-/api-4.5.1.tgz", + "integrity": "sha512-gi4fg3XXp37su+d4t0J9mAXa9qYr4v/sFo5mtI0VXaE0ApHNwnyvZcrVHKjj1yw2V54EQIp4a2l79Sn2dhHF3Q==", "dev": true, "requires": { "mutation-testing-report-schema": "~1.5.2", @@ -1038,17 +1062,17 @@ } }, "@stryker-mutator/core": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@stryker-mutator/core/-/core-4.4.1.tgz", - "integrity": "sha512-xGH/GmKDgB4O8tqZx+N0dNhwuG7li13Yzv7Tqz/VIe3CTuTjoKFrmLq4UnsL9yA/DBbNfjgILBdY8BMNHr9kXA==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@stryker-mutator/core/-/core-4.5.1.tgz", + "integrity": "sha512-T5lJwoNOW88XiBiEYKi5L0u2QYZ1PewoPU5dpi7fyOlOXhTUnSZv00fZfBtLwaGgfk4knWbehD8mxBnlnsvhhA==", "dev": true, "requires": { - "@stryker-mutator/api": "4.4.1", - "@stryker-mutator/instrumenter": "4.4.1", - "@stryker-mutator/util": "4.4.1", - "ajv": "~7.0.2", + "@stryker-mutator/api": "4.5.1", + "@stryker-mutator/instrumenter": "4.5.1", + "@stryker-mutator/util": "4.5.1", + "ajv": "~7.1.0", "chalk": "~4.1.0", - "commander": "~7.0.0", + "commander": "~7.1.0", "execa": "~5.0.0", "file-url": "~3.0.0", "get-port": "~5.0.0", @@ -1074,9 +1098,9 @@ }, "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==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.1.1.tgz", + "integrity": "sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -1123,22 +1147,22 @@ } }, "@stryker-mutator/instrumenter": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@stryker-mutator/instrumenter/-/instrumenter-4.4.1.tgz", - "integrity": "sha512-JQrEgUrUBDfofNAeBdojjnqWJbZRHw8aqX+yRO9tsR5dHX3iSkLrYQs1UTOP0JuBYqnStIeJW2pnDQnjh0z3cw==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@stryker-mutator/instrumenter/-/instrumenter-4.5.1.tgz", + "integrity": "sha512-U+44GJIEJAejQ375I/Q6Es2garBsnC2pZWtWhkO+9gsK/Ev3ftASfWSwi12NTqmQPbY8Hh8NKZjoXoRA9GD1qw==", "dev": true, "requires": { - "@babel/core": "~7.12.3", - "@babel/generator": "~7.12.1", - "@babel/parser": "~7.12.3", + "@babel/core": "~7.13.10", + "@babel/generator": "~7.13.0", + "@babel/parser": "~7.13.10", "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-decorators": "~7.12.1 ", + "@babel/plugin-proposal-decorators": "~7.13.5 ", "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/preset-typescript": "~7.12.1 ", - "@stryker-mutator/api": "4.4.1", - "@stryker-mutator/util": "4.4.1", + "@babel/preset-typescript": "~7.13.0 ", + "@stryker-mutator/api": "4.5.1", + "@stryker-mutator/util": "4.5.1", "angular-html-parser": "~1.7.0", - "weapon-regex": "~0.3.0" + "weapon-regex": "~0.4.1" }, "dependencies": { "@babel/code-frame": { @@ -1151,35 +1175,35 @@ } }, "@babel/core": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.17.tgz", - "integrity": "sha512-V3CuX1aBywbJvV2yzJScRxeiiw0v2KZZYYE3giywxzFJL13RiyPjaaDwhDnxmgFTTS7FgvM2ijr4QmKNIu0AtQ==", + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.14.tgz", + "integrity": "sha512-wZso/vyF4ki0l0znlgM4inxbdrUvCb+cVz8grxDq+6C9k6qbqoIJteQOKicaKjCipU3ISV+XedCqpL2RJJVehA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.12.17", - "@babel/helper-module-transforms": "^7.12.17", - "@babel/helpers": "^7.12.17", - "@babel/parser": "^7.12.17", + "@babel/generator": "^7.13.9", + "@babel/helper-compilation-targets": "^7.13.13", + "@babel/helper-module-transforms": "^7.13.14", + "@babel/helpers": "^7.13.10", + "@babel/parser": "^7.13.13", "@babel/template": "^7.12.13", - "@babel/traverse": "^7.12.17", - "@babel/types": "^7.12.17", + "@babel/traverse": "^7.13.13", + "@babel/types": "^7.13.14", "convert-source-map": "^1.7.0", "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", + "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", - "lodash": "^4.17.19", - "semver": "^5.4.1", + "semver": "^6.3.0", "source-map": "^0.5.0" } }, "@babel/generator": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.17.tgz", - "integrity": "sha512-DSA7ruZrY4WI8VxuS1jWSRezFnghEoYEFrZcw9BizQRmOZiUsiHl59+qEARGPqPikwA/GPTyRCi7isuCK/oyqg==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", "dev": true, "requires": { - "@babel/types": "^7.12.17", + "@babel/types": "^7.13.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" } @@ -1205,38 +1229,37 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.17.tgz", - "integrity": "sha512-Bzv4p3ODgS/qpBE0DiJ9qf5WxSmrQ8gVTe8ClMfwwsY2x/rhykxxy3bXzG7AGTnPB2ij37zGJ/Q/6FruxHxsxg==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz", + "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==", "dev": true, "requires": { - "@babel/types": "^7.12.17" + "@babel/types": "^7.13.12" } }, "@babel/helper-module-imports": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz", - "integrity": "sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", + "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", "dev": true, "requires": { - "@babel/types": "^7.12.13" + "@babel/types": "^7.13.12" } }, "@babel/helper-module-transforms": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.17.tgz", - "integrity": "sha512-sFL+p6zOCQMm9vilo06M4VHuTxUAwa6IxgL56Tq1DVtA0ziAGTH1ThmJq7xwPqdQlgAbKX3fb0oZNbtRIyA5KQ==", + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz", + "integrity": "sha512-QuU/OJ0iAOSIatyVZmfqB0lbkVP0kDRiKj34xy+QNsnVZi/PA6BoSoreeqnxxa9EHFAIL0R9XOaAR/G9WlIy5g==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-replace-supers": "^7.12.13", - "@babel/helper-simple-access": "^7.12.13", + "@babel/helper-module-imports": "^7.13.12", + "@babel/helper-replace-supers": "^7.13.12", + "@babel/helper-simple-access": "^7.13.12", "@babel/helper-split-export-declaration": "^7.12.13", "@babel/helper-validator-identifier": "^7.12.11", "@babel/template": "^7.12.13", - "@babel/traverse": "^7.12.17", - "@babel/types": "^7.12.17", - "lodash": "^4.17.19" + "@babel/traverse": "^7.13.13", + "@babel/types": "^7.13.14" } }, "@babel/helper-optimise-call-expression": { @@ -1249,24 +1272,24 @@ } }, "@babel/helper-replace-supers": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.13.tgz", - "integrity": "sha512-pctAOIAMVStI2TMLhozPKbf5yTEXc0OJa0eENheb4w09SrgOWEs+P4nTOZYJQCqs8JlErGLDPDJTiGIp3ygbLg==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz", + "integrity": "sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.12.13", + "@babel/helper-member-expression-to-functions": "^7.13.12", "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/traverse": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.12" } }, "@babel/helper-simple-access": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.13.tgz", - "integrity": "sha512-0ski5dyYIHEfwpWGx5GPWhH35j342JaflmCeQmsPWcrOQDtCN6C1zKAVRFVbK53lPW2c9TsuLLSUDf0tIGJ5hA==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz", + "integrity": "sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA==", "dev": true, "requires": { - "@babel/types": "^7.12.13" + "@babel/types": "^7.13.12" } }, "@babel/helper-split-export-declaration": { @@ -1285,20 +1308,20 @@ "dev": true }, "@babel/helpers": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.17.tgz", - "integrity": "sha512-tEpjqSBGt/SFEsFikKds1sLNChKKGGR17flIgQKXH4fG6m9gTgl3gnOC1giHNyaBCSKuTfxaSzHi7UnvqiVKxg==", + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.10.tgz", + "integrity": "sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ==", "dev": true, "requires": { "@babel/template": "^7.12.13", - "@babel/traverse": "^7.12.17", - "@babel/types": "^7.12.17" + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" } }, "@babel/highlight": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz", - "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==", + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", @@ -1307,9 +1330,9 @@ } }, "@babel/parser": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.17.tgz", - "integrity": "sha512-r1yKkiUTYMQ8LiEI0UcQx5ETw5dpTLn9wijn9hk6KkTtOK95FndDN10M+8/s6k/Ymlbivw0Av9q4SlgF80PtHg==", + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", "dev": true }, "@babel/template": { @@ -1324,26 +1347,25 @@ } }, "@babel/traverse": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.17.tgz", - "integrity": "sha512-LGkTqDqdiwC6Q7fWSwQoas/oyiEYw6Hqjve5KOSykXkmFJFqzvGMb9niaUEag3Rlve492Mkye3gLw9FTv94fdQ==", + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz", + "integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.12.17", + "@babel/generator": "^7.13.9", "@babel/helper-function-name": "^7.12.13", "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.12.17", - "@babel/types": "^7.12.17", + "@babel/parser": "^7.13.13", + "@babel/types": "^7.13.13", "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" + "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.17.tgz", - "integrity": "sha512-tNMDjcv/4DIcHxErTgwB9q2ZcYyN0sUfgGKUK/mm1FJK7Wz+KstoEekxrl/tBiNDgLK1HGi+sppj1An/1DR4fQ==", + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", @@ -1362,6 +1384,12 @@ "supports-color": "^5.3.0" } }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -1371,13 +1399,13 @@ } }, "@stryker-mutator/jest-runner": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@stryker-mutator/jest-runner/-/jest-runner-4.4.1.tgz", - "integrity": "sha512-5sNE+kGaHe6pFK8D4t0WFM9Qx05ZvCdRkadcnHff+RvMCmVqRd4mUvH/VU35FPsrnBZb/IhnhP2wydijyc9e4w==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@stryker-mutator/jest-runner/-/jest-runner-4.5.1.tgz", + "integrity": "sha512-ei0YWdf3tjShChvU5cBBET3Eqa3PfshcfHxAG/RgYgrfZYGHL1GnT5dsGLojf4b5TEPY12Q9HVkSnsnoFvW5mQ==", "dev": true, "requires": { - "@stryker-mutator/api": "4.4.1", - "@stryker-mutator/util": "4.4.1", + "@stryker-mutator/api": "4.5.1", + "@stryker-mutator/util": "4.5.1", "semver": "~6.3.0", "tslib": "~2.1.0" }, @@ -1391,9 +1419,9 @@ } }, "@stryker-mutator/util": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@stryker-mutator/util/-/util-4.4.1.tgz", - "integrity": "sha512-F0IFpjU6cc4H/exn8iI08QLqa7d5yLod+p5lI0IeddzQJQCs0ztMX5g9zqLU7nTCTcEbL2XgI9S8815/YbNjDQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@stryker-mutator/util/-/util-4.5.1.tgz", + "integrity": "sha512-oURW2MDXntOjRke9FxmhMAjULtPr3r8unwVAN6vxIBdOOC/50hNKgu/+rHgFwIcTRsF7mg9axeYZ4PwKzlSz9Q==", "dev": true, "requires": { "lodash.flatmap": "~4.5.0" @@ -1667,16 +1695,39 @@ "dev": true }, "array-includes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", - "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "get-intrinsic": "^1.0.1", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", "is-string": "^1.0.5" + }, + "dependencies": { + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + } } }, "array-unique": { @@ -1928,6 +1979,19 @@ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, + "browserslist": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz", + "integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001181", + "colorette": "^1.2.1", + "electron-to-chromium": "^1.3.649", + "escalade": "^3.1.1", + "node-releases": "^1.1.70" + } + }, "bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", @@ -1982,6 +2046,12 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "caniuse-lite": { + "version": "1.0.30001204", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001204.tgz", + "integrity": "sha512-JUdjWpcxfJ9IPamy2f5JaRDCaqJOxDzOSKtbdx4rH9VivMd1vIzoPumsJa9LoMIi4Fx2BV2KZOxWhNkBjaYivQ==", + "dev": true + }, "capture-exit": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", @@ -2211,6 +2281,12 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2221,9 +2297,9 @@ } }, "commander": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.0.0.tgz", - "integrity": "sha512-ovx/7NkTrnPuIV8sqk/GjUIIM1+iUQeqA3ye2VNpq9sVoiZsooObWlQy+OPWGI17GDaEoybuAGJm6U8yC077BA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz", + "integrity": "sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg==", "dev": true }, "compare-versions": { @@ -2493,6 +2569,12 @@ "safer-buffer": "^2.1.0" } }, + "electron-to-chromium": { + "version": "1.3.703", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.703.tgz", + "integrity": "sha512-SVBVhNB+4zPL+rvtWLw7PZQkw/Eqj1HQZs22xtcqW36+xoifzEOEEDEpkxSMfB6RFeSIOcG00w6z5mSqLr1Y6w==", + "dev": true + }, "emittery": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz", @@ -2533,23 +2615,56 @@ } }, "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" + }, + "dependencies": { + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + } } }, "es-to-primitive": { @@ -2563,6 +2678,12 @@ "is-symbol": "^1.0.2" } }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -2631,13 +2752,13 @@ } }, "eslint": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.20.0.tgz", - "integrity": "sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.23.0.tgz", + "integrity": "sha512-kqvNVbdkjzpFy0XOszNwjkKzZ+6TcwCQ/h+ozlcIWwaimBBuhlQ4nN6kbiM2L+OjDcznkTJxzYfRFH92sx4a0Q==", "dev": true, "requires": { "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.3.0", + "@eslint/eslintrc": "^0.4.0", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -2650,10 +2771,10 @@ "espree": "^7.3.1", "esquery": "^1.4.0", "esutils": "^2.0.2", - "file-entry-cache": "^6.0.0", + "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", - "globals": "^12.1.0", + "globals": "^13.6.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", @@ -2661,7 +2782,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.20", + "lodash": "^4.17.21", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -2691,27 +2812,33 @@ "dev": true }, "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.7.0.tgz", + "integrity": "sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "type-fest": "^0.20.2" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true } } @@ -2732,22 +2859,23 @@ } }, "eslint-plugin-react": { - "version": "7.22.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", - "integrity": "sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==", + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.23.1.tgz", + "integrity": "sha512-MvFGhZjI8Z4HusajmSw0ougGrq3Gs4vT/0WgwksZgf5RrLrRa2oYAw56okU4tZJl8+j7IYNuTM+2RnFEuTSdRQ==", "dev": true, "requires": { - "array-includes": "^3.1.1", - "array.prototype.flatmap": "^1.2.3", + "array-includes": "^3.1.3", + "array.prototype.flatmap": "^1.2.4", "doctrine": "^2.1.0", "has": "^1.0.3", "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "object.entries": "^1.1.2", - "object.fromentries": "^2.0.2", - "object.values": "^1.1.1", + "minimatch": "^3.0.4", + "object.entries": "^1.1.3", + "object.fromentries": "^2.0.4", + "object.values": "^1.1.3", "prop-types": "^15.7.2", - "resolve": "^1.18.1", - "string.prototype.matchall": "^4.0.2" + "resolve": "^2.0.0-next.3", + "string.prototype.matchall": "^4.0.4" }, "dependencies": { "doctrine": { @@ -2758,6 +2886,16 @@ "requires": { "esutils": "^2.0.2" } + }, + "resolve": { + "version": "2.0.0-next.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz", + "integrity": "sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } } } }, @@ -3337,9 +3475,9 @@ } }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -3389,6 +3527,12 @@ "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -3642,33 +3786,25 @@ } }, "internal-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", - "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", "dev": true, "requires": { - "es-abstract": "^1.17.0-next.1", + "get-intrinsic": "^1.1.0", "has": "^1.0.3", - "side-channel": "^1.0.2" + "side-channel": "^1.0.4" }, "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "dev": true, "requires": { - "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "has-symbols": "^1.0.1" } } } @@ -3705,6 +3841,21 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", + "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "dev": true + }, + "is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -3712,9 +3863,9 @@ "dev": true }, "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", "dev": true }, "is-ci": { @@ -3832,6 +3983,12 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", @@ -3854,12 +4011,25 @@ "dev": true }, "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", "dev": true, "requires": { + "call-bind": "^1.0.2", "has-symbols": "^1.0.1" + }, + "dependencies": { + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + } } }, "is-regexp": { @@ -4780,12 +4950,24 @@ "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "dev": true }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, "lodash.flatmap": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz", "integrity": "sha1-74y/QI9uSCaGYzRTBcaswLd4cC4=", "dev": true }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", @@ -4804,6 +4986,12 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, "log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -5096,6 +5284,12 @@ } } }, + "node-releases": { + "version": "1.1.71", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", + "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", + "dev": true + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -5218,15 +5412,27 @@ } }, "object.fromentries": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.3.tgz", - "integrity": "sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.4.tgz", + "integrity": "sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has": "^1.0.3" + }, + "dependencies": { + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + } } }, "object.pick": { @@ -5239,15 +5445,27 @@ } }, "object.values": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", - "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", + "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has": "^1.0.3" + }, + "dependencies": { + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + } } }, "once": { @@ -5579,10 +5797,13 @@ "dev": true }, "qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", - "dev": true + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } }, "react-is": { "version": "16.13.1", @@ -5640,32 +5861,23 @@ } }, "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" }, "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "requires": { - "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "get-intrinsic": "^1.0.2" } } } @@ -5824,9 +6036,9 @@ "dev": true }, "rfdc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.2.0.tgz", - "integrity": "sha512-ijLyszTMmUrXvjSooucVQwimGUk84eRcmCuLV8Xghe3UO85mjUtRAHRyoMM6XtyqbECaXuBWx18La3523sXINA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", "dev": true }, "rimraf": { @@ -6207,16 +6419,16 @@ "dev": true }, "sinon": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", - "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", + "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", "dev": true, "requires": { "@sinonjs/commons": "^1.8.1", "@sinonjs/fake-timers": "^6.0.1", "@sinonjs/samsam": "^5.3.1", "diff": "^4.0.2", - "nise": "^4.0.4", + "nise": "^4.1.0", "supports-color": "^7.1.0" }, "dependencies": { @@ -6612,38 +6824,74 @@ } }, "string.prototype.matchall": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz", - "integrity": "sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.4.tgz", + "integrity": "sha512-pknFIWVachNcyqRfaQSeu/FUfpvJTe4uskUSZ9Wc1RijsPuzbZ8TyYT8WCNnntCjUEqQ3vUHMAfVj2+wLAisPQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has-symbols": "^1.0.1", - "internal-slot": "^1.0.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.3" + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.3.1", + "side-channel": "^1.0.4" + }, + "dependencies": { + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + } } }, "string.prototype.trimend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", - "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" + }, + "dependencies": { + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + } } }, "string.prototype.trimstart": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", - "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" + }, + "dependencies": { + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + } } }, "stringify-object": { @@ -6739,21 +6987,26 @@ "dev": true }, "table": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", - "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", - "dev": true, - "requires": { - "ajv": "^7.0.2", - "lodash": "^4.17.20", + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/table/-/table-6.0.9.tgz", + "integrity": "sha512-F3cLs9a3hL1Z7N4+EkSscsel3z55XT950AvB05bwayrNg5T1/gykXtigioTAjbltvbMSJvvhFCbnf6mX+ntnJQ==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "lodash.clonedeep": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", "string-width": "^4.2.0" }, "dependencies": { "ajv": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.1.1.tgz", - "integrity": "sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.0.1.tgz", + "integrity": "sha512-46ZA4TalFcLLqX1dEU3dhdY38wAtDydJ4e7QQTVekLUTzXkb1LfqU6VOBXC/a9wiv4T094WURqJH6ZitF92Kqw==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -6951,9 +7204,9 @@ "dev": true }, "typed-rest-client": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.1.tgz", - "integrity": "sha512-7JbJFBZZuu3G64u6ksklN1xtVGfqBKiR5MQoTe5oLTi68OyB6pRuuIQCllfK/BdGjQtZYp62rgUOnEYDz4e9Xg==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.3.tgz", + "integrity": "sha512-gJoH7RE3trY77Bf5MNezVV+21O/WMmt9ps7w1bjFyLxrQqDymDWJSDacem1eM6R86zFM0FlE07F8dOupLmKLmQ==", "dev": true, "requires": { "qs": "^6.9.1", @@ -6970,6 +7223,26 @@ "is-typedarray": "^1.0.0" } }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "dependencies": { + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + } + } + }, "underscore": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", @@ -7062,9 +7335,9 @@ "dev": true }, "v8-compile-cache": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", - "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, "v8-to-istanbul": { @@ -7127,9 +7400,9 @@ } }, "weapon-regex": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/weapon-regex/-/weapon-regex-0.3.0.tgz", - "integrity": "sha512-IctFbNWZJ7n8mBmEqVAdirWZbLhFlv+2so3FEiZjhzlUuhs07drvKHXiU+DppO8Fz/EbYfbcTt7HGeNzinXUlw==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/weapon-regex/-/weapon-regex-0.4.1.tgz", + "integrity": "sha512-25QYfAcXcK1wRBKzc6L7NeyDyHdrMGmT50yib0cI4c1k9D0AwNc+yxshk1jEo7Ib2gEfJngoauIMkiU++BsLLg==", "dev": true }, "webidl-conversions": { @@ -7173,6 +7446,19 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", diff --git a/package.json b/package.json index eb0662e..7d02a2d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cypress-fail-fast", - "version": "2.2.2", + "version": "2.3.0", "description": "Skip the rest of Cypress tests on first failure", "keywords": [ "cypress", @@ -8,9 +8,11 @@ "fail-fast", "failure", "skip", + "cancel", "tests", "testing-tools", - "testing" + "testing", + "parallel" ], "author": "Javier Brea", "license": "MIT", @@ -38,18 +40,18 @@ "cypress": "5.x || 6.x" }, "devDependencies": { - "@stryker-mutator/core": "4.4.1", - "@stryker-mutator/jest-runner": "4.4.1", + "@stryker-mutator/core": "4.5.1", + "@stryker-mutator/jest-runner": "4.5.1", "babel-eslint": "10.1.0", - "eslint": "7.20.0", + "eslint": "7.23.0", "eslint-config-prettier": "8.1.0", "eslint-plugin-prettier": "3.3.1", - "eslint-plugin-react": "7.22.0", + "eslint-plugin-react": "7.23.1", "husky": "4.3.8", "jest": "26.6.3", "lint-staged": "10.5.4", "prettier": "2.2.1", - "sinon": "9.2.4" + "sinon": "10.0.0" }, "lint-staged": { "*.js": "eslint", diff --git a/plugin.d.ts b/plugin.d.ts index ae47463..75d6975 100644 --- a/plugin.d.ts +++ b/plugin.d.ts @@ -1,11 +1,35 @@ /// +interface FailFastParallelCallbacks { + /** + * onCancel callback. + * Callback that will be executed on first test failure producing that cypress-fail-fast starts skipping tests. + */ + onCancel(): void + + /** + * isCancelled callback. + * If this callback returns true, cypress-fail-fast will start skipping tests. + * @returns boolean. true if remaining tests should be skipped + */ + isCancelled(): boolean +} + +interface FailFastPluginConfigOptions { + /** + * Parallel callbacks. + * Callbacks to be executed when strategy is "parallel". + */ + parallelCallbacks?: FailFastParallelCallbacks +} + /** * Installs cypress-fail-fast plugin - * @example failFastPlugin(on, config); + * @example failFastPlugin(on, config, {}); * @param on Cypress plugin events * @param config Cypress plugin config options + * @param failFastConfig cypress-fail-fast plugin config options * @returns Cypress plugin config options */ -declare function _exports(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions): Cypress.PluginConfigOptions +declare function _exports(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions, failFastConfig?: FailFastPluginConfigOptions): Cypress.PluginConfigOptions export = _exports; diff --git a/sonar-project.properties b/sonar-project.properties index 24e0759..7a2c7df 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,6 +1,6 @@ sonar.organization=javierbrea sonar.projectKey=cypress-fail-fast -sonar.projectVersion=2.2.2 +sonar.projectVersion=2.3.0 sonar.javascript.file.suffixes=.js sonar.sourceEncoding=UTF-8 diff --git a/src/helpers.js b/src/helpers.js index 2a03ed6..540e84f 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -1,20 +1,31 @@ const PLUGIN_ENVIRONMENT_VAR = "FAIL_FAST_PLUGIN"; const ENABLED_ENVIRONMENT_VAR = "FAIL_FAST_ENABLED"; +const STRATEGY_ENVIRONMENT_VAR = "FAIL_FAST_STRATEGY"; const SHOULD_SKIP_TASK = "failFastShouldSkip"; const RESET_SKIP_TASK = "failFastResetSkip"; +const STRATEGIES = ["spec", "parallel"]; + +const TRUTHY_VALUES = [true, "true", 1, "1"]; +const FALSY_VALUES = [false, "false", 0, "0"]; + const ENVIRONMENT_DEFAULT_VALUES = { [PLUGIN_ENVIRONMENT_VAR]: true, [ENABLED_ENVIRONMENT_VAR]: true, }; -const TRUTHY_VALUES = [true, "true", 1, "1"]; -const FALSY_VALUES = [false, "false", 0, "0"]; - function valueIsOneOf(value, arrayOfValues) { return arrayOfValues.includes(value); } +function strategyIsParallel(value) { + return value === STRATEGIES[1]; +} + +function strategyIsSpec(value) { + return value === STRATEGIES[0]; +} + function isTruthy(value) { return valueIsOneOf(value, TRUTHY_VALUES); } @@ -27,8 +38,11 @@ module.exports = { ENVIRONMENT_DEFAULT_VALUES, PLUGIN_ENVIRONMENT_VAR, ENABLED_ENVIRONMENT_VAR, + STRATEGY_ENVIRONMENT_VAR, SHOULD_SKIP_TASK, RESET_SKIP_TASK, isTruthy, isFalsy, + strategyIsParallel, + strategyIsSpec, }; diff --git a/src/plugin.js b/src/plugin.js index c470191..2d3654a 100644 --- a/src/plugin.js +++ b/src/plugin.js @@ -1,20 +1,45 @@ -const { SHOULD_SKIP_TASK, RESET_SKIP_TASK } = require("./helpers"); +const { + SHOULD_SKIP_TASK, + RESET_SKIP_TASK, + STRATEGY_ENVIRONMENT_VAR, + strategyIsParallel, +} = require("./helpers"); -module.exports = (on, config) => { +module.exports = (on, config, pluginConfig = {}) => { // store skip flag - let shouldSkip = false; + let shouldSkipFlag = false; + + const parallelCallbacks = + strategyIsParallel(config.env[STRATEGY_ENVIRONMENT_VAR]) && !!pluginConfig.parallelCallbacks + ? pluginConfig.parallelCallbacks + : {}; + const isCancelledCallback = parallelCallbacks.isCancelled; + const onCancelCallback = parallelCallbacks.onCancel; + + const shouldSkip = () => { + if (!!shouldSkipFlag) { + return shouldSkipFlag; + } + if (isCancelledCallback) { + shouldSkipFlag = isCancelledCallback() || false; + } + return shouldSkipFlag; + }; // Expose fail fast tasks on("task", { [RESET_SKIP_TASK]: function () { - shouldSkip = false; + shouldSkipFlag = false; return null; }, [SHOULD_SKIP_TASK]: function (value) { if (value === true) { - shouldSkip = value; + if (onCancelCallback) { + onCancelCallback(); + } + shouldSkipFlag = value; } - return shouldSkip; + return shouldSkip(); }, }); diff --git a/src/support.js b/src/support.js index 9f95867..3b73dbf 100644 --- a/src/support.js +++ b/src/support.js @@ -2,10 +2,12 @@ const { ENVIRONMENT_DEFAULT_VALUES, PLUGIN_ENVIRONMENT_VAR, ENABLED_ENVIRONMENT_VAR, + STRATEGY_ENVIRONMENT_VAR, SHOULD_SKIP_TASK, RESET_SKIP_TASK, isFalsy, isTruthy, + strategyIsSpec, } = require("./helpers"); function support(Cypress, cy, beforeEach, afterEach, before) { @@ -27,6 +29,7 @@ function support(Cypress, cy, beforeEach, afterEach, before) { return { plugin: booleanEnvironmentVarValue(PLUGIN_ENVIRONMENT_VAR), enabled: booleanEnvironmentVarValue(ENABLED_ENVIRONMENT_VAR), + strategyIsSpec: strategyIsSpec(Cypress.env(STRATEGY_ENVIRONMENT_VAR)), }; } @@ -53,6 +56,10 @@ function support(Cypress, cy, beforeEach, afterEach, before) { return getFailFastEnvironmentConfig(); } + function currentStrategyIsSpec() { + return getFailFastEnvironmentConfig().strategyIsSpec; + } + function pluginIsEnabled() { return getFailFastEnvironmentConfig().plugin; } @@ -91,7 +98,7 @@ function support(Cypress, cy, beforeEach, afterEach, before) { before(function () { if (pluginIsEnabled()) { - if (isHeaded()) { + if (isHeaded() || currentStrategyIsSpec()) { /* Reset the shouldSkip flag at the start of a run, so that it doesn't carry over into subsequent runs. diff --git a/test-e2e/commands/support/copy.js b/test-e2e/commands/support/copy.js index f22b01b..1604467 100644 --- a/test-e2e/commands/support/copy.js +++ b/test-e2e/commands/support/copy.js @@ -3,6 +3,7 @@ const fsExtra = require("fs-extra"); const CYPRESS_PATH = "cypress"; const CYPRESS_PLUGINS_PATH = "plugins"; +const CYPRESS_CUSTOM_PLUGINS_PATH = "plugins-custom"; const CYPRESS_SUPPORT_PATH = "support"; const CYPRESS_INTEGRATION_PATH = "integration"; const TESTS_PATH = path.resolve(__dirname, "..", ".."); @@ -65,23 +66,35 @@ const copyPluginToCypressSupport = (variant) => { fsExtra.copySync(eslintFile, path.resolve(pluginDestFolder, ESLINT_FILE)); }; +const copyCypressPluginFile = (variant, typescript = false, customPluginFolder = null) => { + const destPaths = variantPaths(variant); + const INDEX_FILE = toTypeScriptName("index.js", typescript); + + const pluginsPath = path.resolve(CYPRESS_SRC_PATH, CYPRESS_PLUGINS_PATH); + const customPluginsPath = path.resolve(CYPRESS_SRC_PATH, CYPRESS_CUSTOM_PLUGINS_PATH); + const pluginFile = customPluginFolder + ? path.resolve(customPluginsPath, customPluginFolder, INDEX_FILE) + : path.resolve(pluginsPath, INDEX_FILE); + + fsExtra.removeSync(destPaths.cypress.plugins); + fsExtra.ensureDirSync(destPaths.cypress.plugins); + fsExtra.copySync(pluginFile, path.resolve(destPaths.cypress.plugins, INDEX_FILE)); +}; + const copyCypressSources = (variant, typescript = false) => { const destPaths = variantPaths(variant); const BABEL_CONFIG_FILE = "babel.config.js"; const CYPRESS_CONFIG_FILE = "cypress.json"; const INDEX_FILE = toTypeScriptName("index.js", typescript); - const pluginsPath = path.resolve(CYPRESS_SRC_PATH, CYPRESS_PLUGINS_PATH); const supportPath = path.resolve(CYPRESS_SRC_PATH, CYPRESS_SUPPORT_PATH); const cypressConfigFile = path.resolve(CYPRESS_SRC_PATH, CYPRESS_CONFIG_FILE); const babelConfigFile = path.resolve(CYPRESS_SRC_PATH, BABEL_CONFIG_FILE); - const pluginFile = path.resolve(pluginsPath, INDEX_FILE); const supportFile = path.resolve(supportPath, INDEX_FILE); fsExtra.removeSync(destPaths.cypress.plugins); fsExtra.ensureDirSync(destPaths.cypress.plugins); - fsExtra.copySync(pluginFile, path.resolve(destPaths.cypress.plugins, INDEX_FILE)); fsExtra.removeSync(destPaths.cypress.support); fsExtra.ensureDirSync(destPaths.cypress.support); @@ -92,6 +105,8 @@ const copyCypressSources = (variant, typescript = false) => { if (!typescript) { fsExtra.copySync(babelConfigFile, path.resolve(destPaths.root, BABEL_CONFIG_FILE)); } + + copyCypressPluginFile(variant, typescript); }; const copyCypressSpecs = (specsFolder, variant) => { @@ -135,5 +150,6 @@ module.exports = { copyPluginToCypressSupport, copyCypressSources, copyCypressSpecs, + copyCypressPluginFile, copyScripts, }; diff --git a/test-e2e/cypress-src/integration/all-tests-passing/a-file.js b/test-e2e/cypress-src/integration/all-tests-passing/a-file.js new file mode 100644 index 0000000..85891c7 --- /dev/null +++ b/test-e2e/cypress-src/integration/all-tests-passing/a-file.js @@ -0,0 +1,22 @@ +describe("List items", () => { + before(() => { + cy.task("log", "Executing before hook"); + cy.visit("/"); + }); + + it("should display title", () => { + cy.get("h1").should("have.text", "Items list"); + }); + + it("should display first item", () => { + cy.get("ul li:eq(0)").should("have.text", "First item"); + }); + + it("should display second item", () => { + cy.get("ul li:eq(1)").should("have.text", "Second item"); + }); + + it("should display third item", () => { + cy.get("ul li:eq(2)").should("have.text", "Third item"); + }); +}); diff --git a/test-e2e/cypress-src/integration/all-tests-passing/b-file.js b/test-e2e/cypress-src/integration/all-tests-passing/b-file.js new file mode 100644 index 0000000..91fc4a0 --- /dev/null +++ b/test-e2e/cypress-src/integration/all-tests-passing/b-file.js @@ -0,0 +1,23 @@ +describe("List items", () => { + before(() => { + cy.task("log", "Executing before hook"); + cy.visit("/"); + cy.wait(10000); + }); + + it("should display title", () => { + cy.get("h1").should("have.text", "Items list"); + }); + + it("should display first item", () => { + cy.get("ul li:eq(0)").should("have.text", "First item"); + }); + + it("should display second item", () => { + cy.get("ul li:eq(1)").should("have.text", "Second item"); + }); + + it("should display third item", () => { + cy.get("ul li:eq(2)").should("have.text", "Third item"); + }); +}); diff --git a/test-e2e/cypress-src/integration/all-tests-passing/c-file.js b/test-e2e/cypress-src/integration/all-tests-passing/c-file.js new file mode 100644 index 0000000..85891c7 --- /dev/null +++ b/test-e2e/cypress-src/integration/all-tests-passing/c-file.js @@ -0,0 +1,22 @@ +describe("List items", () => { + before(() => { + cy.task("log", "Executing before hook"); + cy.visit("/"); + }); + + it("should display title", () => { + cy.get("h1").should("have.text", "Items list"); + }); + + it("should display first item", () => { + cy.get("ul li:eq(0)").should("have.text", "First item"); + }); + + it("should display second item", () => { + cy.get("ul li:eq(1)").should("have.text", "Second item"); + }); + + it("should display third item", () => { + cy.get("ul li:eq(2)").should("have.text", "Third item"); + }); +}); diff --git a/test-e2e/cypress-src/plugins-custom/parallel/index.js b/test-e2e/cypress-src/plugins-custom/parallel/index.js new file mode 100644 index 0000000..804a011 --- /dev/null +++ b/test-e2e/cypress-src/plugins-custom/parallel/index.js @@ -0,0 +1,38 @@ +const fsExtra = require("fs-extra"); +const path = require("path"); + +const storageFile = path.resolve( + __dirname, + "..", + "..", + "..", + "..", + "parallel-storage", + "parallel-storage.json" +); + +module.exports = (on, config) => { + require("../../../../../plugin")(on, config, { + parallelCallbacks: { + onCancel: () => { + fsExtra.writeJsonSync(storageFile, { cancelled: true }); + }, + isCancelled: () => { + if (fsExtra.pathExistsSync(storageFile)) { + return fsExtra.readJsonSync(storageFile).cancelled; + } + return false; + }, + }, + }); + + // Add log task + on("task", { + log: function (message) { + console.log(message); + return null; + }, + }); + + return config; +}; diff --git a/test-e2e/cypress-src/plugins-custom/parallel/index.ts b/test-e2e/cypress-src/plugins-custom/parallel/index.ts new file mode 100644 index 0000000..97d9bbc --- /dev/null +++ b/test-e2e/cypress-src/plugins-custom/parallel/index.ts @@ -0,0 +1,39 @@ +import fsExtra = require("fs-extra"); +import path = require("path"); + +const storageFile = path.resolve( + __dirname, + "..", + "..", + "..", + "..", + "parallel-storage", + "parallel-storage.json" +); + +import cypressFailFast = require("../support/cypress-fail-fast/plugin"); + +export default (on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions): Cypress.ResolvedConfigOptions => { + cypressFailFast(on, config, { + parallelCallbacks: { + onCancel: () => { + fsExtra.writeJsonSync(storageFile, { cancelled: true }); + }, + isCancelled: () => { + if (fsExtra.pathExistsSync(storageFile)) { + return fsExtra.readJsonSync(storageFile).cancelled; + } + return false; + }, + }, + }); + + on("task", { + log: function (message) { + console.log(message); + return null; + }, + }); + + return config; +}; diff --git a/test-e2e/cypress-variants/typescript/package-lock.json b/test-e2e/cypress-variants/typescript/package-lock.json index 6eae23e..5319f8b 100644 --- a/test-e2e/cypress-variants/typescript/package-lock.json +++ b/test-e2e/cypress-variants/typescript/package-lock.json @@ -2246,9 +2246,9 @@ "dev": true }, "typescript": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.5.tgz", - "integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", + "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", "dev": true }, "universalify": { diff --git a/test-e2e/cypress-variants/typescript/package.json b/test-e2e/cypress-variants/typescript/package.json index 9947a40..4ac8f55 100644 --- a/test-e2e/cypress-variants/typescript/package.json +++ b/test-e2e/cypress-variants/typescript/package.json @@ -11,7 +11,7 @@ }, "devDependencies": { "cypress": "6.8.0", - "typescript": "4.1.5", + "typescript": "4.2.3", "cross-env": "7.0.3", "fs-extra": "9.1.0", "mochawesome": "6.2.2", diff --git a/test-e2e/jest.config.js b/test-e2e/jest.config.js index e21566b..ad759dc 100644 --- a/test-e2e/jest.config.js +++ b/test-e2e/jest.config.js @@ -13,5 +13,5 @@ module.exports = { // The glob patterns Jest uses to detect test files testMatch: ["**/test/**/*.spec.js"], - // testMatch: ["**/test/**/environment-config.spec.js"], + // testMatch: ["**/test/**/strategy.spec.js"], }; diff --git a/test-e2e/package-lock.json b/test-e2e/package-lock.json index 5a83275..f3e0d5f 100644 --- a/test-e2e/package-lock.json +++ b/test-e2e/package-lock.json @@ -1002,6 +1002,12 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -2234,9 +2240,9 @@ } }, "follow-redirects": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz", - "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", + "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==", "dev": true }, "for-in": { @@ -2277,6 +2283,18 @@ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", "dev": true }, + "fs-extra": { + "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": "^2.0.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3387,6 +3405,16 @@ "minimist": "^1.2.5" } }, + "jsonfile": { + "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": "^2.0.0" + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4262,9 +4290,9 @@ "dev": true }, "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -4890,9 +4918,9 @@ } }, "start-server-and-test": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-1.12.0.tgz", - "integrity": "sha512-y3M/PLUPkPBsgKoengMIMQeceT8uOnOc4bkdor/RSCK9Ih/j8z4WthSCrAboXLjgtJJWOporAiEQsnYox+THXg==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-1.12.1.tgz", + "integrity": "sha512-qGQ2HQiF2yDIfyaHsXkHfoE5UOl4zJUbJ/gx2xOkfX7iPMXW9qHmoFyaMfIDJVLNkxCK7RxSrvWEI9hNVKQluw==", "dev": true, "requires": { "bluebird": "3.7.2", @@ -4901,7 +4929,7 @@ "execa": "3.4.0", "lazy-ass": "1.6.0", "ps-tree": "1.2.0", - "wait-on": "5.2.1" + "wait-on": "5.3.0" }, "dependencies": { "execa": { @@ -5321,6 +5349,12 @@ "set-value": "^2.0.1" } }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -5464,16 +5498,24 @@ } }, "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==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-5.3.0.tgz", + "integrity": "sha512-DwrHrnTK+/0QFaB9a8Ol5Lna3k7WvUR4jzSKmz0YaPBpuN2sACyiPVKVfj6ejnjcajAcvn3wlbTyMIn9AZouOg==", "dev": true, "requires": { "axios": "^0.21.1", "joi": "^17.3.0", - "lodash": "^4.17.20", + "lodash": "^4.17.21", "minimist": "^1.2.5", "rxjs": "^6.6.3" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + } } }, "walker": { diff --git a/test-e2e/package.json b/test-e2e/package.json index d6243a2..b526347 100644 --- a/test-e2e/package.json +++ b/test-e2e/package.json @@ -12,9 +12,10 @@ }, "devDependencies": { "cross-env": "7.0.3", + "fs-extra": "9.1.0", "jest": "26.6.3", "serve": "11.3.2", - "start-server-and-test": "1.12.0", + "start-server-and-test": "1.12.1", "strip-ansi": "6.0.0" } } diff --git a/test-e2e/parallel-storage/.gitignore b/test-e2e/parallel-storage/.gitignore new file mode 100644 index 0000000..9651ce7 --- /dev/null +++ b/test-e2e/parallel-storage/.gitignore @@ -0,0 +1,5 @@ +# exclude everything +/* + +# exception to the rule +!/.gitignore diff --git a/test-e2e/test/parallel.spec.js b/test-e2e/test/parallel.spec.js new file mode 100644 index 0000000..a229a38 --- /dev/null +++ b/test-e2e/test/parallel.spec.js @@ -0,0 +1,153 @@ +const path = require("path"); +const fsExtra = require("fs-extra"); + +const { runParallelSpecsTests } = require("./support/testsRunner"); +const cypressVariants = require("../commands/support/variants"); + +const removeParallelStorage = () => { + fsExtra.removeSync(path.resolve(__dirname, "..", "parallel-storage", "parallel-storage.json")); +}; + +runParallelSpecsTests( + "When parallel strategy is enabled and first tests run fails", + [ + { + cypress: cypressVariants[1], + pluginFile: "parallel", + specs: "environment-config-only", + delay: 3000, + specsResults: [ + { + logBefore: true, + executed: 4, + passed: 1, + failed: 1, + skipped: 2, + }, + { + logBefore: false, + executed: 4, + passed: 0, + failed: 0, + skipped: 4, + }, + { + logBefore: false, + executed: 3, + passed: 0, + failed: 0, + skipped: 3, + }, + ], + env: { + CYPRESS_FAIL_FAST_STRATEGY: "parallel", + }, + }, + { + cypress: cypressVariants[2], + pluginFile: "parallel", + specs: "all-tests-passing", + specsResults: [ + { + logBefore: true, + executed: 4, + passed: 4, + failed: 0, + skipped: 0, + }, + { + logBefore: true, + executed: 4, + passed: 0, + failed: 0, + skipped: 4, + }, + { + logBefore: false, + executed: 4, + passed: 0, + failed: 0, + skipped: 4, + }, + ], + env: { + CYPRESS_FAIL_FAST_STRATEGY: "parallel", + }, + }, + ], + { + afterAll: removeParallelStorage, + } +); + +runParallelSpecsTests( + "When parallel strategy is disabled and first tests run fails", + [ + { + cypress: cypressVariants[1], + pluginFile: "parallel", + specs: "environment-config-only", + delay: 3000, + specsResults: [ + { + logBefore: true, + executed: 4, + passed: 1, + failed: 1, + skipped: 2, + }, + { + logBefore: false, + executed: 4, + passed: 0, + failed: 0, + skipped: 4, + }, + { + logBefore: false, + executed: 3, + passed: 0, + failed: 0, + skipped: 3, + }, + ], + env: { + CYPRESS_FAIL_FAST_STRATEGY: "run", + }, + }, + { + cypress: cypressVariants[2], + pluginFile: "parallel", + specs: "all-tests-passing", + specsResults: [ + { + logBefore: true, + executed: 4, + passed: 4, + failed: 0, + skipped: 0, + }, + { + logBefore: true, + executed: 4, + passed: 4, + failed: 0, + skipped: 0, + }, + { + logBefore: true, + executed: 4, + passed: 4, + failed: 0, + skipped: 0, + }, + ], + env: { + CYPRESS_FAIL_FAST_STRATEGY: "run", + }, + }, + ], + { + afterAll: removeParallelStorage, + } +); diff --git a/test-e2e/test/strategy.spec.js b/test-e2e/test/strategy.spec.js new file mode 100644 index 0000000..08c571f --- /dev/null +++ b/test-e2e/test/strategy.spec.js @@ -0,0 +1,93 @@ +const { runSpecsTests } = require("./support/testsRunner"); + +runSpecsTests("When strategy is spec", { + specs: "describe-disabled-test-enabled", + specsResults: [ + { + logBefore: true, + executed: 4, + passed: 1, + failed: 1, + skipped: 2, + }, + { + logBefore: true, + executed: 4, + passed: 4, + failed: 0, + skipped: 0, + }, + { + logBefore: true, + executed: 3, + passed: 1, + failed: 1, + skipped: 1, + }, + ], + env: { + CYPRESS_FAIL_FAST_STRATEGY: "spec", + }, +}); + +runSpecsTests("When strategy is run", { + skipVariants: true, + specs: "describe-disabled-test-enabled", + specsResults: [ + { + logBefore: true, + executed: 4, + passed: 1, + failed: 1, + skipped: 2, + }, + { + logBefore: false, + executed: 4, + passed: 0, + failed: 0, + skipped: 4, + }, + { + logBefore: false, + executed: 3, + passed: 0, + failed: 0, + skipped: 3, + }, + ], + env: { + CYPRESS_FAIL_FAST_STRATEGY: "run", + }, +}); + +runSpecsTests("When strategy is parallel", { + skipVariants: true, + specs: "describe-disabled-test-enabled", + specsResults: [ + { + logBefore: true, + executed: 4, + passed: 1, + failed: 1, + skipped: 2, + }, + { + logBefore: false, + executed: 4, + passed: 0, + failed: 0, + skipped: 4, + }, + { + logBefore: false, + executed: 3, + passed: 0, + failed: 0, + skipped: 3, + }, + ], + env: { + CYPRESS_FAIL_FAST_STRATEGY: "parallel", + }, +}); diff --git a/test-e2e/test/support/testsRunner.js b/test-e2e/test/support/testsRunner.js index 1a4ce3b..493e535 100644 --- a/test-e2e/test/support/testsRunner.js +++ b/test-e2e/test/support/testsRunner.js @@ -1,13 +1,21 @@ const path = require("path"); const fs = require("fs"); const cypressVariants = require("../../commands/support/variants"); -const { copyCypressSpecs } = require("../../commands/support/copy"); +const { copyCypressSpecs, copyCypressPluginFile } = require("../../commands/support/copy"); const { npmRun, VARIANTS_FOLDER } = require("./npmCommandRunner"); const { splitLogsBySpec } = require("./logs"); const AFTER_EVENT_LOG = "Executed test:after:run event in failed test"; const BEFORE_HOOK_LOG = "Executing before hook"; +const wait = (time = 1000) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(); + }, time); + }); +}; + const readReport = (variantPath) => { return new Promise((resolve, reject) => { fs.readFile( @@ -86,6 +94,16 @@ const getSpecsStatusesTests = (specsExpectedStatuses) => { }; }; +const getParallelSpecsStatusesTests = (runIndex, specsExpectedStatuses) => { + return (getLogs, getReport) => { + describe(`Run ${runIndex}`, () => { + specsExpectedStatuses.forEach((specExpectedStatuses, index) => { + getSpecTests({ ...specExpectedStatuses, spec: index + 1 }, getLogs, getReport); + }); + }); + }; +}; + const runVariantTests = (cypressVariant, tests, options = {}) => { describe(`Executed in ${cypressVariant.name}`, () => { let logs; @@ -115,6 +133,98 @@ const runSpecsTests = (description, options = {}) => { }); }; +const waitAndRun = (time, run) => { + if (!time) { + return run(); + } + return wait(time).then(() => run()); +}; + +const runParallelTests = ( + cypressVariant1, + cypressVariant2, + tests1, + tests2, + options1 = {}, + options2 = {}, + commonOptions = {} +) => { + describe(`Running in parallel ${cypressVariant1.name}:${options1.specs} and ${cypressVariant2.name}:${options2.specs}`, () => { + let logs1; + let logs2; + let report1; + let report2; + const getLogs1 = (specIndex) => logs1[specIndex]; + const getReport1 = () => report1; + const getLogs2 = (specIndex) => logs2[specIndex]; + const getReport2 = () => report2; + + beforeAll(async () => { + copyCypressSpecs(options1.specs, cypressVariant1); + copyCypressSpecs(options2.specs, cypressVariant2); + if (options1.pluginFile) { + copyCypressPluginFile( + cypressVariant1.path, + cypressVariant1.typescript, + options1.pluginFile + ); + } + if (options2.pluginFile) { + copyCypressPluginFile( + cypressVariant2.path, + cypressVariant2.typescript, + options2.pluginFile + ); + } + const logs = await Promise.all([ + waitAndRun(options1.delay, () => + npmRun(["cypress:run"], cypressVariant1.path, options1.env) + ), + waitAndRun(options2.delay, () => + npmRun(["cypress:run"], cypressVariant2.path, options2.env) + ), + ]); + + logs1 = splitLogsBySpec(logs[0]); + logs2 = splitLogsBySpec(logs[1]); + await npmRun(["report:create"], cypressVariant1.path, options1.env); + await npmRun(["report:create"], cypressVariant2.path, options2.env); + report1 = await readReport(cypressVariant1.path); + report2 = await readReport(cypressVariant2.path); + }, 60000); + + afterAll(() => { + if (options1.pluginFile) { + copyCypressPluginFile(cypressVariant1.path, cypressVariant1.typescript); + } + if (options2.pluginFile) { + copyCypressPluginFile(cypressVariant2.path, cypressVariant2.typescript); + } + if (commonOptions.afterAll) { + commonOptions.afterAll(); + } + }); + + tests1(getLogs1, getReport1); + tests2(getLogs2, getReport2); + }); +}; + +const runParallelSpecsTests = (description, runsOptions, options) => { + describe(description, () => { + runParallelTests( + runsOptions[0].cypress, + runsOptions[1].cypress, + getParallelSpecsStatusesTests(1, runsOptions[0].specsResults), + getParallelSpecsStatusesTests(2, runsOptions[1].specsResults), + runsOptions[0], + runsOptions[1], + options + ); + }); +}; + module.exports = { runSpecsTests, + runParallelSpecsTests, }; diff --git a/test/plugin.spec.js b/test/plugin.spec.js index 7b7b83a..50bb2db 100644 --- a/test/plugin.spec.js +++ b/test/plugin.spec.js @@ -8,8 +8,8 @@ describe("plugin", () => { let failFastShouldSkip; let failFastResetSkip; - const getPluginMethods = () => { - plugin(onEventSpy); + const getPluginMethods = (config, env) => { + plugin(onEventSpy, { env: env || {} }, config); eventName = onEventSpy.getCall(0).args[0]; failFastShouldSkip = onEventSpy.getCall(0).args[1].failFastShouldSkip; failFastResetSkip = onEventSpy.getCall(0).args[1].failFastResetSkip; @@ -45,7 +45,7 @@ describe("plugin", () => { }); describe("when it is enabled using boolean", () => { - it("should return shouldSkip flag as false by default when plugin ", () => { + it("should return shouldSkip flag as false by default", () => { getPluginMethods(); expect(failFastShouldSkip()).toEqual(false); }); @@ -66,7 +66,7 @@ describe("plugin", () => { }); describe("when it is enabled using string", () => { - it("should return shouldSkip flag as false by default when plugin ", () => { + it("should return shouldSkip flag as false by default", () => { getPluginMethods(); expect(failFastShouldSkip()).toEqual(false); }); @@ -85,4 +85,110 @@ describe("plugin", () => { expect(failFastShouldSkip()).toEqual(false); }); }); + + describe("when parallel callbacks are provided", () => { + describe("when strategy is parallel", () => { + const env = { + FAIL_FAST_STRATEGY: "parallel", + }; + + it("should return shouldSkip flag as true if flag is false but isCancelled callback returns true", () => { + getPluginMethods( + { + parallelCallbacks: { + isCancelled: () => true, + }, + }, + env + ); + expect(failFastShouldSkip()).toEqual(true); + }); + + it("should return shouldSkip flag as false if flag is false and isCancelled callback does not return value", () => { + getPluginMethods( + { + parallelCallbacks: { + isCancelled: () => null, + }, + }, + env + ); + expect(failFastShouldSkip()).toEqual(false); + }); + + it("should return shouldSkip flag as true if flag is true even when isCancelled callback returns false", () => { + getPluginMethods( + { + parallelCallbacks: { + isCancelled: () => false, + }, + }, + env + ); + failFastShouldSkip(true); + expect(failFastShouldSkip()).toEqual(true); + }); + + it("should call to onCancel callback when shouldSkip flag is set to true", () => { + const spy = sandbox.spy(); + getPluginMethods( + { + parallelCallbacks: { + onCancel: spy, + }, + }, + env + ); + failFastShouldSkip(true); + expect(spy.callCount).toEqual(1); + }); + + it("should not call to onCancel callback when shouldSkip flag is set with a value different to true", () => { + const spy = sandbox.spy(); + getPluginMethods( + { + parallelCallbacks: { + onCancel: spy, + }, + }, + env + ); + failFastShouldSkip(); + failFastShouldSkip(false); + expect(spy.callCount).toEqual(0); + }); + }); + + describe("when strategy is not parallel", () => { + const env = { + FAIL_FAST_STRATEGY: "run", + }; + + it("should return shouldSkip flag as false if flag is false but isCancelled callback returns true", () => { + getPluginMethods( + { + parallelCallbacks: { + isCancelled: () => true, + }, + }, + env + ); + expect(failFastShouldSkip()).toEqual(false); + }); + + it("should not call to isCancelled callback", () => { + const spy = sandbox.spy(); + getPluginMethods( + { + parallelCallbacks: { + isCancelled: spy, + }, + }, + env + ); + failFastShouldSkip(); + expect(spy.callCount).toEqual(0); + }); + }); + }); }); diff --git a/test/support.spec.js b/test/support.spec.js index 61e3b3d..0e450bf 100644 --- a/test/support.spec.js +++ b/test/support.spec.js @@ -14,6 +14,7 @@ describe("support", () => { let beforeEachCallback; let afterEachCallback; let beforeCallback; + let getCurrentTest; let Cypress; let cy; @@ -30,6 +31,9 @@ describe("support", () => { if (envKey === "FAIL_FAST_ENABLED") { return options.enabled; } + if (envKey === "FAIL_FAST_STRATEGY") { + return options.strategy; + } }, runner: { stop: sandbox.spy(), @@ -65,6 +69,8 @@ describe("support", () => { }; } + getCurrentTest = () => currentTest; + const beforeEachMethod = (callback) => { beforeEachCallback = callback.bind(currentTest); }; @@ -148,6 +154,16 @@ describe("support", () => { expect(Cypress.runner.stop.callCount).toEqual(1); }); + it("should set currentTest as pending if failFastShouldSkip returns true", async () => { + getSupportCallbacks({ + ...config, + shouldSkip: true, + }); + beforeEachCallback(); + await wait(200); + expect(getCurrentTest().currentTest.pending).toEqual(true); + }); + it("should not log the task when setting flag to true", async () => { getSupportCallbacks({ ...config, @@ -253,6 +269,16 @@ describe("support", () => { expect(cy.task.calledWith("failFastResetSkip")).toEqual(true); }); + it("should call to reset plugin if strategy is spec", async () => { + getSupportCallbacks({ + ...config, + strategy: "spec", + }); + beforeCallback(); + await wait(200); + expect(cy.task.calledWith("failFastResetSkip")).toEqual(true); + }); + it("should not log the task when resetting the plugin flag", async () => { getSupportCallbacks({ ...config, @@ -275,6 +301,18 @@ describe("support", () => { expect(Cypress.runner.stop.callCount).toEqual(1); }); + it("should not log the task when checking if has to skip", async () => { + getSupportCallbacks({ + ...config, + browserIsHeaded: false, + shouldSkip: true, + }); + beforeCallback(); + await wait(200); + expect(cy.task.getCall(0).args[1]).toEqual(null); + expect(cy.task.getCall(0).args[2]).toEqual({ log: false }); + }); + it("should not call to stop runner if browser is not headed and should not skip", async () => { getSupportCallbacks({ ...config,