From 401bd7ab18cbeca37bfd2166701ba0ebb771e639 Mon Sep 17 00:00:00 2001
From: Renovate Bot <bot@renovateapp.com>
Date: Tue, 30 Mar 2021 19:41:00 +0000
Subject: [PATCH 01/28] chore(deps): update dependency eslint to v7.23.0

---
 package-lock.json | 117 +++++++++++++++++++++++++++++++---------------
 package.json      |   2 +-
 2 files changed, 81 insertions(+), 38 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 435825d..fa049db 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -714,9 +714,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 +726,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"
       },
@@ -2631,13 +2630,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 +2649,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 +2660,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 +2690,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
         }
       }
@@ -3337,9 +3342,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"
@@ -3705,6 +3710,15 @@
       "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
       "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",
@@ -3832,6 +3846,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",
@@ -4780,12 +4800,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 +4836,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",
@@ -6739,21 +6777,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",
@@ -7062,9 +7105,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": {
diff --git a/package.json b/package.json
index eb0662e..2ec901f 100644
--- a/package.json
+++ b/package.json
@@ -41,7 +41,7 @@
     "@stryker-mutator/core": "4.4.1",
     "@stryker-mutator/jest-runner": "4.4.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",

From f6f6d03e4984ced8d3c0dfb66f03f9150d40aae9 Mon Sep 17 00:00:00 2001
From: Renovate Bot <bot@renovateapp.com>
Date: Tue, 30 Mar 2021 22:38:41 +0000
Subject: [PATCH 02/28] chore(deps): update dependency eslint-plugin-react to
 v7.23.1

---
 package-lock.json | 360 +++++++++++++++++++++++++++++++++-------------
 package.json      |   2 +-
 2 files changed, 265 insertions(+), 97 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index fa049db..85beec6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1666,16 +1666,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": {
@@ -2532,23 +2555,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": {
@@ -2737,22 +2793,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": {
@@ -2763,6 +2820,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"
+          }
         }
       }
     },
@@ -3394,6 +3461,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",
@@ -3647,33 +3720,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"
           }
         }
       }
@@ -3710,6 +3775,12 @@
       "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",
@@ -3726,9 +3797,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": {
@@ -3874,12 +3945,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": {
@@ -5256,15 +5340,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": {
@@ -5277,15 +5373,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": {
@@ -5678,32 +5786,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"
           }
         }
       }
@@ -6650,38 +6749,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": {
@@ -7013,6 +7148,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",
@@ -7216,6 +7371,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 2ec901f..3303fb4 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,7 @@
     "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",

From efce64018bae1db1e464728b03cb4f6f8e8ae3da Mon Sep 17 00:00:00 2001
From: Renovate Bot <bot@renovateapp.com>
Date: Wed, 31 Mar 2021 00:12:07 +0000
Subject: [PATCH 03/28] chore(deps): update dependency start-server-and-test to
 v1.12.1

---
 test-e2e/package-lock.json | 36 ++++++++++++++++++++++--------------
 test-e2e/package.json      |  2 +-
 2 files changed, 23 insertions(+), 15 deletions(-)

diff --git a/test-e2e/package-lock.json b/test-e2e/package-lock.json
index 5a83275..90e80e2 100644
--- a/test-e2e/package-lock.json
+++ b/test-e2e/package-lock.json
@@ -2234,9 +2234,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": {
@@ -4262,9 +4262,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 +4890,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 +4901,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": {
@@ -5464,16 +5464,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..794296f 100644
--- a/test-e2e/package.json
+++ b/test-e2e/package.json
@@ -14,7 +14,7 @@
     "cross-env": "7.0.3",
     "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"
   }
 }

From 78fcfc9b1a97578ea3ae960adc9cfb9c969f71cf Mon Sep 17 00:00:00 2001
From: Renovate Bot <bot@renovateapp.com>
Date: Wed, 31 Mar 2021 03:18:42 +0000
Subject: [PATCH 04/28] chore(deps): update dependency typescript to v4.2.3

---
 test-e2e/cypress-variants/typescript/package-lock.json | 6 +++---
 test-e2e/cypress-variants/typescript/package.json      | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

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

From 41da7c2bf8459874a9fb0e5c151c4ad258c08abf Mon Sep 17 00:00:00 2001
From: Renovate Bot <bot@renovateapp.com>
Date: Wed, 31 Mar 2021 04:53:51 +0000
Subject: [PATCH 05/28] chore(deps): update stryker monorepo to v4.5.1

---
 package-lock.json | 467 +++++++++++++++++++++++++++-------------------
 package.json      |   4 +-
 2 files changed, 273 insertions(+), 198 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 85beec6..f1136db 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -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
         }
       }
@@ -1026,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",
@@ -1037,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",
@@ -1073,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",
@@ -1122,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": {
@@ -1150,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"
           }
@@ -1204,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": {
@@ -1248,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": {
@@ -1284,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",
@@ -1306,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": {
@@ -1323,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",
@@ -1361,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",
@@ -1370,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"
       },
@@ -1390,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"
@@ -1950,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",
@@ -2004,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",
@@ -2233,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",
@@ -2243,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": {
@@ -2515,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",
@@ -2618,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",
@@ -5218,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",
@@ -5725,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",
@@ -5961,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": {
@@ -7129,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",
@@ -7325,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": {
diff --git a/package.json b/package.json
index 3303fb4..2f20b03 100644
--- a/package.json
+++ b/package.json
@@ -38,8 +38,8 @@
     "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.23.0",
     "eslint-config-prettier": "8.1.0",

From 76cabe5b0b2e1393485696731f6823e4538967c2 Mon Sep 17 00:00:00 2001
From: Renovate Bot <bot@renovateapp.com>
Date: Wed, 31 Mar 2021 08:13:35 +0000
Subject: [PATCH 06/28] chore(deps): update dependency sinon to v10

---
 package-lock.json | 8 ++++----
 package.json      | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index f1136db..4c8674c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6419,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": {
diff --git a/package.json b/package.json
index 2f20b03..ce87816 100644
--- a/package.json
+++ b/package.json
@@ -49,7 +49,7 @@
     "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",

From 53534bde3bde76bd65c9ce967228b4637869fe50 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Wed, 31 Mar 2021 19:54:33 +0200
Subject: [PATCH 07/28] feat: add parallel strategy callbacks (#33)

---
 .github/workflows/build.yml                   | 27 +++---
 src/plugin.js                                 | 27 +++++-
 test-e2e/commands/support/copy.js             | 22 ++++-
 .../integration/all-tests-passing/a-file.js   | 22 +++++
 .../integration/all-tests-passing/b-file.js   | 22 +++++
 .../integration/all-tests-passing/c-file.js   | 22 +++++
 .../plugins-custom/parallel/index.js          | 38 ++++++++
 .../plugins-custom/parallel/index.ts          | 14 +++
 test-e2e/jest.config.js                       |  2 +-
 test-e2e/package-lock.json                    | 34 +++++++
 test-e2e/package.json                         |  1 +
 test-e2e/parallel-storage/.gitignore          |  5 +
 test-e2e/test/parallel.spec.js                | 74 +++++++++++++++
 test-e2e/test/support/testsRunner.js          | 93 ++++++++++++++++++-
 14 files changed, 382 insertions(+), 21 deletions(-)
 create mode 100644 test-e2e/cypress-src/integration/all-tests-passing/a-file.js
 create mode 100644 test-e2e/cypress-src/integration/all-tests-passing/b-file.js
 create mode 100644 test-e2e/cypress-src/integration/all-tests-passing/c-file.js
 create mode 100644 test-e2e/cypress-src/plugins-custom/parallel/index.js
 create mode 100644 test-e2e/cypress-src/plugins-custom/parallel/index.ts
 create mode 100644 test-e2e/parallel-storage/.gitignore
 create mode 100644 test-e2e/test/parallel.spec.js

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d87d5e2..187d434 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -4,6 +4,8 @@ on:
     branches:
       - main
       - release
+      # TODO, remove before merging
+      - feat-parallel-strategy
   pull_request:
 jobs:
   test:
@@ -14,10 +16,11 @@ 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
+      # TODO: move to another action
+      # - 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:
@@ -38,13 +41,15 @@ jobs:
         run: npm ci
       - name: Lint
         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 }}
+      # TODO, uncomment before merging
+      # - name: Test unit
+        # run: npm run test:unit
+      # TODO: move to another action
+      # - 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/src/plugin.js b/src/plugin.js
index c470191..40a601f 100644
--- a/src/plugin.js
+++ b/src/plugin.js
@@ -1,20 +1,37 @@
 const { SHOULD_SKIP_TASK, RESET_SKIP_TASK } = require("./helpers");
 
-module.exports = (on, config) => {
+module.exports = (on, config, pluginConfig = {}) => {
   // store skip flag
-  let shouldSkip = false;
+  let shouldSkipFlag = false;
+
+  const 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/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..85891c7
--- /dev/null
+++ b/test-e2e/cypress-src/integration/all-tests-passing/b-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/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..97e63ca
--- /dev/null
+++ b/test-e2e/cypress-src/plugins-custom/parallel/index.ts
@@ -0,0 +1,14 @@
+import cypressFailFast = require("../support/cypress-fail-fast/plugin");
+
+export default (on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions, {}): Cypress.ResolvedConfigOptions => {
+  cypressFailFast(on, config);
+
+  on("task", {
+    log: function (message) {
+      console.log(message);
+      return null;
+    },
+  });
+
+  return config;
+};
diff --git a/test-e2e/jest.config.js b/test-e2e/jest.config.js
index e21566b..a5ecfe6 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/**/parallel.spec.js"],
 };
diff --git a/test-e2e/package-lock.json b/test-e2e/package-lock.json
index 90e80e2..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",
@@ -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",
@@ -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",
diff --git a/test-e2e/package.json b/test-e2e/package.json
index 794296f..b526347 100644
--- a/test-e2e/package.json
+++ b/test-e2e/package.json
@@ -12,6 +12,7 @@
   },
   "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.1",
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..b471a84
--- /dev/null
+++ b/test-e2e/test/parallel.spec.js
@@ -0,0 +1,74 @@
+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",
+      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,
+        },
+      ],
+    },
+    {
+      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,
+        },
+      ],
+    },
+  ],
+  {
+    afterAll: removeParallelStorage,
+  }
+);
diff --git a/test-e2e/test/support/testsRunner.js b/test-e2e/test/support/testsRunner.js
index 1a4ce3b..379e653 100644
--- a/test-e2e/test/support/testsRunner.js
+++ b/test-e2e/test/support/testsRunner.js
@@ -1,7 +1,7 @@
 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");
 
@@ -86,6 +86,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 +125,87 @@ const runSpecsTests = (description, options = {}) => {
   });
 };
 
+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([
+        npmRun(["cypress:run"], cypressVariant1.path, options1.env),
+        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,
 };

From 0263eb6cc387ef25e07f54ec245c2eff7c905502 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Wed, 31 Mar 2021 20:14:43 +0200
Subject: [PATCH 08/28] test: add e2e test checking parallel cancellation (#33)

---
 .../integration/all-tests-passing/a-file.js   |  1 -
 .../integration/all-tests-passing/b-file.js   |  1 -
 .../plugins-custom/parallel/index.ts          | 29 +++++++++++++++++--
 test-e2e/test/parallel.spec.js                | 19 ++++--------
 test-e2e/test/support/testsRunner.js          | 23 +++++++++++++--
 5 files changed, 54 insertions(+), 19 deletions(-)

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
index 85891c7..03dfad3 100644
--- a/test-e2e/cypress-src/integration/all-tests-passing/a-file.js
+++ b/test-e2e/cypress-src/integration/all-tests-passing/a-file.js
@@ -1,6 +1,5 @@
 describe("List items", () => {
   before(() => {
-    cy.task("log", "Executing before hook");
     cy.visit("/");
   });
 
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
index 85891c7..03dfad3 100644
--- a/test-e2e/cypress-src/integration/all-tests-passing/b-file.js
+++ b/test-e2e/cypress-src/integration/all-tests-passing/b-file.js
@@ -1,6 +1,5 @@
 describe("List items", () => {
   before(() => {
-    cy.task("log", "Executing before hook");
     cy.visit("/");
   });
 
diff --git a/test-e2e/cypress-src/plugins-custom/parallel/index.ts b/test-e2e/cypress-src/plugins-custom/parallel/index.ts
index 97e63ca..97d9bbc 100644
--- a/test-e2e/cypress-src/plugins-custom/parallel/index.ts
+++ b/test-e2e/cypress-src/plugins-custom/parallel/index.ts
@@ -1,7 +1,32 @@
+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);
+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) {
diff --git a/test-e2e/test/parallel.spec.js b/test-e2e/test/parallel.spec.js
index b471a84..51c9722 100644
--- a/test-e2e/test/parallel.spec.js
+++ b/test-e2e/test/parallel.spec.js
@@ -42,28 +42,21 @@ runParallelSpecsTests(
     {
       cypress: cypressVariants[2],
       pluginFile: "parallel",
+      delay: 3000,
       specs: "all-tests-passing",
       specsResults: [
         {
-          logBefore: true,
-          executed: 4,
-          passed: 4,
-          failed: 0,
-          skipped: 0,
+          logBefore: false,
         },
         {
-          logBefore: true,
-          executed: 4,
-          passed: 4,
-          failed: 0,
-          skipped: 0,
+          logBefore: false,
         },
         {
-          logBefore: true,
+          logBefore: false,
           executed: 4,
-          passed: 4,
+          passed: 0,
           failed: 0,
-          skipped: 0,
+          skipped: 4,
         },
       ],
     },
diff --git a/test-e2e/test/support/testsRunner.js b/test-e2e/test/support/testsRunner.js
index 379e653..493e535 100644
--- a/test-e2e/test/support/testsRunner.js
+++ b/test-e2e/test/support/testsRunner.js
@@ -8,6 +8,14 @@ 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(
@@ -125,6 +133,13 @@ const runSpecsTests = (description, options = {}) => {
   });
 };
 
+const waitAndRun = (time, run) => {
+  if (!time) {
+    return run();
+  }
+  return wait(time).then(() => run());
+};
+
 const runParallelTests = (
   cypressVariant1,
   cypressVariant2,
@@ -162,8 +177,12 @@ const runParallelTests = (
         );
       }
       const logs = await Promise.all([
-        npmRun(["cypress:run"], cypressVariant1.path, options1.env),
-        npmRun(["cypress:run"], cypressVariant2.path, options2.env),
+        waitAndRun(options1.delay, () =>
+          npmRun(["cypress:run"], cypressVariant1.path, options1.env)
+        ),
+        waitAndRun(options2.delay, () =>
+          npmRun(["cypress:run"], cypressVariant2.path, options2.env)
+        ),
       ]);
 
       logs1 = splitLogsBySpec(logs[0]);

From 5f725577191119c6867146bb4aeaf98c8681d772 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Wed, 31 Mar 2021 20:18:24 +0200
Subject: [PATCH 09/28] test: increase wait time in second run to let first run
 fail

---
 test-e2e/test/parallel.spec.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test-e2e/test/parallel.spec.js b/test-e2e/test/parallel.spec.js
index 51c9722..e53f2e2 100644
--- a/test-e2e/test/parallel.spec.js
+++ b/test-e2e/test/parallel.spec.js
@@ -42,7 +42,7 @@ runParallelSpecsTests(
     {
       cypress: cypressVariants[2],
       pluginFile: "parallel",
-      delay: 3000,
+      delay: 10000,
       specs: "all-tests-passing",
       specsResults: [
         {

From b9fdb602e461f9deff29b29367acb2fba2619e7a Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Wed, 31 Mar 2021 20:27:14 +0200
Subject: [PATCH 10/28] test: improve parallel tests

---
 .github/workflows/build.yml                   | 40 +++++++++----------
 .../integration/all-tests-passing/a-file.js   |  1 +
 .../integration/all-tests-passing/b-file.js   |  2 +
 test-e2e/test/parallel.spec.js                | 14 +++++--
 4 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 187d434..7451694 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -59,23 +59,23 @@ jobs:
           name: coverage-${{ matrix.node }}
           path: coverage
           retention-days: 1
-  quality:
-    runs-on: ubuntu-latest
-    needs: test
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v2
-      - name: Download test results
-        uses: actions/download-artifact@v2
-        with:
-          name: coverage-15.2.0
-          path: coverage
-      - name: Coveralls
-        uses: coverallsapp/github-action@master
-        with:
-          github-token: ${{ secrets.GITHUB_TOKEN }}
-      - name: SonarCloud Scan
-        uses: sonarsource/sonarcloud-github-action@master
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+#  quality:
+#    runs-on: ubuntu-latest
+#    needs: test
+#    steps:
+#      - name: Checkout
+#        uses: actions/checkout@v2
+#      - name: Download test results
+#        uses: actions/download-artifact@v2
+#        with:
+#          name: coverage-15.2.0
+#          path: coverage
+#      - name: Coveralls
+#        uses: coverallsapp/github-action@master
+#        with:
+#          github-token: ${{ secrets.GITHUB_TOKEN }}
+#      - name: SonarCloud Scan
+#        uses: sonarsource/sonarcloud-github-action@master
+#        env:
+#          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+#          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
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
index 03dfad3..85891c7 100644
--- a/test-e2e/cypress-src/integration/all-tests-passing/a-file.js
+++ b/test-e2e/cypress-src/integration/all-tests-passing/a-file.js
@@ -1,5 +1,6 @@
 describe("List items", () => {
   before(() => {
+    cy.task("log", "Executing before hook");
     cy.visit("/");
   });
 
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
index 03dfad3..91fc4a0 100644
--- a/test-e2e/cypress-src/integration/all-tests-passing/b-file.js
+++ b/test-e2e/cypress-src/integration/all-tests-passing/b-file.js
@@ -1,6 +1,8 @@
 describe("List items", () => {
   before(() => {
+    cy.task("log", "Executing before hook");
     cy.visit("/");
+    cy.wait(10000);
   });
 
   it("should display title", () => {
diff --git a/test-e2e/test/parallel.spec.js b/test-e2e/test/parallel.spec.js
index e53f2e2..8503f6f 100644
--- a/test-e2e/test/parallel.spec.js
+++ b/test-e2e/test/parallel.spec.js
@@ -15,6 +15,7 @@ runParallelSpecsTests(
       cypress: cypressVariants[1],
       pluginFile: "parallel",
       specs: "environment-config-only",
+      delay: 3000,
       specsResults: [
         {
           logBefore: true,
@@ -42,14 +43,21 @@ runParallelSpecsTests(
     {
       cypress: cypressVariants[2],
       pluginFile: "parallel",
-      delay: 10000,
       specs: "all-tests-passing",
       specsResults: [
         {
-          logBefore: false,
+          logBefore: true,
+          executed: 4,
+          passed: 4,
+          failed: 0,
+          skipped: 0,
         },
         {
-          logBefore: false,
+          logBefore: true,
+          executed: 4,
+          passed: 0,
+          failed: 0,
+          skipped: 4,
         },
         {
           logBefore: false,

From 80e12913863316e3ec4a4093243206cc3471cd67 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Wed, 31 Mar 2021 20:30:21 +0200
Subject: [PATCH 11/28] test: run all e2e tests

---
 test-e2e/jest.config.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test-e2e/jest.config.js b/test-e2e/jest.config.js
index a5ecfe6..f074e16 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/**/parallel.spec.js"],
+  // testMatch: ["**/test/**/parallel.spec.js"],
 };

From 01b2edb82690c4f5894e0e52045699d24c1d8c79 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Fri, 2 Apr 2021 09:28:30 +0200
Subject: [PATCH 12/28] test: Add parallel callbacks unit tests

---
 test/plugin.spec.js | 61 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 57 insertions(+), 4 deletions(-)

diff --git a/test/plugin.spec.js b/test/plugin.spec.js
index 7b7b83a..570a97a 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) => {
+    plugin(onEventSpy, {}, 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,57 @@ describe("plugin", () => {
       expect(failFastShouldSkip()).toEqual(false);
     });
   });
+
+  describe("when parallel callbacks are provided", () => {
+    it("should return shouldSkip flag as true if flag is false but isCancelled callback returns true", () => {
+      getPluginMethods({
+        parallelCallbacks: {
+          isCancelled: () => true,
+        },
+      });
+      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,
+        },
+      });
+      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,
+        },
+      });
+      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,
+        },
+      });
+      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,
+        },
+      });
+      failFastShouldSkip();
+      failFastShouldSkip(false);
+      expect(spy.callCount).toEqual(0);
+    });
+  });
 });

From 95074fbc3703081115b68092d64dccb1d8471032 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Fri, 2 Apr 2021 09:29:30 +0200
Subject: [PATCH 13/28] chore: enable unit tests again in pipeline

---
 .github/workflows/build.yml | 45 ++++++++++++++++++-------------------
 1 file changed, 22 insertions(+), 23 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 7451694..6d27730 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -41,9 +41,8 @@ jobs:
         run: npm ci
       - name: Lint
         run: npm run lint
-      # TODO, uncomment before merging
-      # - name: Test unit
-        # run: npm run test:unit
+      - name: Test unit
+        run: npm run test:unit
       # TODO: move to another action
       # - name: Test mutation
         # run: npm run test:mutation
@@ -59,23 +58,23 @@ jobs:
           name: coverage-${{ matrix.node }}
           path: coverage
           retention-days: 1
-#  quality:
-#    runs-on: ubuntu-latest
-#    needs: test
-#    steps:
-#      - name: Checkout
-#        uses: actions/checkout@v2
-#      - name: Download test results
-#        uses: actions/download-artifact@v2
-#        with:
-#          name: coverage-15.2.0
-#          path: coverage
-#      - name: Coveralls
-#        uses: coverallsapp/github-action@master
-#        with:
-#          github-token: ${{ secrets.GITHUB_TOKEN }}
-#      - name: SonarCloud Scan
-#        uses: sonarsource/sonarcloud-github-action@master
-#        env:
-#          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-#          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+  quality:
+    runs-on: ubuntu-latest
+    needs: test
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v2
+      - name: Download test results
+        uses: actions/download-artifact@v2
+        with:
+          name: coverage-15.2.0
+          path: coverage
+      - name: Coveralls
+        uses: coverallsapp/github-action@master
+        with:
+          github-token: ${{ secrets.GITHUB_TOKEN }}
+      - name: SonarCloud Scan
+        uses: sonarsource/sonarcloud-github-action@master
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

From 8d95f8fa1f886dc0d7549858f4cd4f3795e0c1fb Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Fri, 2 Apr 2021 10:15:12 +0200
Subject: [PATCH 14/28] feat: Add plugin parallel callbacks config typeScript
 declarations (#33)

---
 plugin.d.ts | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

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 @@
 /// <reference types="cypress" />
 
+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;

From 4c5f7bc4fb73f493e90557be9eee550f557862dd Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Fri, 2 Apr 2021 11:10:12 +0200
Subject: [PATCH 15/28] feat: Run parallel callbacks only if strategy is
 parallel (#33)

---
 src/helpers.js                 |  31 +++++++++-
 src/plugin.js                  |  12 +++-
 src/support.js                 |   3 +
 test-e2e/test/parallel.spec.js |  78 ++++++++++++++++++++++++
 test/plugin.spec.js            | 105 ++++++++++++++++++++-------------
 5 files changed, 182 insertions(+), 47 deletions(-)

diff --git a/src/helpers.js b/src/helpers.js
index 2a03ed6..5189572 100644
--- a/src/helpers.js
+++ b/src/helpers.js
@@ -1,20 +1,40 @@
 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 STRATEGY_ALLOWED_VALUES = ["run", "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,
+  [STRATEGY_ENVIRONMENT_VAR]: STRATEGY_ALLOWED_VALUES[0],
 };
 
-const TRUTHY_VALUES = [true, "true", 1, "1"];
-const FALSY_VALUES = [false, "false", 0, "0"];
-
 function valueIsOneOf(value, arrayOfValues) {
   return arrayOfValues.includes(value);
 }
 
+function isValidStrategy(value) {
+  return !!value && valueIsOneOf(value, STRATEGY_ALLOWED_VALUES);
+}
+
+function currentStrategyOrDefault(value) {
+  return isValidStrategy(value) ? value : ENVIRONMENT_DEFAULT_VALUES[STRATEGY_ENVIRONMENT_VAR];
+}
+
+function strategyIsParallel(value) {
+  return currentStrategyOrDefault(value) === STRATEGY_ALLOWED_VALUES[2];
+}
+
+function strategyIsSpec(value) {
+  return currentStrategyOrDefault(value) === STRATEGY_ALLOWED_VALUES[1];
+}
+
 function isTruthy(value) {
   return valueIsOneOf(value, TRUTHY_VALUES);
 }
@@ -27,8 +47,13 @@ module.exports = {
   ENVIRONMENT_DEFAULT_VALUES,
   PLUGIN_ENVIRONMENT_VAR,
   ENABLED_ENVIRONMENT_VAR,
+  STRATEGY_ENVIRONMENT_VAR,
   SHOULD_SKIP_TASK,
   RESET_SKIP_TASK,
   isTruthy,
   isFalsy,
+  isValidStrategy,
+  currentStrategyOrDefault,
+  strategyIsParallel,
+  strategyIsSpec,
 };
diff --git a/src/plugin.js b/src/plugin.js
index 40a601f..2d3654a 100644
--- a/src/plugin.js
+++ b/src/plugin.js
@@ -1,10 +1,18 @@
-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, pluginConfig = {}) => {
   // store skip flag
   let shouldSkipFlag = false;
 
-  const parallelCallbacks = pluginConfig.parallelCallbacks || {};
+  const parallelCallbacks =
+    strategyIsParallel(config.env[STRATEGY_ENVIRONMENT_VAR]) && !!pluginConfig.parallelCallbacks
+      ? pluginConfig.parallelCallbacks
+      : {};
   const isCancelledCallback = parallelCallbacks.isCancelled;
   const onCancelCallback = parallelCallbacks.onCancel;
 
diff --git a/src/support.js b/src/support.js
index 9f95867..2e2b2df 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)),
     };
   }
 
diff --git a/test-e2e/test/parallel.spec.js b/test-e2e/test/parallel.spec.js
index 8503f6f..a229a38 100644
--- a/test-e2e/test/parallel.spec.js
+++ b/test-e2e/test/parallel.spec.js
@@ -39,6 +39,9 @@ runParallelSpecsTests(
           skipped: 3,
         },
       ],
+      env: {
+        CYPRESS_FAIL_FAST_STRATEGY: "parallel",
+      },
     },
     {
       cypress: cypressVariants[2],
@@ -67,6 +70,81 @@ runParallelSpecsTests(
           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",
+      },
     },
   ],
   {
diff --git a/test/plugin.spec.js b/test/plugin.spec.js
index 570a97a..a84acb7 100644
--- a/test/plugin.spec.js
+++ b/test/plugin.spec.js
@@ -8,8 +8,8 @@ describe("plugin", () => {
   let failFastShouldSkip;
   let failFastResetSkip;
 
-  const getPluginMethods = (config) => {
-    plugin(onEventSpy, {}, config);
+  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;
@@ -87,55 +87,76 @@ describe("plugin", () => {
   });
 
   describe("when parallel callbacks are provided", () => {
-    it("should return shouldSkip flag as true if flag is false but isCancelled callback returns true", () => {
-      getPluginMethods({
-        parallelCallbacks: {
-          isCancelled: () => true,
-        },
+    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);
       });
-      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,
-        },
+      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);
       });
-      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,
-        },
+      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);
       });
-      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,
-        },
+      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);
       });
-      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,
-        },
+      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);
       });
-      failFastShouldSkip();
-      failFastShouldSkip(false);
-      expect(spy.callCount).toEqual(0);
     });
   });
 });

From 7cdc4fa2d04b7498983988940143e8fe609c0369 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Fri, 2 Apr 2021 11:36:03 +0200
Subject: [PATCH 16/28] feat: support spec strategy, which produces skipping
 tests only in current spec (#29)

---
 src/support.js                 |  6 ++-
 test-e2e/jest.config.js        |  2 +-
 test-e2e/test/strategy.spec.js | 91 ++++++++++++++++++++++++++++++++++
 test/support.spec.js           | 13 +++++
 4 files changed, 110 insertions(+), 2 deletions(-)
 create mode 100644 test-e2e/test/strategy.spec.js

diff --git a/src/support.js b/src/support.js
index 2e2b2df..3b73dbf 100644
--- a/src/support.js
+++ b/src/support.js
@@ -56,6 +56,10 @@ function support(Cypress, cy, beforeEach, afterEach, before) {
     return getFailFastEnvironmentConfig();
   }
 
+  function currentStrategyIsSpec() {
+    return getFailFastEnvironmentConfig().strategyIsSpec;
+  }
+
   function pluginIsEnabled() {
     return getFailFastEnvironmentConfig().plugin;
   }
@@ -94,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/jest.config.js b/test-e2e/jest.config.js
index f074e16..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/**/parallel.spec.js"],
+  // testMatch: ["**/test/**/strategy.spec.js"],
 };
diff --git a/test-e2e/test/strategy.spec.js b/test-e2e/test/strategy.spec.js
new file mode 100644
index 0000000..e1744ea
--- /dev/null
+++ b/test-e2e/test/strategy.spec.js
@@ -0,0 +1,91 @@
+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", {
+  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", {
+  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/support.spec.js b/test/support.spec.js
index 61e3b3d..5c38083 100644
--- a/test/support.spec.js
+++ b/test/support.spec.js
@@ -30,6 +30,9 @@ describe("support", () => {
         if (envKey === "FAIL_FAST_ENABLED") {
           return options.enabled;
         }
+        if (envKey === "FAIL_FAST_STRATEGY") {
+          return options.strategy;
+        }
       },
       runner: {
         stop: sandbox.spy(),
@@ -253,6 +256,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,

From e1a82c5305da638e3c02bf4a0a17363d12c2e74c Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Fri, 2 Apr 2021 11:43:37 +0200
Subject: [PATCH 17/28] chore: extract test-mutation step from build to a
 separated workflow

---
 .github/workflows/build.yml         | 11 --------
 .github/workflows/test-mutation.yml | 40 +++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 11 deletions(-)
 create mode 100644 .github/workflows/test-mutation.yml

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 6d27730..d8d68a3 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -16,11 +16,6 @@ jobs:
     steps:
       - name: Checkout
         uses: actions/checkout@v2
-      # TODO: move to another action
-      # - 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:
@@ -43,12 +38,6 @@ jobs:
         run: npm run lint
       - name: Test unit
         run: npm run test:unit
-      # TODO: move to another action
-      # - 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..aba2bf0
--- /dev/null
+++ b/.github/workflows/test-mutation.yml
@@ -0,0 +1,40 @@
+name: test-mutation
+on:
+  push:
+    branches:
+      - main
+      - release
+      # TODO, remove before merging
+      - feat-parallel-strategy
+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 }}
\ No newline at end of file

From a85fca14e2a1341bcf93c12f11b8fee8c27d9c8c Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Fri, 2 Apr 2021 12:35:02 +0200
Subject: [PATCH 18/28] test: improve mutation score

---
 src/helpers.js       | 17 +++--------------
 test/plugin.spec.js  | 32 ++++++++++++++++++++++++++++++++
 test/support.spec.js | 25 +++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 14 deletions(-)

diff --git a/src/helpers.js b/src/helpers.js
index 5189572..540e84f 100644
--- a/src/helpers.js
+++ b/src/helpers.js
@@ -4,7 +4,7 @@ const STRATEGY_ENVIRONMENT_VAR = "FAIL_FAST_STRATEGY";
 const SHOULD_SKIP_TASK = "failFastShouldSkip";
 const RESET_SKIP_TASK = "failFastResetSkip";
 
-const STRATEGY_ALLOWED_VALUES = ["run", "spec", "parallel"];
+const STRATEGIES = ["spec", "parallel"];
 
 const TRUTHY_VALUES = [true, "true", 1, "1"];
 const FALSY_VALUES = [false, "false", 0, "0"];
@@ -12,27 +12,18 @@ const FALSY_VALUES = [false, "false", 0, "0"];
 const ENVIRONMENT_DEFAULT_VALUES = {
   [PLUGIN_ENVIRONMENT_VAR]: true,
   [ENABLED_ENVIRONMENT_VAR]: true,
-  [STRATEGY_ENVIRONMENT_VAR]: STRATEGY_ALLOWED_VALUES[0],
 };
 
 function valueIsOneOf(value, arrayOfValues) {
   return arrayOfValues.includes(value);
 }
 
-function isValidStrategy(value) {
-  return !!value && valueIsOneOf(value, STRATEGY_ALLOWED_VALUES);
-}
-
-function currentStrategyOrDefault(value) {
-  return isValidStrategy(value) ? value : ENVIRONMENT_DEFAULT_VALUES[STRATEGY_ENVIRONMENT_VAR];
-}
-
 function strategyIsParallel(value) {
-  return currentStrategyOrDefault(value) === STRATEGY_ALLOWED_VALUES[2];
+  return value === STRATEGIES[1];
 }
 
 function strategyIsSpec(value) {
-  return currentStrategyOrDefault(value) === STRATEGY_ALLOWED_VALUES[1];
+  return value === STRATEGIES[0];
 }
 
 function isTruthy(value) {
@@ -52,8 +43,6 @@ module.exports = {
   RESET_SKIP_TASK,
   isTruthy,
   isFalsy,
-  isValidStrategy,
-  currentStrategyOrDefault,
   strategyIsParallel,
   strategyIsSpec,
 };
diff --git a/test/plugin.spec.js b/test/plugin.spec.js
index a84acb7..50bb2db 100644
--- a/test/plugin.spec.js
+++ b/test/plugin.spec.js
@@ -158,5 +158,37 @@ describe("plugin", () => {
         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 5c38083..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;
 
@@ -68,6 +69,8 @@ describe("support", () => {
       };
     }
 
+    getCurrentTest = () => currentTest;
+
     const beforeEachMethod = (callback) => {
       beforeEachCallback = callback.bind(currentTest);
     };
@@ -151,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,
@@ -288,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,

From b0ef79f8771c23c7517da7c809d181fa368de544 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Fri, 2 Apr 2021 12:40:01 +0200
Subject: [PATCH 19/28] test: Omit some strategy tests in cypress 5 and
 TypeScript

---
 test-e2e/test/strategy.spec.js | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/test-e2e/test/strategy.spec.js b/test-e2e/test/strategy.spec.js
index e1744ea..08c571f 100644
--- a/test-e2e/test/strategy.spec.js
+++ b/test-e2e/test/strategy.spec.js
@@ -31,6 +31,7 @@ runSpecsTests("When strategy is spec", {
 });
 
 runSpecsTests("When strategy is run", {
+  skipVariants: true,
   specs: "describe-disabled-test-enabled",
   specsResults: [
     {
@@ -61,6 +62,7 @@ runSpecsTests("When strategy is run", {
 });
 
 runSpecsTests("When strategy is parallel", {
+  skipVariants: true,
   specs: "describe-disabled-test-enabled",
   specsResults: [
     {

From aa466b16edf6a94a9f22cf75875ef663e21aa20a Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Sun, 4 Apr 2021 12:32:22 +0200
Subject: [PATCH 20/28] docs: Add documentation (#33,#29)

---
 README.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/README.md b/README.md
index 3d9e296..3963572 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,17 @@
 
 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 for parallel runs](#configuration-for-parallel-runs)
+- [Usage with TypeScript](#usage-with-typescript)
+
 ## Installation
 
 Add the plugin to `devDependencies`
@@ -39,6 +50,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).
 
@@ -130,6 +145,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 start 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
 

From 56bcd29e708e74251ebf45cbb7b2ba8595fe0eec Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Sun, 4 Apr 2021 12:35:57 +0200
Subject: [PATCH 21/28] docs: Add link to summary

---
 README.md | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 3963572..62c70ed 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,7 @@ It can be configured to skip all remaining tests in current spec file, in curren
 - [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)
 
@@ -69,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
   }
 }
 ```

From 0134e1534e621f4adb1a28d3d373be2261c24772 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Sun, 4 Apr 2021 12:37:45 +0200
Subject: [PATCH 22/28] docs: fix typo

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 62c70ed..e39bbfc 100644
--- a/README.md
+++ b/README.md
@@ -172,7 +172,7 @@ module.exports = (on, config) => {
   require("cypress-fail-fast/plugin")(on, config, {
     parallelCallbacks: {
       onCancel: () => {
-        // Create flag file when the plugin start skipping tests
+        // Create flag file when the plugin starts skipping tests
         fs.writeFileSync(isCancelledFlagPath);
       },
       isCancelled: () => {

From 761df0957bf5f2813abef4117c238b7a0833a026 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Sun, 4 Apr 2021 12:38:14 +0200
Subject: [PATCH 23/28] chore: execute mutation tests only in release and main
 branches

---
 .github/workflows/test-mutation.yml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/.github/workflows/test-mutation.yml b/.github/workflows/test-mutation.yml
index aba2bf0..55c78f4 100644
--- a/.github/workflows/test-mutation.yml
+++ b/.github/workflows/test-mutation.yml
@@ -4,8 +4,6 @@ on:
     branches:
       - main
       - release
-      # TODO, remove before merging
-      - feat-parallel-strategy
 jobs:
   test-mutation:
     runs-on: ubuntu-latest

From e56807b2670c3787bedb19b76e086c23b9b01597 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Sun, 4 Apr 2021 12:38:59 +0200
Subject: [PATCH 24/28] chore: execute build only in PRs, release and main
 branches

---
 .github/workflows/build.yml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d8d68a3..7ec19dc 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -4,8 +4,6 @@ on:
     branches:
       - main
       - release
-      # TODO, remove before merging
-      - feat-parallel-strategy
   pull_request:
 jobs:
   test:

From 7d2561bf2a8b1f00dac64e1bafdac6e9804f6978 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Sun, 4 Apr 2021 12:41:51 +0200
Subject: [PATCH 25/28] docs: add changes to changelog

---
 CHANGELOG.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6cc149..1f6fb74 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [unreleased]
 ### 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
 ### Fixed
 ### Removed

From 35e496cc66670f5e7b66119c13f74a936cb97b03 Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Sun, 4 Apr 2021 12:48:55 +0200
Subject: [PATCH 26/28] docs: add change to changelog

---
 .github/workflows/test-mutation.yml | 2 +-
 CHANGELOG.md                        | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/test-mutation.yml b/.github/workflows/test-mutation.yml
index 55c78f4..ee31f50 100644
--- a/.github/workflows/test-mutation.yml
+++ b/.github/workflows/test-mutation.yml
@@ -35,4 +35,4 @@ jobs:
       run: npm run test:mutation
       env:
         BRANCH_NAME: ${{ steps.extract-branch.outputs.branch }}
-        STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_TOKEN }}
\ No newline at end of file
+        STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_TOKEN }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1f6fb74..af9bac8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 - 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
 ### Fixed
 ### Removed
 ### BREAKING CHANGES

From 8460a163ca7fbb19741d5a85305752edc32ca11a Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Sun, 4 Apr 2021 13:04:08 +0200
Subject: [PATCH 27/28] chore(release): Upgrade version

---
 CHANGELOG.md             | 12 +++++++++---
 package-lock.json        |  2 +-
 package.json             |  6 ++++--
 sonar-project.properties |  2 +-
 4 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index af9bac8..fd1d2a5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,14 +6,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [unreleased]
 ### 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
 ### Fixed
 ### 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
+
 ## [2.2.2] - 2021-03-30
 
 ### Fixed
diff --git a/package-lock.json b/package-lock.json
index 4c8674c..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": {
diff --git a/package.json b/package.json
index ce87816..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",
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

From 054f2a3569683163677aa0ab8bfb2ce791a2a79a Mon Sep 17 00:00:00 2001
From: "javier.brea" <javier.brea@gmail.com>
Date: Sun, 4 Apr 2021 13:05:18 +0200
Subject: [PATCH 28/28] docs: Add change to changelog

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fd1d2a5..8332ffe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ### Changed
 - chore(ci): Separate test mutation job to a new workflow
+- chore(deps): Update devDependencies
 
 ## [2.2.2] - 2021-03-30