From d8cb641fe2a2ba14da3475f51776cdfd218dbcfe Mon Sep 17 00:00:00 2001 From: pplancq Date: Sat, 23 Mar 2024 12:56:18 +0100 Subject: [PATCH 1/4] chore(lint): replace tslint by eslint and prettier --- package-lock.json | 5127 ++++++++++++++--- package.json | 18 +- .../validation-and-code-generation.steps.ts | 2 - src/automatic-step-binding.ts | 1 - src/code-generation/scenario-generation.ts | 2 - src/code-generation/step-generation.ts | 2 - src/feature-definition-creation.ts | 1 - src/tag-filtering.ts | 1 - src/validation/scenario-validation.ts | 1 - src/validation/step-definition-validation.ts | 2 - tslint.json | 10 - 11 files changed, 4408 insertions(+), 759 deletions(-) delete mode 100644 tslint.json diff --git a/package-lock.json b/package-lock.json index a7e3125..fc71022 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,14 +15,17 @@ "uuid": "^8.3.2" }, "devDependencies": { + "@pplancq/eslint-config": "^2.1.0", + "@pplancq/prettier-config": "^1.0.1", "@types/glob": "^7.1.3", "@types/jest": "^29.5.12", "@types/node": "^20.11.30", "@types/uuid": "^8.3.0", - "babel-jest": "^29.7.0", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", + "prettier": "^3.2.5", "ts-jest": "^29.1.2", - "tslint": "^5.10.0", "typescript": "^5.4.3" }, "peerDependencies": { @@ -35,6 +38,15 @@ } } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -566,6 +578,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", + "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.24.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", @@ -657,6 +681,148 @@ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz", "integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==" }, + "node_modules/@cucumber/messages/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1008,6 +1174,131 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@pplancq/eslint-config": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@pplancq/eslint-config/-/eslint-config-2.1.0.tgz", + "integrity": "sha512-H9sdRqp5JJNOvRLtA9nhrTwG1NQmzcTyD+5EL9nCUDjXY/vQ6Ovs0OTJQ6jPmqpzYjWoU/5nIONLxc1rTvHYyQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "^7.3.0", + "@typescript-eslint/parser": "^7.2.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-prettier": "^9.1.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.0", + "eslint-plugin-jest": "^27.6.0", + "eslint-plugin-jest-dom": "^5.1.0", + "eslint-plugin-jest-extended": "^2.0.0", + "eslint-plugin-jsx-a11y": "^6.8.0", + "eslint-plugin-react": "^7.34.1", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-testing-library": "^6.2.0", + "eslint-plugin-vitest": "^0.3.26", + "eslint-plugin-vitest-globals": "^1.5.0" + }, + "bin": { + "init-eslint-config": "bin/init.js" + }, + "peerDependencies": { + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.0.1", + "prettier": "^3.2.5" + }, + "peerDependenciesMeta": { + "eslint-plugin-prettier": { + "optional": true + }, + "prettier": { + "optional": true + } + } + }, + "node_modules/@pplancq/eslint-config/node_modules/eslint-plugin-vitest": { + "version": "0.3.26", + "resolved": "https://registry.npmjs.org/eslint-plugin-vitest/-/eslint-plugin-vitest-0.3.26.tgz", + "integrity": "sha512-oxe5JSPgRjco8caVLTh7Ti8PxpwJdhSV0hTQAmkFcNcmy/9DnqLB/oNVRA11RmVRP//2+jIIT6JuBEcpW3obYg==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^7.1.1" + }, + "engines": { + "node": "^18.0.0 || >= 20.0.0" + }, + "peerDependencies": { + "eslint": ">=8.0.0", + "vitest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "vitest": { + "optional": true + } + } + }, + "node_modules/@pplancq/prettier-config": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@pplancq/prettier-config/-/prettier-config-1.0.1.tgz", + "integrity": "sha512-vmHPOK1AWvR9b07D8AqGbq5ymDxE+Dxdd6RTs+QeKR8Ii8eIMyBBHEUZAHb4rlHwsceckGaAf7PtrKgmEvclXQ==", + "dev": true, + "dependencies": { + "prettier-plugin-sh": "^0.14.0" + }, + "bin": { + "init-prettier-config": "bin/init.js" + }, + "peerDependencies": { + "prettier": "^3.1.1" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -1167,6 +1458,18 @@ "pretty-format": "^29.0.0" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, "node_modules/@types/long": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", @@ -1182,10 +1485,17 @@ "version": "20.11.30", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -1213,921 +1523,3430 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.3.1.tgz", + "integrity": "sha512-STEDMVQGww5lhCuNXVSQfbfuNII5E08QWkvAw5Qwf+bj2WT+JkG1uc+5/vXA3AOYMDHVOSpL+9rcbEUiHIm2dw==", "dev": true, "dependencies": { - "type-fest": "^0.21.3" + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "7.3.1", + "@typescript-eslint/type-utils": "7.3.1", + "@typescript-eslint/utils": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@typescript-eslint/parser": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.3.1.tgz", + "integrity": "sha512-Rq49+pq7viTRCH48XAbTA+wdLRrB/3sRq4Lpk0oGDm0VmnjBrAOVXH/Laalmwsv2VpekiEfVFwJYVk6/e8uvQw==", "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.3.1", + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/typescript-estree": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1", + "debug": "^4.3.4" + }, "engines": { - "node": ">=8" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.3.1.tgz", + "integrity": "sha512-fVS6fPxldsKY2nFvyT7IP78UO1/I2huG+AYu5AMjCT9wtl6JFiDnsv4uad4jQ0GTFzcUV5HShVeN96/17bTBag==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@typescript-eslint/type-utils": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.3.1.tgz", + "integrity": "sha512-iFhaysxFsMDQlzJn+vr3OrxN8NmdQkHks4WaqD4QBnt5hsq234wcYdyQ9uquzJJIDAj5W4wQne3yEsYA6OmXGw==", "dev": true, "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@typescript-eslint/typescript-estree": "7.3.1", + "@typescript-eslint/utils": "7.3.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">= 8" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@typescript-eslint/types": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.3.1.tgz", + "integrity": "sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw==", "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz", + "integrity": "sha512-tLpuqM46LVkduWP7JO7yVoWshpJuJzxDOPYIVWUUZbW+4dBpgGeUdl/fQkhuV0A8eGnphYw3pp8d2EnvPOfxmQ==", "dev": true, "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/babel-jest/node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "balanced-match": "^1.0.0" } }, - "node_modules/babel-jest/node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/babel-jest/node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "node_modules/@typescript-eslint/utils": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.3.1.tgz", + "integrity": "sha512-jIERm/6bYQ9HkynYlNZvXpzmXWZGhMbrOvq3jJzOSOlKXsVjrrolzWBjDW6/TvT5Q3WqaN4EkmcfdQwi9tDjBQ==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "7.3.1", + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/typescript-estree": "7.3.1", + "semver": "^7.5.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "eslint": "^8.56.0" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz", + "integrity": "sha512-9RMXwQF8knsZvfv9tdi+4D/j7dMG28X/wMJ8Jj6eOHyHWwDW4ngQJcqEczSsqIKKjFiLFr40Mnr7a5ulDD3vmw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" + "@typescript-eslint/types": "7.3.1", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=8" + "node": ">=0.4.0" } }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, "engines": { "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" + "color-convert": "^2.0.1" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "dependencies": { - "fast-json-stable-stringify": "2.x" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, "engines": { - "node": ">= 6" + "node": ">= 8" } }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { - "node-int64": "^0.4.0" + "sprintf-js": "~1.0.2" } }, - "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001600", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", - "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", + "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", + "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", + "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/babel-jest/node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-jest/node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, { "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" + "url": "https://github.com/sponsors/ai" } ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, "engines": { - "node": ">=8" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001600", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", + "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.715", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.715.tgz", + "integrity": "sha512-XzWNH4ZSa9BwVUQSDorPWAUQ5WGuYz7zJUNpNif40zFCiCl20t8zgylmreNmn26h5kiyw2lg7RfTmeMBsDklqg==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", + "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", + "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", + "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", + "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", + "dev": true, + "dependencies": { + "eslint-config-airbnb-base": "^15.0.0", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5" + }, + "engines": { + "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react-hooks": "^4.3.0" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "27.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", + "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^5.10.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", + "eslint": "^7.0.0 || ^8.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jest-dom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest-dom/-/eslint-plugin-jest-dom-5.2.0.tgz", + "integrity": "sha512-ctnCP0MsLmUvbCyhnOQ+/1OmsZj+e7V6kFunazIx5728Yq7TQnuKI8HOsgPTStB+9iYEpiEa+VfKB09Lq7/3fA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.16.3", + "requireindex": "^1.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", + "npm": ">=6", + "yarn": ">=1" + }, + "peerDependencies": { + "@testing-library/dom": "^8.0.0 || ^9.0.0", + "eslint": "^6.8.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@testing-library/dom": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jest-extended": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest-extended/-/eslint-plugin-jest-extended-2.0.0.tgz", + "integrity": "sha512-nMhVVsVcG/+Q6FMshql35WBxwx8xlBhxKgAG08WP3BYWfXrp28oxLpJVu9JSbMpfmfKGVrHwMYJGfPLRKlGB8w==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^5.10.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-jest-extended/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-jest-extended/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-jest-extended/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jest-extended/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-jest-extended/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-jest-extended/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-plugin-jest-extended/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-jest/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-plugin-jest/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", + "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.23.2", + "aria-query": "^5.3.0", + "array-includes": "^3.1.7", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "=4.7.0", + "axobject-query": "^3.2.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.15", + "hasown": "^2.0.0", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.34.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", + "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlast": "^1.2.4", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.3", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.17", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7", + "object.hasown": "^1.1.3", + "object.values": "^1.1.7", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.10" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-testing-library": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.2.0.tgz", + "integrity": "sha512-+LCYJU81WF2yQ+Xu4A135CgK8IszcFcyMF4sWkbiu6Oj+Nel0TrkZq/HvDw0/1WuO3dhDQsZA/OpEMGd0NfcUw==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^5.58.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", + "npm": ">=6" + }, + "peerDependencies": { + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-testing-library/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-plugin-testing-library/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-vitest-globals": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vitest-globals/-/eslint-plugin-vitest-globals-1.5.0.tgz", + "integrity": "sha512-ZSsVOaOIig0oVLzRTyk8lUfBfqzWxr/J3/NFMfGGRIkGQPejJYmDH3gXmSJxAojts77uzAGB/UmVrwi2DC4LYA==", + "dev": true + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=12" + "node": ">=10.13.0" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">=4" } }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "define-properties": "^1.1.3" }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "get-intrinsic": "^1.1.3" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "ms": "2.1.2" + "es-define-property": "^1.0.0" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, "engines": { - "node": ">=6.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, "engines": { - "node": ">=0.3.1" + "node": ">=10.17.0" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 4" } }, - "node_modules/electron-to-chromium": { - "version": "1.4.715", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.715.tgz", - "integrity": "sha512-XzWNH4ZSa9BwVUQSDorPWAUQ5WGuYz7zJUNpNif40zFCiCl20t8zgylmreNmn26h5kiyw2lg7RfTmeMBsDklqg==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=6" }, "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "dependencies": { - "is-arrayish": "^0.2.1" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, "engines": { - "node": ">=0.8.0" + "node": ">= 0.4" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, - "engines": { - "node": ">= 0.8.0" + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "bser": "2.1.1" + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=0.10.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { - "node": ">=6.9.0" + "node": ">=8" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=6" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": ">=8.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, "engines": { - "node": ">=10" + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, "engines": { - "node": "*" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.12.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "dependencies": { - "function-bind": "^1.1.2" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, "engines": { - "node": ">=10.17.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "call-bind": "^1.0.7" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "engines": { - "node": ">=0.8.19" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "dependencies": { - "hasown": "^2.0.0" + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, - "engines": { - "node": ">=0.12.0" + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2215,6 +5034,19 @@ "node": ">=8" } }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -2871,12 +5703,30 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -2889,6 +5739,30 @@ "node": ">=6" } }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -2898,6 +5772,24 @@ "node": ">=6" } }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -2907,6 +5799,19 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -2931,11 +5836,29 @@ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2999,6 +5922,15 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -3041,61 +5973,180 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mvdan-sh": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/mvdan-sh/-/mvdan-sh-0.10.1.tgz", + "integrity": "sha512-kMbrH0EObaKmK3nVRKUIIya1dpASHIEusM13S4V1ViHFuxuNxCo+arxoa6j/dbV22YBGjl7UKJm9QQKJ2Crzhg==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "dependencies": { - "minimist": "^1.2.5" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": ">= 0.4" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/object.hasown": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", + "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "dependencies": { - "path-key": "^3.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/once": { @@ -3121,6 +6172,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -3157,6 +6225,18 @@ "node": ">=6" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -3207,6 +6287,15 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -3246,6 +6335,70 @@ "node": ">=8" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prettier-plugin-sh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-sh/-/prettier-plugin-sh-0.14.0.tgz", + "integrity": "sha512-hfXulj5+zEl/ulrO5kMuuTPKmXvOg0bnLHY1hKFNN/N+/903iZbNp8NyZBTsgI8dtkSgFfAEIQq0IQTyP1ZVFQ==", + "dev": true, + "dependencies": { + "mvdan-sh": "^0.10.1", + "sh-syntax": "^0.4.1" + }, + "engines": { + "node": ">=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + }, + "peerDependencies": { + "prettier": "^3.0.3" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -3285,6 +6438,23 @@ "node": ">= 6" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, "node_modules/protobufjs": { "version": "6.11.4", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", @@ -3310,6 +6480,23 @@ "pbts": "bin/pbts" } }, + "node_modules/protobufjs/node_modules/@types/node": { + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -3326,12 +6513,77 @@ } ] }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3341,6 +6593,15 @@ "node": ">=0.10.0" } }, + "node_modules/requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true, + "engines": { + "node": ">=0.10.5" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -3370,31 +6631,176 @@ "node": ">=8" } }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/resolve.exports": { + "node_modules/set-function-name": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" } }, - "node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/sh-syntax": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/sh-syntax/-/sh-syntax-0.4.2.tgz", + "integrity": "sha512-/l2UZ5fhGZLVZa16XQM9/Vq/hezGGbdHeVEA01uWjOL1+7Ek/gt6FquW0iKKws4a9AYPYvlz6RyVvjh3JxOteg==", "dev": true, - "bin": { - "semver": "bin/semver" + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" } }, "node_modules/shebang-command": { @@ -3418,6 +6824,24 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -3510,6 +6934,81 @@ "node": ">=8" } }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -3576,6 +7075,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -3590,6 +7114,12 @@ "node": ">=8" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -3617,6 +7147,18 @@ "node": ">=8.0" } }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-jest": { "version": "29.1.2", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", @@ -3660,156 +7202,170 @@ } } }, - "node_modules/ts-jest/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" }, "bin": { - "semver": "bin/semver.js" - }, + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=4" } }, "node_modules/tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, - "node_modules/tslint": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", - "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.29.0" - }, - "bin": { - "tslint": "bin/tslint" + "tslib": "^1.8.1" }, "engines": { - "node": ">=4.8.0" + "node": ">= 6" }, "peerDependencies": { - "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev" + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/tslint/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "node_modules/tslint/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, "engines": { "node": ">=4" } }, - "node_modules/tslint/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/tslint/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/tslint/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/tslint/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tslint/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, "dependencies": { - "tslib": "^1.8.1" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, - "peerDependencies": { - "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/typescript": { @@ -3825,6 +7381,21 @@ "node": ">=14.17" } }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -3860,6 +7431,15 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -3906,6 +7486,85 @@ "node": ">= 8" } }, + "node_modules/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, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index c6418fb..be2e6cb 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "jest": "jest --verbose", "test": "npm run build & npm run lint & jest --color", "update-snapshots": "jest --updateSnapshot", - "lint": "tslint --project ./" + "lint": "eslint src specs examples --ext js,jsx,ts,tsx", + "lint:fix": "eslint src specs examples --ext js,jsx,ts,tsx --fix" }, "repository": { "type": "git", @@ -42,14 +43,17 @@ } }, "devDependencies": { + "@pplancq/eslint-config": "^2.1.0", + "@pplancq/prettier-config": "^1.0.1", "@types/glob": "^7.1.3", "@types/jest": "^29.5.12", "@types/node": "^20.11.30", "@types/uuid": "^8.3.0", - "babel-jest": "^29.7.0", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", + "prettier": "^3.2.5", "ts-jest": "^29.1.2", - "tslint": "^5.10.0", "typescript": "^5.4.3" }, "jest": { @@ -64,5 +68,13 @@ "ts", "tsx" ] + }, + "prettier": "@pplancq/prettier-config", + "eslintConfig": { + "extends": [ + "@pplancq/eslint-config/node", + "@pplancq/eslint-config/jest", + "@pplancq/eslint-config/prettier" + ] } } diff --git a/specs/step-definitions/validation-and-code-generation.steps.ts b/specs/step-definitions/validation-and-code-generation.steps.ts index f95d604..5414e22 100644 --- a/specs/step-definitions/validation-and-code-generation.steps.ts +++ b/specs/step-definitions/validation-and-code-generation.steps.ts @@ -223,7 +223,6 @@ defineFeature(feature, (test) => { thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); }); - // tslint:disable-next-line: max-line-length test('Enabled and a step in the step definitions doesn\'t match the step in the feature', ({ given, and, when, then }) => { givenStepsMustMatchFeatureFileIsEnabled(given); andIHaveAScenarioWhereTheStepMatcherForTheSecondStepDoesntMatchTheStep(and); @@ -231,7 +230,6 @@ defineFeature(feature, (test) => { thenIShouldSeeAValidationErrorAndGeneratedCode(then); }); - // tslint:disable-next-line: max-line-length test('Disabled and a step in the step definitions doesn\'t match the step in the feature', ({ given, and, when, then }) => { givenStepsMustMatchFeatureFileIsDisabled(given); andIHaveAScenarioWhereTheStepMatcherForTheSecondStepDoesntMatchTheStep(and); diff --git a/src/automatic-step-binding.ts b/src/automatic-step-binding.ts index cbf75fe..608c965 100644 --- a/src/automatic-step-binding.ts +++ b/src/automatic-step-binding.ts @@ -48,7 +48,6 @@ export const createAutoBindSteps = (jestLike: IJestLike) => { options.defineStep(match.stepMatcher, match.stepFunction); } else if (matches.length === 0) { const stepCode = generateStepCode(scenario.steps, stepIndex, false); - // tslint:disable-next-line:max-line-length errors.push(`No matching step found for step "${step.stepText}" in scenario "${scenario.title}" in feature "${feature.title}". Please add the following step code: \n\n${stepCode}`); } else { const matchingCode = matches.map((match) => `${match.stepMatcher.toString()}\n\n${match.stepFunction.toString()}`); diff --git a/src/code-generation/scenario-generation.ts b/src/code-generation/scenario-generation.ts index 51acc1e..1e4ed25 100644 --- a/src/code-generation/scenario-generation.ts +++ b/src/code-generation/scenario-generation.ts @@ -3,7 +3,6 @@ import { generateStepCode, generateStepFunctionCall } from './step-generation'; import { indent } from './utils'; const scenarioTemplate = (scenarioTitle: string, steps: string, stepKeywords: string[]) => { - // tslint:disable-next-line:max-line-length return `test('${scenarioTitle.replace(/'+/g, `\\'`)}', ({ ${stepKeywords.join(', ')} }) => {\n${indent(steps, 1).slice(0, -1)}\n});`; }; @@ -31,6 +30,5 @@ export const generateScenarioCodeWithSeparateStepFunctions = (scenario: ParsedSc const stepFunctionCalls = scenario.steps.map((step, index) => generateStepFunctionCall(scenario.steps, index)); const stepKeywords = getStepKeywords(scenario); - // tslint:disable-next-line:max-line-length return `${stepFunctionCode.join('\n\n')}\n\n${scenarioTemplate(scenario.title, stepFunctionCalls.join('\n'), stepKeywords)}`; }; diff --git a/src/code-generation/step-generation.ts b/src/code-generation/step-generation.ts index b722e2b..74c9c13 100644 --- a/src/code-generation/step-generation.ts +++ b/src/code-generation/step-generation.ts @@ -6,7 +6,6 @@ const stepTemplate = (stepKeyword: string, stepMatcher: string, stepArgumentVari }; const getStepFunctionWrapperName = (stepKeyword: string, stepText: string) => { - // tslint:disable-next-line:max-line-length return `${stepKeyword}_${stepText.replace(stepTextArgumentRegex, 'X').replace(/\s/g, '_').replace(/[^A-Za-z0-9_]/g, '')}`; }; @@ -16,7 +15,6 @@ const stepWrapperFunctionTemplate = ( stepMatcher: string, stepArgumentVariables: string[], ) => { - // tslint:disable-next-line:max-line-length return `export const ${getStepFunctionWrapperName(stepKeyword, stepText)} = (${stepKeyword}) => {\n${indent(stepTemplate(stepKeyword, stepMatcher, stepArgumentVariables), 1).slice(0, -1)}\n}`; }; diff --git a/src/feature-definition-creation.ts b/src/feature-definition-creation.ts index 5bc3ece..6900ad3 100644 --- a/src/feature-definition-creation.ts +++ b/src/feature-definition-creation.ts @@ -68,7 +68,6 @@ export const createDefineFeature = (jestLike: IJestLike): DefineFeatureFunction }); } catch (err) { throw new Error( - // tslint:disable-next-line:max-line-length `An error occurred while executing a scenario name template. \nTemplate:\n${options.scenarioNameTemplate}\nError:${err.message}`, ); } diff --git a/src/tag-filtering.ts b/src/tag-filtering.ts index ca502d1..e27b52d 100644 --- a/src/tag-filtering.ts +++ b/src/tag-filtering.ts @@ -14,7 +14,6 @@ const convertTagFilterExpressionToFunction = (tagFilterExpression: string) => { match = tagRegex.exec(tagFilterExpression); if (match) { - // tslint:disable-next-line:max-line-length newTagFilterExpression = newTagFilterExpression.replace(match[1], `(tags.indexOf("${match[1].toLowerCase()}")!==-1)`); if (tags.indexOf(match[1]) !== -1) { diff --git a/src/validation/scenario-validation.ts b/src/validation/scenario-validation.ts index 5e1fa66..b20d524 100644 --- a/src/validation/scenario-validation.ts +++ b/src/validation/scenario-validation.ts @@ -47,7 +47,6 @@ const findScenarioFromStepDefinitions = ( }); if (matchingScenarios.length === 0 && errorOptions.scenariosMustMatchFeatureFile) { - // tslint:disable-next-line:max-line-length errors.push(`Feature file has a scenario titled "${scenarioTitle}", but no match found in step definitions. Try adding the following code:\n\n${generateScenarioCode(scenario)}`); return null; diff --git a/src/validation/step-definition-validation.ts b/src/validation/step-definition-validation.ts index a0f941d..092d061 100644 --- a/src/validation/step-definition-validation.ts +++ b/src/validation/step-definition-validation.ts @@ -49,14 +49,12 @@ export const ensureFeatureFileAndStepDefinitionScenarioHaveSameSteps = ( if ( parsedStepCount !== stepDefinitionCount) { - // tslint:disable-next-line:max-line-length errors.push(`Scenario "${parsedScenario.title}" has ${parsedStepCount} step(s) in the feature file, but ${stepDefinitionCount} step definition(s) defined. Try adding the following code:\n\n${generateScenarioCode(parsedScenario)}`); } else { parsedScenarioSteps.forEach((parsedStep, index) => { const stepFromStepDefinitions = scenarioFromStepDefinitions.steps[index]; if (!stepFromStepDefinitions || !matchSteps(parsedStep.stepText, stepFromStepDefinitions.stepMatcher)) { - // tslint:disable-next-line:max-line-length errors.push(`Expected step #${index + 1} in scenario "${parsedScenario.title}" to match "${parsedStep.stepText}". Try adding the following code:\n\n${generateStepCode(parsedScenario.steps, index)}`); } }); diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 7d80c15..0000000 --- a/tslint.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "tslint:recommended", - "rules": { - "ordered-imports": [false], - "quotemark": [true, "single"], - "no-conditional-assignment": [false], - "object-literal-sort-keys": [false], - "interface-over-type-literal": [false] - } -} \ No newline at end of file From 95575d54e3ceeb717396026d2c351b1fe8c8c15e Mon Sep 17 00:00:00 2001 From: pplancq Date: Sat, 23 Mar 2024 12:56:58 +0100 Subject: [PATCH 2/4] chore(lint): add config for always use end of line lf --- .editorconfig | 4 ++++ .gitattributes | 1 + 2 files changed, 5 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..921dcc9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +end_of_line = lf \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..94f480d --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf \ No newline at end of file From ab9b2f22882c0d58ba199e5d2d90889dd3919e19 Mon Sep 17 00:00:00 2001 From: pplancq Date: Sat, 23 Mar 2024 15:18:22 +0100 Subject: [PATCH 3/4] chore(lint): fix lint for all files --- .../auto-step-binding.steps.js | 57 +- .../step-definitions/backgrounds.steps.js | 145 ++--- .../step-definitions/basic-scenarios.steps.js | 33 +- .../more-scenario-outlines.steps.js | 30 +- .../scenario-outlines.steps.js | 37 +- .../using-docstrings.steps.js | 31 +- .../using-dynamic-values.steps.js | 35 +- .../using-gherkin-tables.steps.js | 55 +- .../using-latest-gherkin-keywords.steps.js | 159 ++--- examples/ecmascript/src/arcade-machine.js | 53 +- examples/ecmascript/src/bank-account.js | 22 +- examples/ecmascript/src/calculator.js | 62 +- .../ecmascript/src/certificate-factory.js | 54 +- examples/ecmascript/src/online-sales.js | 35 +- examples/ecmascript/src/password-validator.js | 18 +- examples/ecmascript/src/rocket.js | 18 +- examples/ecmascript/src/todo-list.js | 30 +- examples/ecmascript/src/vending-machine.js | 50 +- .../auto-step-binding.steps.ts | 56 +- .../step-definitions/backgrounds.steps.ts | 144 ++--- .../step-definitions/basic-scenarios.steps.ts | 34 +- .../specs/step-definitions/language.steps.ts | 161 ++--- .../more-scenario-outlines.steps.ts | 25 +- .../scenario-outlines.steps.ts | 34 +- .../using-docstrings.steps.ts | 34 +- .../using-dynamic-values.steps.ts | 32 +- .../using-gherkin-tables.steps.ts | 59 +- .../using-latest-gherkin-keywords.steps.ts | 158 ++--- examples/typescript/src/arcade-machine.ts | 74 ++- examples/typescript/src/bank-account.ts | 14 +- examples/typescript/src/calculator.ts | 80 +-- .../typescript/src/certificate-factory.ts | 53 +- examples/typescript/src/online-sales.ts | 29 +- examples/typescript/src/password-validator.ts | 22 +- examples/typescript/src/todo-list.ts | 28 +- examples/typescript/src/vending-machine.ts | 47 +- .../step-definitions/step-execution.steps.ts | 203 +++---- specs/step-definitions/step-matching.steps.ts | 99 ++- .../table-step-arguments.steps.ts | 117 ++-- .../validation-and-code-generation.steps.ts | 447 +++++++------- specs/test-data/step-execution.ts | 168 +++--- specs/test-data/step-matching.ts | 42 +- specs/test-data/step-table-arguments.ts | 42 +- .../validation-and-code-generation.ts | 230 +++---- .../mock-test-runner/mock-describe-block.ts | 31 +- .../mock-test-runner/mock-test-runner.ts | 213 ++++--- specs/utils/mock-test-runner/mock-test.ts | 40 +- specs/utils/wire-up-mock-scenario.ts | 18 +- src/automatic-step-binding.ts | 136 +++-- .../generate-code-by-line-number.ts | 134 +++-- src/code-generation/scenario-generation.ts | 30 +- src/code-generation/step-generation.ts | 120 ++-- src/code-generation/utils.ts | 14 +- src/configuration.ts | 46 +- src/feature-definition-creation.ts | 550 ++++++++--------- src/index.ts | 6 +- src/models.ts | 52 +- src/parsed-feature-loading.ts | 563 +++++++++--------- src/tag-filtering.ts | 145 ++--- src/validation/scenario-validation.ts | 179 +++--- src/validation/step-definition-validation.ts | 94 +-- 61 files changed, 2863 insertions(+), 2864 deletions(-) diff --git a/examples/ecmascript/specs/step-definitions/auto-step-binding.steps.js b/examples/ecmascript/specs/step-definitions/auto-step-binding.steps.js index ce29c78..746417d 100644 --- a/examples/ecmascript/specs/step-definitions/auto-step-binding.steps.js +++ b/examples/ecmascript/specs/step-definitions/auto-step-binding.steps.js @@ -1,28 +1,29 @@ -import { loadFeatures, autoBindSteps } from 'jest-cucumber'; -import { VendingMachine } from '../../src/vending-machine'; - -export const vendingMachineSteps = ({ given, and, when, then }) => { - let vendingMachine; - - given(/^the vending machine has "(.*)" in stock$/, (itemName) => { - vendingMachine = new VendingMachine(); - vendingMachine.stockItem(itemName, 1); - }); - - and('I have inserted the correct amount of money', () => { - vendingMachine.insertMoney(0.50); - }); - - when(/^I purchase "(.*)"$/, (itemName) => { - vendingMachine.dispenseItem(itemName); - }); - - then(/^my "(.*)" should be dispensed$/, (itemName) => { - const inventoryAmount = vendingMachine.items[itemName]; - expect(inventoryAmount).toBe(0); - }); -}; - -const features = loadFeatures('./specs/features/auto-binding/**/*.feature'); - -autoBindSteps(features, [ vendingMachineSteps ]); +// eslint-disable-next-line import/no-unresolved +import { loadFeatures, autoBindSteps } from 'jest-cucumber'; +import { VendingMachine } from '../../src/vending-machine'; + +export const vendingMachineSteps = ({ given, and, when, then }) => { + let vendingMachine; + + given(/^the vending machine has "(.*)" in stock$/, itemName => { + vendingMachine = new VendingMachine(); + vendingMachine.stockItem(itemName, 1); + }); + + and('I have inserted the correct amount of money', () => { + vendingMachine.insertMoney(0.5); + }); + + when(/^I purchase "(.*)"$/, itemName => { + vendingMachine.dispenseItem(itemName); + }); + + then(/^my "(.*)" should be dispensed$/, itemName => { + const inventoryAmount = vendingMachine.items[itemName]; + expect(inventoryAmount).toBe(0); + }); +}; + +const features = loadFeatures('./specs/features/auto-binding/**/*.feature'); + +autoBindSteps(features, [vendingMachineSteps]); diff --git a/examples/ecmascript/specs/step-definitions/backgrounds.steps.js b/examples/ecmascript/specs/step-definitions/backgrounds.steps.js index 3a8ca04..48982a4 100644 --- a/examples/ecmascript/specs/step-definitions/backgrounds.steps.js +++ b/examples/ecmascript/specs/step-definitions/backgrounds.steps.js @@ -1,72 +1,73 @@ -import { loadFeature, defineFeature } from 'jest-cucumber'; -import { ArcadeMachine, COIN_TYPES } from '../../src/arcade-machine'; - -const feature = loadFeature('./specs/features/backgrounds.feature'); - -defineFeature(feature, (test) => { - let arcadeMachine; - - beforeEach(() => { - arcadeMachine = new ArcadeMachine(); - }); - - const givenMyMachineIsConfiguredToRequireCoins = (given) => { - given('my machine is configured to require coins', () => { - arcadeMachine.requireCoins = true; - }); - }; - - const givenMyMachineIsConfiguredToAcceptUsQuarters = (given) => { - given('my machine is configured to accept US Quarters', () => { - arcadeMachine.acceptedCoinType = COIN_TYPES.USQuarter; - }); - }; - - test('Successfully inserting coins', ({ given, when, then }) => { - givenMyMachineIsConfiguredToRequireCoins(given); - - given('I have not inserted any coins', () => { - arcadeMachine.balance = 0; - }); - - when('I insert one US quarter', () => { - arcadeMachine.insertCoin(COIN_TYPES.USQuarter); - }); - - then(/^I should have a balance of (\d+) cents$/, (balance) => { - arcadeMachine.balance = balance / 100; - }); - }); - - test('Inserting a Canadian coin', ({ given, when, then }) => { - let coinStatus; - - givenMyMachineIsConfiguredToRequireCoins(given); - - givenMyMachineIsConfiguredToAcceptUsQuarters(given); - - when('I insert a Canadian Quarter', () => { - coinStatus = arcadeMachine.insertCoin(COIN_TYPES.CanadianQuarter); - }); - - then('my coin should be returned', () => { - expect(coinStatus).toBe('CoinReturned'); - }); - }); - - test('Inserting a badly damaged coin', ({ given, when, then }) => { - let coinStatus; - - givenMyMachineIsConfiguredToRequireCoins(given); - - givenMyMachineIsConfiguredToAcceptUsQuarters(given); - - when('I insert a US Quarter that is badly damaged', () => { - coinStatus = arcadeMachine.insertCoin(COIN_TYPES.Unknown); - }); - - then('my coin should be returned', () => { - expect(coinStatus).toBe('CoinReturned'); - }); - }); -}); +// eslint-disable-next-line import/no-unresolved +import { loadFeature, defineFeature } from 'jest-cucumber'; +import { ArcadeMachine, COIN_TYPES } from '../../src/arcade-machine'; + +const feature = loadFeature('./specs/features/backgrounds.feature'); + +defineFeature(feature, test => { + let arcadeMachine; + + beforeEach(() => { + arcadeMachine = new ArcadeMachine(); + }); + + const givenMyMachineIsConfiguredToRequireCoins = given => { + given('my machine is configured to require coins', () => { + arcadeMachine.requireCoins = true; + }); + }; + + const givenMyMachineIsConfiguredToAcceptUsQuarters = given => { + given('my machine is configured to accept US Quarters', () => { + arcadeMachine.acceptedCoinType = COIN_TYPES.USQuarter; + }); + }; + + test('Successfully inserting coins', ({ given, when, then }) => { + givenMyMachineIsConfiguredToRequireCoins(given); + + given('I have not inserted any coins', () => { + arcadeMachine.balance = 0; + }); + + when('I insert one US quarter', () => { + arcadeMachine.insertCoin(COIN_TYPES.USQuarter); + }); + + then(/^I should have a balance of (\d+) cents$/, balance => { + arcadeMachine.balance = balance / 100; + }); + }); + + test('Inserting a Canadian coin', ({ given, when, then }) => { + let coinStatus; + + givenMyMachineIsConfiguredToRequireCoins(given); + + givenMyMachineIsConfiguredToAcceptUsQuarters(given); + + when('I insert a Canadian Quarter', () => { + coinStatus = arcadeMachine.insertCoin(COIN_TYPES.CanadianQuarter); + }); + + then('my coin should be returned', () => { + expect(coinStatus).toBe('CoinReturned'); + }); + }); + + test('Inserting a badly damaged coin', ({ given, when, then }) => { + let coinStatus; + + givenMyMachineIsConfiguredToRequireCoins(given); + + givenMyMachineIsConfiguredToAcceptUsQuarters(given); + + when('I insert a US Quarter that is badly damaged', () => { + coinStatus = arcadeMachine.insertCoin(COIN_TYPES.Unknown); + }); + + then('my coin should be returned', () => { + expect(coinStatus).toBe('CoinReturned'); + }); + }); +}); diff --git a/examples/ecmascript/specs/step-definitions/basic-scenarios.steps.js b/examples/ecmascript/specs/step-definitions/basic-scenarios.steps.js index 4bad43c..46d5623 100644 --- a/examples/ecmascript/specs/step-definitions/basic-scenarios.steps.js +++ b/examples/ecmascript/specs/step-definitions/basic-scenarios.steps.js @@ -1,27 +1,28 @@ +// eslint-disable-next-line import/no-unresolved import { defineFeature, loadFeature } from 'jest-cucumber'; import { PasswordValidator } from '../../src/password-validator'; const feature = loadFeature('./specs/features/basic-scenarios.feature'); -defineFeature(feature, (test) => { - let passwordValidator = new PasswordValidator(); - let accessGranted = false; +defineFeature(feature, test => { + let passwordValidator = new PasswordValidator(); + let accessGranted = false; - beforeEach(() => { - passwordValidator = new PasswordValidator(); - }); + beforeEach(() => { + passwordValidator = new PasswordValidator(); + }); - test('Entering a correct password', ({ given, when, then }) => { - given('I have previously created a password', () => { - passwordValidator.setPassword('1234'); - }); + test('Entering a correct password', ({ given, when, then }) => { + given('I have previously created a password', () => { + passwordValidator.setPassword('1234'); + }); - when('I enter my password correctly', () => { - accessGranted = passwordValidator.validatePassword('1234'); - }); + when('I enter my password correctly', () => { + accessGranted = passwordValidator.validatePassword('1234'); + }); - then('I should be granted access', () => { - expect(accessGranted).toBe(true); - }); + then('I should be granted access', () => { + expect(accessGranted).toBeTrue(); }); + }); }); diff --git a/examples/ecmascript/specs/step-definitions/more-scenario-outlines.steps.js b/examples/ecmascript/specs/step-definitions/more-scenario-outlines.steps.js index bcc9553..c859dba 100644 --- a/examples/ecmascript/specs/step-definitions/more-scenario-outlines.steps.js +++ b/examples/ecmascript/specs/step-definitions/more-scenario-outlines.steps.js @@ -1,9 +1,10 @@ +// eslint-disable-next-line import/no-unresolved import { defineFeature, loadFeature } from 'jest-cucumber'; import { SeriesSolver } from '../../src/series-solver'; const feature = loadFeature('./specs/features/more-scenario-outlines.feature'); -defineFeature(feature, (test) => { +defineFeature(feature, test => { let solver; let solution; let terms; @@ -13,14 +14,14 @@ defineFeature(feature, (test) => { solver = new SeriesSolver(); }); - const whenISolveTheSeries = (when) => { + const whenISolveTheSeries = when => { when(/^I solve the series$/, () => { solution = solver.solve(terms, operator); }); }; - const thenIShouldGetXAsTheAnswer = (then) => { - then(/^I should get (.*) as the answer$/, (expectedSolution) => { + const thenIShouldGetXAsTheAnswer = then => { + then(/^I should get (.*) as the answer$/, expectedSolution => { expect(solution).toBe(expectedSolution); }); }; @@ -29,12 +30,13 @@ defineFeature(feature, (test) => { given( /^I have a series (.*) (.*) (.*) (.*) (.*) (.*) (.*)$/, (firstTerm, firstOperator, secondTerm, secondOperator, thirdTerm, thirdOperator, forthTerm) => { - expect(firstOperator).toEqual(secondOperator); - expect(firstOperator).toEqual(thirdOperator); + expect(firstOperator).toStrictEqual(secondOperator); + expect(firstOperator).toStrictEqual(thirdOperator); operator = firstOperator; terms = [firstTerm, secondTerm, thirdTerm, forthTerm]; - }); + }, + ); whenISolveTheSeries(when); @@ -42,14 +44,12 @@ defineFeature(feature, (test) => { }); test('Adding series', ({ given, when, then }) => { - given( - /^I add the following series:$/, - (table) => { - const row = table[0]; - terms = row.Series.split(` ${row.Operator} `); - operator = row.Operator; - solver.add(terms, operator, row.Solution); - }); + given(/^I add the following series:$/, table => { + const row = table[0]; + terms = row.Series.split(` ${row.Operator} `); + operator = row.Operator; + solver.add(terms, operator, row.Solution); + }); whenISolveTheSeries(when); diff --git a/examples/ecmascript/specs/step-definitions/scenario-outlines.steps.js b/examples/ecmascript/specs/step-definitions/scenario-outlines.steps.js index 7f24d89..f770178 100644 --- a/examples/ecmascript/specs/step-definitions/scenario-outlines.steps.js +++ b/examples/ecmascript/specs/step-definitions/scenario-outlines.steps.js @@ -1,27 +1,28 @@ +// eslint-disable-next-line import/no-unresolved import { defineFeature, loadFeature } from 'jest-cucumber'; import { OnlineSales } from '../../src/online-sales'; const feature = loadFeature('./specs/features/scenario-outlines.feature'); defineFeature(feature, test => { - let onlineSales; - let salesPrice; - - beforeEach(() => { - onlineSales = new OnlineSales(); - }); + let onlineSales; + let salesPrice; - test('Selling an at $', ({ given, when, then, pending }) => { - given(/^I have a\(n\) (.*)$/, item => { - onlineSales.listItem(item); - }); + beforeEach(() => { + onlineSales = new OnlineSales(); + }); - when(/^I sell the (.*)$/, item => { - salesPrice = onlineSales.sellItem(item); - }); + test('Selling an at $', ({ given, when, then }) => { + given(/^I have a\(n\) (.*)$/, item => { + onlineSales.listItem(item); + }); - then(/^I should get \$(\d+)$/, expectedSalesPrice => { - expect(salesPrice).toBe(parseInt(expectedSalesPrice)); - }); - }); -}); \ No newline at end of file + when(/^I sell the (.*)$/, item => { + salesPrice = onlineSales.sellItem(item); + }); + + then(/^I should get \$(\d+)$/, expectedSalesPrice => { + expect(salesPrice).toBe(parseInt(expectedSalesPrice, 10)); + }); + }); +}); diff --git a/examples/ecmascript/specs/step-definitions/using-docstrings.steps.js b/examples/ecmascript/specs/step-definitions/using-docstrings.steps.js index cbc6b86..ba4b4b3 100644 --- a/examples/ecmascript/specs/step-definitions/using-docstrings.steps.js +++ b/examples/ecmascript/specs/step-definitions/using-docstrings.steps.js @@ -1,27 +1,28 @@ +// eslint-disable-next-line import/no-unresolved import { defineFeature, loadFeature } from 'jest-cucumber'; import { CertificateFactory } from '../../src/certificate-factory'; const feature = loadFeature('./specs/features/using-docstrings.feature'); defineFeature(feature, test => { - let certificateFactory; - let certificate; + let certificateFactory; + let certificate; - beforeEach(() => { - certificateFactory = new CertificateFactory(); - }); + beforeEach(() => { + certificateFactory = new CertificateFactory(); + }); - test('Print a certificate', ({ given, when, then }) => { - given(/^(.*) (.*) has achieved a ([0-9]*)$/, (title, lastName, score) => { - certificateFactory.setReceiver(title, lastName, score); - }); + test('Print a certificate', ({ given, when, then }) => { + given(/^(.*) (.*) has achieved a ([0-9]*)$/, (title, lastName, score) => { + certificateFactory.setReceiver(title, lastName, score); + }); - when(/^I print the certificate$/, () => { - certificate = certificateFactory.printCertificate(); - }); + when(/^I print the certificate$/, () => { + certificate = certificateFactory.printCertificate(); + }); - then(/^It prints$/, (expectedCertificate) => { - expect(certificate).toBe(expectedCertificate); - }); + then(/^It prints$/, expectedCertificate => { + expect(certificate).toBe(expectedCertificate); }); + }); }); diff --git a/examples/ecmascript/specs/step-definitions/using-dynamic-values.steps.js b/examples/ecmascript/specs/step-definitions/using-dynamic-values.steps.js index e348158..6e9aec8 100644 --- a/examples/ecmascript/specs/step-definitions/using-dynamic-values.steps.js +++ b/examples/ecmascript/specs/step-definitions/using-dynamic-values.steps.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line import/no-unresolved import { defineFeature, loadFeature } from 'jest-cucumber'; import { BankAccount } from '../../src/bank-account'; @@ -5,23 +6,23 @@ import { BankAccount } from '../../src/bank-account'; const feature = loadFeature('./specs/features/using-dynamic-values.feature'); defineFeature(feature, test => { - let myAccount; - - beforeEach(() => { - myAccount = new BankAccount(); - }); + let myAccount; - test('Depositing a paycheck', ({ given, when, then, pending }) => { - given(/^my account balance is \$(\d+)$/, balance => { - myAccount.deposit(parseInt(balance)); - }); + beforeEach(() => { + myAccount = new BankAccount(); + }); - when(/^I get paid \$(\d+) for writing some awesome code$/, paycheck => { - myAccount.deposit(parseInt(paycheck)); - }); + test('Depositing a paycheck', ({ given, when, then }) => { + given(/^my account balance is \$(\d+)$/, balance => { + myAccount.deposit(parseInt(balance, 10)); + }); - then(/^my account balance should be \$(\d+)$/, expectedBalance => { - expect(myAccount.balance).toBe(parseInt(expectedBalance)); - }); - }); -}); \ No newline at end of file + when(/^I get paid \$(\d+) for writing some awesome code$/, paycheck => { + myAccount.deposit(parseInt(paycheck, 10)); + }); + + then(/^my account balance should be \$(\d+)$/, expectedBalance => { + expect(myAccount.balance).toBe(parseInt(expectedBalance, 10)); + }); + }); +}); diff --git a/examples/ecmascript/specs/step-definitions/using-gherkin-tables.steps.js b/examples/ecmascript/specs/step-definitions/using-gherkin-tables.steps.js index 4f1b20e..693ed24 100644 --- a/examples/ecmascript/specs/step-definitions/using-gherkin-tables.steps.js +++ b/examples/ecmascript/specs/step-definitions/using-gherkin-tables.steps.js @@ -1,39 +1,40 @@ +// eslint-disable-next-line import/no-unresolved import { defineFeature, loadFeature } from 'jest-cucumber'; import { TodoList } from '../../src/todo-list'; const feature = loadFeature('./specs/features/using-gherkin-tables.feature'); defineFeature(feature, test => { - let todoList; - - beforeEach(() => { - todoList = new TodoList(); - }); + let todoList; - test('Adding an item to my todo list', ({ given, when, then }) => { - given('my todo list currently looks as follows:', table => { - table.forEach(row => { - todoList.add({ - name: row.TaskName, - priority: row.Priority - }); - }); - }); + beforeEach(() => { + todoList = new TodoList(); + }); - when('I add the following task:', table => { - todoList.add({ - name: table[0].TaskName, - priority: table[0].Priority - }); + test('Adding an item to my todo list', ({ given, when, then }) => { + given('my todo list currently looks as follows:', table => { + table.forEach(row => { + todoList.add({ + name: row.TaskName, + priority: row.Priority, }); + }); + }); - then('I should see the following todo list:', table => { - expect(todoList.items.length).toBe(table.length); + when('I add the following task:', table => { + todoList.add({ + name: table[0].TaskName, + priority: table[0].Priority, + }); + }); - table.forEach((row, index) => { - expect(todoList.items[index].name).toBe(table[index].TaskName); - expect(todoList.items[index].priority).toBe(table[index].Priority); - }); - }); + then('I should see the following todo list:', table => { + expect(todoList.items).toHaveLength(table.length); + + table.forEach((row, index) => { + expect(todoList.items[index].name).toBe(table[index].TaskName); + expect(todoList.items[index].priority).toBe(table[index].Priority); + }); }); -}); \ No newline at end of file + }); +}); diff --git a/examples/ecmascript/specs/step-definitions/using-latest-gherkin-keywords.steps.js b/examples/ecmascript/specs/step-definitions/using-latest-gherkin-keywords.steps.js index 614c913..0073049 100644 --- a/examples/ecmascript/specs/step-definitions/using-latest-gherkin-keywords.steps.js +++ b/examples/ecmascript/specs/step-definitions/using-latest-gherkin-keywords.steps.js @@ -1,79 +1,80 @@ -import { defineFeature, loadFeature } from 'jest-cucumber'; - -import { Calculator } from '../../src/calculator'; - -const feature = loadFeature('./specs/features/using-latest-gherkin-keywords.feature'); - -defineFeature(feature, (test) => { - let calculator; - let output; - - beforeEach(() => { - calculator = new Calculator(); - }); - - const givenIHaveEnteredXAsTheFirstOperand = (given) => { - given(/^I have entered "(\d+)" as the first operand$/, (firstOperand) => { - calculator.setFirstOperand(parseFloat(firstOperand)); - }); - }; - - const andIHaveEnteredXAsTheOperator = (and) => { - and(/^I have entered "([+-/*])" as the operator$/, (operator) => { - calculator.setCalculatorOperator(operator); - }); - }; - - const andIHaveEnteredXAsTheSecondOperand = (and) => { - and(/^I have entered "(\d+)" as the second operand$/, (secondOperand) => { - calculator.setSecondOperand(parseFloat(secondOperand)); - }); - }; - - const whenIPressTheEnterKey = (when) => { - when('I press the equals key', () => { - output = calculator.computeOutput(); - }); - }; - - const thenTheOutputOfXShouldBeDisplayed = (then) => { - then(/^the output of "(\d+)" should be displayed$/, (expectedOutput) => { - if (!expectedOutput) { - expect(output).toBeFalsy(); - } else { - expect(output).toBe(parseFloat(expectedOutput)); - } - }); - }; - - test('Subtracting two numbers', ({ given, and, when, then }) => { - givenIHaveEnteredXAsTheFirstOperand(given); - andIHaveEnteredXAsTheOperator(and); - andIHaveEnteredXAsTheSecondOperand(and); - whenIPressTheEnterKey(when); - thenTheOutputOfXShouldBeDisplayed(then); - }); - - test('Attempting to subtract without entering a second number', ({ given, and, when, then }) => { - givenIHaveEnteredXAsTheFirstOperand(given); - andIHaveEnteredXAsTheOperator(and); - - and('I have not entered a second operand', () => { - // Nothing to do here - }); - - whenIPressTheEnterKey(when); - - then('no output should be displayed', () => { - expect(output).toBeFalsy(); - }); - }); - - test('Division operations', ({ given, and, when, then }) => { - givenIHaveEnteredXAsTheFirstOperand(given); - andIHaveEnteredXAsTheOperator(and); - andIHaveEnteredXAsTheSecondOperand(and); - whenIPressTheEnterKey(when); - thenTheOutputOfXShouldBeDisplayed(then); - }); -}); +// eslint-disable-next-line import/no-unresolved +import { defineFeature, loadFeature } from 'jest-cucumber'; + +import { Calculator } from '../../src/calculator'; + +const feature = loadFeature('./specs/features/using-latest-gherkin-keywords.feature'); + +defineFeature(feature, test => { + let calculator; + let output; + + beforeEach(() => { + calculator = new Calculator(); + }); + + const givenIHaveEnteredXAsTheFirstOperand = given => { + given(/^I have entered "(\d+)" as the first operand$/, firstOperand => { + calculator.setFirstOperand(parseFloat(firstOperand)); + }); + }; + + const andIHaveEnteredXAsTheOperator = and => { + and(/^I have entered "([+-/*])" as the operator$/, operator => { + calculator.setCalculatorOperator(operator); + }); + }; + + const andIHaveEnteredXAsTheSecondOperand = and => { + and(/^I have entered "(\d+)" as the second operand$/, secondOperand => { + calculator.setSecondOperand(parseFloat(secondOperand)); + }); + }; + + const whenIPressTheEnterKey = when => { + when('I press the equals key', () => { + output = calculator.computeOutput(); + }); + }; + + const thenTheOutputOfXShouldBeDisplayed = then => { + then(/^the output of "(\d+)" should be displayed$/, expectedOutput => { + if (!expectedOutput) { + expect(output).toBeFalsy(); + } else { + expect(output).toBe(parseFloat(expectedOutput)); + } + }); + }; + + test('Subtracting two numbers', ({ given, and, when, then }) => { + givenIHaveEnteredXAsTheFirstOperand(given); + andIHaveEnteredXAsTheOperator(and); + andIHaveEnteredXAsTheSecondOperand(and); + whenIPressTheEnterKey(when); + thenTheOutputOfXShouldBeDisplayed(then); + }); + + test('Attempting to subtract without entering a second number', ({ given, and, when, then }) => { + givenIHaveEnteredXAsTheFirstOperand(given); + andIHaveEnteredXAsTheOperator(and); + + and('I have not entered a second operand', () => { + // Nothing to do here + }); + + whenIPressTheEnterKey(when); + + then('no output should be displayed', () => { + expect(output).toBeFalsy(); + }); + }); + + test('Division operations', ({ given, and, when, then }) => { + givenIHaveEnteredXAsTheFirstOperand(given); + andIHaveEnteredXAsTheOperator(and); + andIHaveEnteredXAsTheSecondOperand(and); + whenIPressTheEnterKey(when); + thenTheOutputOfXShouldBeDisplayed(then); + }); +}); diff --git a/examples/ecmascript/src/arcade-machine.js b/examples/ecmascript/src/arcade-machine.js index 9a94f6a..5d1c4c2 100644 --- a/examples/ecmascript/src/arcade-machine.js +++ b/examples/ecmascript/src/arcade-machine.js @@ -1,27 +1,26 @@ -export const COIN_TYPES = { - USQuarter: { value: 0.25, issuingNation: 'USA' }, - CanadianQuarter: { value: 0.25, issuingNation: 'Canada' }, - Unknown: { value: 0, issuingNation: 'Unknown' }, -}; - -export class ArcadeMachine { - constructor() { - this.acceptedCoinType = null; - this.balance = 0; - this.requireCoins = true; - } - - insertCoin(coinType) { - if (!this.requireCoins) { - return 'CoinReturned'; - } - - if (coinType === this.acceptedCoinType) { - this.balance += coinType.value; - - return 'CoinAccepted'; - } else { - return 'CoinReturned'; - } - } -} +export const COIN_TYPES = { + USQuarter: { value: 0.25, issuingNation: 'USA' }, + CanadianQuarter: { value: 0.25, issuingNation: 'Canada' }, + Unknown: { value: 0, issuingNation: 'Unknown' }, +}; + +export class ArcadeMachine { + constructor() { + this.acceptedCoinType = null; + this.balance = 0; + this.requireCoins = true; + } + + insertCoin(coinType) { + if (!this.requireCoins) { + return 'CoinReturned'; + } + + if (coinType === this.acceptedCoinType) { + this.balance += coinType.value; + + return 'CoinAccepted'; + } + return 'CoinReturned'; + } +} diff --git a/examples/ecmascript/src/bank-account.js b/examples/ecmascript/src/bank-account.js index 6744d52..5d6365d 100644 --- a/examples/ecmascript/src/bank-account.js +++ b/examples/ecmascript/src/bank-account.js @@ -1,13 +1,13 @@ export class BankAccount { - constructor() { - this.balance = 0; - } - - deposit(amount) { - this.balance += amount; - } + constructor() { + this.balance = 0; + } - withdraw(amount) { - this.balance -= amount; - } -} \ No newline at end of file + deposit(amount) { + this.balance += amount; + } + + withdraw(amount) { + this.balance -= amount; + } +} diff --git a/examples/ecmascript/src/calculator.js b/examples/ecmascript/src/calculator.js index 4d515cd..489d429 100644 --- a/examples/ecmascript/src/calculator.js +++ b/examples/ecmascript/src/calculator.js @@ -1,30 +1,32 @@ -export class Calculator { - setFirstOperand(operand) { - this.firstOperand = operand; - } - - setSecondOperand(operand) { - this.secondOperand = operand; - } - - setCalculatorOperator(operator) { - this.operator = operator; - } - - computeOutput() { - if (!this.firstOperand || !this.secondOperand || !this.operator) { - return; - } - - switch (this.operator) { - case '+': - return this.firstOperand + this.secondOperand; - case '-': - return this.firstOperand - this.secondOperand; - case '*': - return this.firstOperand * this.secondOperand; - case '/': - return this.firstOperand / this.secondOperand; - } - } -} +export class Calculator { + setFirstOperand(operand) { + this.firstOperand = operand; + } + + setSecondOperand(operand) { + this.secondOperand = operand; + } + + setCalculatorOperator(operator) { + this.operator = operator; + } + + computeOutput() { + if (!this.firstOperand || !this.secondOperand || !this.operator) { + return null; + } + + switch (this.operator) { + case '+': + return this.firstOperand + this.secondOperand; + case '-': + return this.firstOperand - this.secondOperand; + case '*': + return this.firstOperand * this.secondOperand; + case '/': + return this.firstOperand / this.secondOperand; + default: + return null; + } + } +} diff --git a/examples/ecmascript/src/certificate-factory.js b/examples/ecmascript/src/certificate-factory.js index 67deb36..5ee80ec 100644 --- a/examples/ecmascript/src/certificate-factory.js +++ b/examples/ecmascript/src/certificate-factory.js @@ -1,33 +1,33 @@ export class CertificateFactory { - constructor() { - this.title = ''; - this.lastName = ''; - this.score = 0; - this.rank = 'Novice'; - } + constructor() { + this.title = ''; + this.lastName = ''; + this.score = 0; + this.rank = 'Novice'; + } - setReceiver(title, name, score) { - this.title = title; - this.lastName = name; - this.score = Number.parseInt(score, 10); - if (this.score > 2700) { - this.rank = 'Super Grandmaster'; - } else if (this.score > 2500) { - this.rank = 'Grandmaster'; - } else if (this.score > 2000) { - this.rank = 'Expert'; - } + setReceiver(title, name, score) { + this.title = title; + this.lastName = name; + this.score = Number.parseInt(score, 10); + if (this.score > 2700) { + this.rank = 'Super Grandmaster'; + } else if (this.score > 2500) { + this.rank = 'Grandmaster'; + } else if (this.score > 2000) { + this.rank = 'Expert'; } + } - printCertificate() { - const pieces = [ - `Certificate of Mastery`, - `The title of ${this.rank} is hereby awarded to:`, - `${this.title} ${this.lastName}`, - `For achieving a score of ${this.score}, ${this.title} ${this.lastName}`, - `may henceforth use the title ${this.rank}.`, - ]; + printCertificate() { + const pieces = [ + `Certificate of Mastery`, + `The title of ${this.rank} is hereby awarded to:`, + `${this.title} ${this.lastName}`, + `For achieving a score of ${this.score}, ${this.title} ${this.lastName}`, + `may henceforth use the title ${this.rank}.`, + ]; - return pieces.join('\n'); - } + return pieces.join('\n'); + } } diff --git a/examples/ecmascript/src/online-sales.js b/examples/ecmascript/src/online-sales.js index 170ef83..e4e69ec 100644 --- a/examples/ecmascript/src/online-sales.js +++ b/examples/ecmascript/src/online-sales.js @@ -1,27 +1,26 @@ const itemPrices = { - 'Autographed Neil deGrasse Tyson book': 100, - 'Rick Astley t-shirt': 22, - 'An idea to replace EVERYTHING with blockchains': 0 + 'Autographed Neil deGrasse Tyson book': 100, + 'Rick Astley t-shirt': 22, + 'An idea to replace EVERYTHING with blockchains': 0, }; export class OnlineSales { - constructor() { - this.listedItems = []; - } + constructor() { + this.listedItems = []; + } - listItem(name) { - this.listedItems.push(name); - } + listItem(name) { + this.listedItems.push(name); + } - sellItem(name) { - const itemIndex = this.listedItems.indexOf(name); + sellItem(name) { + const itemIndex = this.listedItems.indexOf(name); - if (itemIndex !== -1) { - this.listedItems.splice(itemIndex, 1); + if (itemIndex !== -1) { + this.listedItems.splice(itemIndex, 1); - return itemPrices[name]; - } else { - return null; - } + return itemPrices[name]; } -} \ No newline at end of file + return null; + } +} diff --git a/examples/ecmascript/src/password-validator.js b/examples/ecmascript/src/password-validator.js index 3f67741..09d1849 100644 --- a/examples/ecmascript/src/password-validator.js +++ b/examples/ecmascript/src/password-validator.js @@ -1,9 +1,9 @@ -export class PasswordValidator { - setPassword(password) { - this.password = password; - } - - validatePassword(claimedPassword) { - return this.password === claimedPassword; - } -} +export class PasswordValidator { + setPassword(password) { + this.password = password; + } + + validatePassword(claimedPassword) { + return this.password === claimedPassword; + } +} diff --git a/examples/ecmascript/src/rocket.js b/examples/ecmascript/src/rocket.js index 55ac1e2..9ede040 100644 --- a/examples/ecmascript/src/rocket.js +++ b/examples/ecmascript/src/rocket.js @@ -1,11 +1,11 @@ export class Rocket { - constructor() { - this.isInSpace = false; - this.boostersLanded = true; - } + constructor() { + this.isInSpace = false; + this.boostersLanded = true; + } - launch() { - this.isInSpace = true; - this.boostersLanded = true; - } -} \ No newline at end of file + launch() { + this.isInSpace = true; + this.boostersLanded = true; + } +} diff --git a/examples/ecmascript/src/todo-list.js b/examples/ecmascript/src/todo-list.js index fe5167a..85c45df 100644 --- a/examples/ecmascript/src/todo-list.js +++ b/examples/ecmascript/src/todo-list.js @@ -1,18 +1,18 @@ export class TodoList { - constructor() { - this.items = []; - } + constructor() { + this.items = []; + } - add(todo) { - if (todo.name.toLocaleLowerCase().indexOf('youtube')) { - this.items = []; - this.items.push(todo); - this.items.push({ - name: 'Sign up for unemployment', - priority: 'high' - }); - } else { - this.items.push(todo); - } + add(todo) { + if (todo.name.toLocaleLowerCase().indexOf('youtube')) { + this.items = []; + this.items.push(todo); + this.items.push({ + name: 'Sign up for unemployment', + priority: 'high', + }); + } else { + this.items.push(todo); } -} \ No newline at end of file + } +} diff --git a/examples/ecmascript/src/vending-machine.js b/examples/ecmascript/src/vending-machine.js index 899f862..e5c3f25 100644 --- a/examples/ecmascript/src/vending-machine.js +++ b/examples/ecmascript/src/vending-machine.js @@ -1,25 +1,25 @@ -const ITEM_COST = 0.50; - -export class VendingMachine { - constructor() { - this.balance = 0; - this.items = {}; - } - - stockItem(itemName, count) { - this.items[itemName] = this.items[itemName] || 0; - this.items[itemName] += count; - } - - insertMoney(amount) { - this.balance += amount; - } - - dispenseItem(itemName) { - if (this.balance >= ITEM_COST && this.items[itemName] > 0) { - this.balance -= ITEM_COST; - } - - this.items[itemName]--; - } -} +const ITEM_COST = 0.5; + +export class VendingMachine { + constructor() { + this.balance = 0; + this.items = {}; + } + + stockItem(itemName, count) { + this.items[itemName] = this.items[itemName] || 0; + this.items[itemName] += count; + } + + insertMoney(amount) { + this.balance += amount; + } + + dispenseItem(itemName) { + if (this.balance >= ITEM_COST && this.items[itemName] > 0) { + this.balance -= ITEM_COST; + } + + this.items[itemName] -= 1; + } +} diff --git a/examples/typescript/specs/step-definitions/auto-step-binding.steps.ts b/examples/typescript/specs/step-definitions/auto-step-binding.steps.ts index 06a7d1c..593e2b3 100644 --- a/examples/typescript/specs/step-definitions/auto-step-binding.steps.ts +++ b/examples/typescript/specs/step-definitions/auto-step-binding.steps.ts @@ -1,28 +1,28 @@ -import { StepDefinitions, loadFeatures, autoBindSteps } from '../../../../src'; -import { VendingMachine } from '../../src/vending-machine'; - -export const vendingMachineSteps: StepDefinitions = ({ given, and, when, then }) => { - let vendingMachine: VendingMachine; - - given(/^the vending machine has "(.*)" in stock$/, (itemName: string) => { - vendingMachine = new VendingMachine(); - vendingMachine.stockItem(itemName, 1); - }); - - and('I have inserted the correct amount of money', () => { - vendingMachine.insertMoney(0.50); - }); - - when(/^I purchase "(.*)"$/, (itemName: string) => { - vendingMachine.dispenseItem(itemName); - }); - - then(/^my "(.*)" should be dispensed$/, (itemName: string) => { - const inventoryAmount = vendingMachine.items[itemName]; - expect(inventoryAmount).toBe(0); - }); -}; - -const features = loadFeatures('./examples/typescript/specs/features/auto-binding/**/*.feature'); - -autoBindSteps(features, [ vendingMachineSteps ]); +import { StepDefinitions, loadFeatures, autoBindSteps } from '../../../../src'; +import { VendingMachine } from '../../src/vending-machine'; + +export const vendingMachineSteps: StepDefinitions = ({ given, and, when, then }) => { + let vendingMachine: VendingMachine; + + given(/^the vending machine has "(.*)" in stock$/, (itemName: string) => { + vendingMachine = new VendingMachine(); + vendingMachine.stockItem(itemName, 1); + }); + + and('I have inserted the correct amount of money', () => { + vendingMachine.insertMoney(0.5); + }); + + when(/^I purchase "(.*)"$/, (itemName: string) => { + vendingMachine.dispenseItem(itemName); + }); + + then(/^my "(.*)" should be dispensed$/, (itemName: string) => { + const inventoryAmount = vendingMachine.items[itemName]; + expect(inventoryAmount).toBe(0); + }); +}; + +const features = loadFeatures('./examples/typescript/specs/features/auto-binding/**/*.feature'); + +autoBindSteps(features, [vendingMachineSteps]); diff --git a/examples/typescript/specs/step-definitions/backgrounds.steps.ts b/examples/typescript/specs/step-definitions/backgrounds.steps.ts index eb1840e..c88c8d6 100644 --- a/examples/typescript/specs/step-definitions/backgrounds.steps.ts +++ b/examples/typescript/specs/step-definitions/backgrounds.steps.ts @@ -1,72 +1,72 @@ -import { loadFeature, defineFeature, DefineStepFunction } from '../../../../src/'; -import { ArcadeMachine, COIN_TYPES, CoinStatus } from '../../src/arcade-machine'; - -const feature = loadFeature('./examples/typescript/specs/features/backgrounds.feature'); - -defineFeature(feature, (test) => { - let arcadeMachine: ArcadeMachine; - - beforeEach(() => { - arcadeMachine = new ArcadeMachine(); - }); - - const givenMyMachineIsConfiguredToRequireCoins = (given: DefineStepFunction) => { - given('my machine is configured to require coins', () => { - arcadeMachine.requireCoins = true; - }); - }; - - const givenMyMachineIsConfiguredToAcceptUsQuarters = (given: DefineStepFunction) => { - given('my machine is configured to accept US Quarters', () => { - arcadeMachine.acceptedCoinType = COIN_TYPES.USQuarter; - }); - }; - - test('Successfully inserting coins', ({ given, when, then }) => { - givenMyMachineIsConfiguredToRequireCoins(given); - - given('I have not inserted any coins', () => { - arcadeMachine.balance = 0; - }); - - when('I insert one US quarter', () => { - arcadeMachine.insertCoin(COIN_TYPES.USQuarter); - }); - - then(/^I should have a balance of (\d+) cents$/, (balance) => { - arcadeMachine.balance = balance / 100; - }); - }); - - test('Inserting a Canadian coin', ({ given, when, then }) => { - let coinStatus: CoinStatus; - - givenMyMachineIsConfiguredToRequireCoins(given); - - givenMyMachineIsConfiguredToAcceptUsQuarters(given); - - when('I insert a Canadian Quarter', () => { - coinStatus = arcadeMachine.insertCoin(COIN_TYPES.CanadianQuarter); - }); - - then('my coin should be returned', () => { - expect(coinStatus).toBe('CoinReturned'); - }); - }); - - test('Inserting a badly damaged coin', ({ given, when, then }) => { - let coinStatus: CoinStatus; - - givenMyMachineIsConfiguredToRequireCoins(given); - - givenMyMachineIsConfiguredToAcceptUsQuarters(given); - - when('I insert a US Quarter that is badly damaged', () => { - coinStatus = arcadeMachine.insertCoin(COIN_TYPES.Unknown); - }); - - then('my coin should be returned', () => { - expect(coinStatus).toBe('CoinReturned'); - }); - }); -}); +import { loadFeature, defineFeature, DefineStepFunction } from '../../../../src'; +import { ArcadeMachine, COIN_TYPES, CoinStatus } from '../../src/arcade-machine'; + +const feature = loadFeature('./examples/typescript/specs/features/backgrounds.feature'); + +defineFeature(feature, test => { + let arcadeMachine: ArcadeMachine; + + beforeEach(() => { + arcadeMachine = new ArcadeMachine(); + }); + + const givenMyMachineIsConfiguredToRequireCoins = (given: DefineStepFunction) => { + given('my machine is configured to require coins', () => { + arcadeMachine.requireCoins = true; + }); + }; + + const givenMyMachineIsConfiguredToAcceptUsQuarters = (given: DefineStepFunction) => { + given('my machine is configured to accept US Quarters', () => { + arcadeMachine.acceptedCoinType = COIN_TYPES.USQuarter; + }); + }; + + test('Successfully inserting coins', ({ given, when, then }) => { + givenMyMachineIsConfiguredToRequireCoins(given); + + given('I have not inserted any coins', () => { + arcadeMachine.balance = 0; + }); + + when('I insert one US quarter', () => { + arcadeMachine.insertCoin(COIN_TYPES.USQuarter); + }); + + then(/^I should have a balance of (\d+) cents$/, balance => { + arcadeMachine.balance = balance / 100; + }); + }); + + test('Inserting a Canadian coin', ({ given, when, then }) => { + let coinStatus: CoinStatus; + + givenMyMachineIsConfiguredToRequireCoins(given); + + givenMyMachineIsConfiguredToAcceptUsQuarters(given); + + when('I insert a Canadian Quarter', () => { + coinStatus = arcadeMachine.insertCoin(COIN_TYPES.CanadianQuarter); + }); + + then('my coin should be returned', () => { + expect(coinStatus).toBe('CoinReturned'); + }); + }); + + test('Inserting a badly damaged coin', ({ given, when, then }) => { + let coinStatus: CoinStatus; + + givenMyMachineIsConfiguredToRequireCoins(given); + + givenMyMachineIsConfiguredToAcceptUsQuarters(given); + + when('I insert a US Quarter that is badly damaged', () => { + coinStatus = arcadeMachine.insertCoin(COIN_TYPES.Unknown); + }); + + then('my coin should be returned', () => { + expect(coinStatus).toBe('CoinReturned'); + }); + }); +}); diff --git a/examples/typescript/specs/step-definitions/basic-scenarios.steps.ts b/examples/typescript/specs/step-definitions/basic-scenarios.steps.ts index 93d1acd..d7624e7 100644 --- a/examples/typescript/specs/step-definitions/basic-scenarios.steps.ts +++ b/examples/typescript/specs/step-definitions/basic-scenarios.steps.ts @@ -1,27 +1,27 @@ -import { loadFeature, defineFeature } from '../../../../src/'; +import { loadFeature, defineFeature } from '../../../../src'; import { PasswordValidator } from '../../src/password-validator'; const feature = loadFeature('./examples/typescript/specs/features/basic-scenarios.feature'); -defineFeature(feature, (test) => { - let passwordValidator = new PasswordValidator(); - let accessGranted = false; +defineFeature(feature, test => { + let passwordValidator = new PasswordValidator(); + let accessGranted = false; - beforeEach(() => { - passwordValidator = new PasswordValidator(); - }); + beforeEach(() => { + passwordValidator = new PasswordValidator(); + }); - test('Entering a correct password', ({ given, when, then }) => { - given('I have previously created a password', () => { - passwordValidator.setPassword('1234'); - }); + test('Entering a correct password', ({ given, when, then }) => { + given('I have previously created a password', () => { + passwordValidator.setPassword('1234'); + }); - when('I enter my password correctly', () => { - accessGranted = passwordValidator.validatePassword('1234'); - }); + when('I enter my password correctly', () => { + accessGranted = passwordValidator.validatePassword('1234'); + }); - then('I should be granted access', () => { - expect(accessGranted).toBe(true); - }); + then('I should be granted access', () => { + expect(accessGranted).toBeTruthy(); }); + }); }); diff --git a/examples/typescript/specs/step-definitions/language.steps.ts b/examples/typescript/specs/step-definitions/language.steps.ts index 60cfff3..6dc59c4 100644 --- a/examples/typescript/specs/step-definitions/language.steps.ts +++ b/examples/typescript/specs/step-definitions/language.steps.ts @@ -1,4 +1,4 @@ -import { loadFeature, defineFeature } from '../../../../src/'; +import { loadFeature, defineFeature } from '../../../../src'; import { PasswordValidator } from '../../src/password-validator'; import { OnlineSales } from '../../src/online-sales'; import { BankAccount } from '../../src/bank-account'; @@ -6,103 +6,108 @@ import { TodoList } from '../../src/todo-list'; const feature = loadFeature('./examples/typescript/specs/features/language.feature'); -defineFeature(feature, (test) => { - describe('basic-scenarios', () => { - let passwordValidator = new PasswordValidator(); - let accessGranted = false; +type TestDate = { + TaakNaam: string; + Prioriteit: string; +}; - beforeEach(() => { - passwordValidator = new PasswordValidator(); - }); +defineFeature(feature, test => { + describe('basic-scenarios', () => { + let passwordValidator = new PasswordValidator(); + let accessGranted = false; + + beforeEach(() => { + passwordValidator = new PasswordValidator(); + }); - test('Invullen van een correct wachtwoord', ({ given, when, then }) => { - given('ik heb voorheen een wachtwoord aangemaakt', () => { - passwordValidator.setPassword('1234'); - }); + test('Invullen van een correct wachtwoord', ({ given, when, then }) => { + given('ik heb voorheen een wachtwoord aangemaakt', () => { + passwordValidator.setPassword('1234'); + }); - when('ik het correcte wachtwoord invoer', () => { - accessGranted = passwordValidator.validatePassword('1234'); - }); + when('ik het correcte wachtwoord invoer', () => { + accessGranted = passwordValidator.validatePassword('1234'); + }); - then('krijg ik toegang', () => { - expect(accessGranted).toBe(true); - }); - }); + then('krijg ik toegang', () => { + expect(accessGranted).toBeTruthy(); + }); }); + }); - describe('scenario-outlines', () => { - test('Verkoop voor €', ({ given, when, then }) => { - const onlineSales = new OnlineSales(); - let salesPrice: number | null; + describe('scenario-outlines', () => { + test('Verkoop voor €', ({ given, when, then }) => { + const onlineSales = new OnlineSales(); + let salesPrice: number | null; - given(/^ik heb een (.*)$/, (item) => { - onlineSales.listItem(item); - }); + given(/^ik heb een (.*)$/, item => { + onlineSales.listItem(item); + }); - when(/^ik (.*) verkoop$/, (item) => { - salesPrice = onlineSales.sellItem(item); - }); + when(/^ik (.*) verkoop$/, item => { + salesPrice = onlineSales.sellItem(item); + }); - then(/^zou ik €(\d+) ontvangen$/, (expectedSalesPrice) => { - expect(salesPrice).toBe(parseInt(expectedSalesPrice, 10)); - }); - }); + then(/^zou ik €(\d+) ontvangen$/, expectedSalesPrice => { + expect(salesPrice).toBe(parseInt(expectedSalesPrice, 10)); + }); }); + }); - describe('using-dynamic-values', () => { - let myAccount: BankAccount; + describe('using-dynamic-values', () => { + let myAccount: BankAccount; - beforeEach(() => { - myAccount = new BankAccount(); - }); + beforeEach(() => { + myAccount = new BankAccount(); + }); - test('Mijn salaris storten', ({ given, when, then, pending }) => { - given(/^mijn account balans is \€(\d+)$/, (balance) => { - myAccount.deposit(parseInt(balance, 10)); - }); + test('Mijn salaris storten', ({ given, when, then }) => { + given(/^mijn account balans is €(\d+)$/, balance => { + myAccount.deposit(parseInt(balance, 10)); + }); - when(/^ik \€(\d+) krijg betaald voor het schrijven van geweldige code$/, (paycheck) => { - myAccount.deposit(parseInt(paycheck, 10)); - }); + when(/^ik €(\d+) krijg betaald voor het schrijven van geweldige code$/, paycheck => { + myAccount.deposit(parseInt(paycheck, 10)); + }); - then(/^zou mijn account balans \€(\d+) zijn$/, (expectedBalance) => { - expect(myAccount.balance).toBe(parseInt(expectedBalance, 10)); - }); - }); + then(/^zou mijn account balans €(\d+) zijn$/, expectedBalance => { + expect(myAccount.balance).toBe(parseInt(expectedBalance, 10)); + }); + }); + }); + + describe('using-gherkin-tables', () => { + let todoList: TodoList; + + beforeEach(() => { + todoList = new TodoList(); }); - describe('using-gherkin-tables', () => { - let todoList: TodoList; + test('een artikel toevoegen aan mijn takenlijst', ({ given, when, then }) => { + given('mijn ziet mijn takenlijst er zo uit:', (table: TestDate[]) => { + table.forEach(row => { + todoList.add({ + name: row.TaakNaam, + priority: row.Prioriteit, + }); + }); + }); - beforeEach(() => { - todoList = new TodoList(); + when('ik de volgende taken toevoeg:', (table: TestDate[]) => { + todoList.add({ + name: table[0].TaakNaam, + priority: table[0].Prioriteit, }); + }); + + then('zou ik de volgende takenlijst zien:', (table: TestDate[]) => { + expect(todoList.items).toHaveLength(table.length); - test('een artikel toevoegen aan mijn takenlijst', ({ given, when, then }) => { - given('mijn ziet mijn takenlijst er zo uit:', (table: any[]) => { - table.forEach((row: any) => { - todoList.add({ - name: row.TaakNaam, - priority: row.Prioriteit, - }); - }); - }); - - when('ik de volgende taken toevoeg:', (table: any) => { - todoList.add({ - name: table[0].TaakNaam, - priority: table[0].Prioriteit, - }); - }); - - then('zou ik de volgende takenlijst zien:', (table: any[]) => { - expect(todoList.items.length).toBe(table.length); - - table.forEach((row: any, index) => { - expect(todoList.items[index].name).toBe(table[index].TaakNaam); - expect(todoList.items[index].priority).toBe(table[index].Prioriteit); - }); - }); + table.forEach((_, index) => { + expect(todoList.items[index].name).toBe(table[index].TaakNaam); + expect(todoList.items[index].priority).toBe(table[index].Prioriteit); }); + }); }); + }); }); diff --git a/examples/typescript/specs/step-definitions/more-scenario-outlines.steps.ts b/examples/typescript/specs/step-definitions/more-scenario-outlines.steps.ts index 3064ff8..6f78b39 100644 --- a/examples/typescript/specs/step-definitions/more-scenario-outlines.steps.ts +++ b/examples/typescript/specs/step-definitions/more-scenario-outlines.steps.ts @@ -3,7 +3,7 @@ import { SeriesSolver } from '../../src/series-solver'; const feature = loadFeature('./examples/typescript/specs/features/more-scenario-outlines.feature'); -defineFeature(feature, (test) => { +defineFeature(feature, test => { let solver: SeriesSolver; let solution: string; let terms: string[]; @@ -20,7 +20,7 @@ defineFeature(feature, (test) => { }; const thenIShouldGetXAsTheAnswer = (then: DefineStepFunction) => { - then(/^I should get (.*) as the answer$/, (expectedSolution) => { + then(/^I should get (.*) as the answer$/, expectedSolution => { expect(solution).toBe(expectedSolution); }); }; @@ -29,12 +29,13 @@ defineFeature(feature, (test) => { given( /^I have a series (.*) (.*) (.*) (.*) (.*) (.*) (.*)$/, (firstTerm, firstOperator, secondTerm, secondOperator, thirdTerm, thirdOperator, forthTerm) => { - expect(firstOperator).toEqual(secondOperator); - expect(firstOperator).toEqual(thirdOperator); + expect(firstOperator).toStrictEqual(secondOperator); + expect(firstOperator).toStrictEqual(thirdOperator); operator = firstOperator; terms = [firstTerm, secondTerm, thirdTerm, forthTerm]; - }); + }, + ); whenISolveTheSeries(when); @@ -42,14 +43,12 @@ defineFeature(feature, (test) => { }); test('Adding series', ({ given, when, then }) => { - given( - /^I add the following series:$/, - (table: [{ Series: string, Operator: string, Solution: string }]) => { - const row = table[0]; - terms = row.Series.split(` ${row.Operator} `); - operator = row.Operator; - solver.add(terms, operator, row.Solution); - }); + given(/^I add the following series:$/, (table: [{ Series: string; Operator: string; Solution: string }]) => { + const row = table[0]; + terms = row.Series.split(` ${row.Operator} `); + operator = row.Operator; + solver.add(terms, operator, row.Solution); + }); whenISolveTheSeries(when); diff --git a/examples/typescript/specs/step-definitions/scenario-outlines.steps.ts b/examples/typescript/specs/step-definitions/scenario-outlines.steps.ts index dd33bbb..0065a9b 100644 --- a/examples/typescript/specs/step-definitions/scenario-outlines.steps.ts +++ b/examples/typescript/specs/step-definitions/scenario-outlines.steps.ts @@ -1,27 +1,27 @@ -import { defineFeature, loadFeature } from '../../../../src/'; +import { defineFeature, loadFeature } from '../../../../src'; import { OnlineSales } from '../../src/online-sales'; const feature = loadFeature('./examples/typescript/specs/features/scenario-outlines.feature'); -defineFeature(feature, (test) => { - let onlineSales: OnlineSales; - let salesPrice: number | null; +defineFeature(feature, test => { + let onlineSales: OnlineSales; + let salesPrice: number | null; - beforeEach(() => { - onlineSales = new OnlineSales(); - }); + beforeEach(() => { + onlineSales = new OnlineSales(); + }); - test('Selling an at $', ({ given, when, then }) => { - given(/^I have a\(n\) (.*)$/, (item) => { - onlineSales.listItem(item); - }); + test('Selling an at $', ({ given, when, then }) => { + given(/^I have a\(n\) (.*)$/, item => { + onlineSales.listItem(item); + }); - when(/^I sell the (.*)$/, (item) => { - salesPrice = onlineSales.sellItem(item); - }); + when(/^I sell the (.*)$/, item => { + salesPrice = onlineSales.sellItem(item); + }); - then(/^I should get \$(\d+)$/, (expectedSalesPrice) => { - expect(salesPrice).toBe(parseInt(expectedSalesPrice, 10)); - }); + then(/^I should get \$(\d+)$/, expectedSalesPrice => { + expect(salesPrice).toBe(parseInt(expectedSalesPrice, 10)); }); + }); }); diff --git a/examples/typescript/specs/step-definitions/using-docstrings.steps.ts b/examples/typescript/specs/step-definitions/using-docstrings.steps.ts index c5bd7b0..bd23443 100644 --- a/examples/typescript/specs/step-definitions/using-docstrings.steps.ts +++ b/examples/typescript/specs/step-definitions/using-docstrings.steps.ts @@ -1,27 +1,27 @@ -import { defineFeature, loadFeature } from '../../../../src/'; +import { defineFeature, loadFeature } from '../../../../src'; import { CertificateFactory } from '../../src/certificate-factory'; const feature = loadFeature('./examples/typescript/specs/features/using-docstrings.feature'); -defineFeature(feature, (test) => { - let certificateFactory: CertificateFactory; - let certificate: string | null; +defineFeature(feature, test => { + let certificateFactory: CertificateFactory; + let certificate: string | null; - beforeEach(() => { - certificateFactory = new CertificateFactory(); - }); + beforeEach(() => { + certificateFactory = new CertificateFactory(); + }); - test('Print a certificate', ({ given, when, then }) => { - given(/^(.*) (.*) has achieved a ([0-9]*)$/, (title, lastName, score) => { - certificateFactory.setReceiver(title, lastName, score); - }); + test('Print a certificate', ({ given, when, then }) => { + given(/^(.*) (.*) has achieved a ([0-9]*)$/, (title, lastName, score) => { + certificateFactory.setReceiver(title, lastName, score); + }); - when(/^I print the certificate$/, () => { - certificate = certificateFactory.printCertificate(); - }); + when(/^I print the certificate$/, () => { + certificate = certificateFactory.printCertificate(); + }); - then(/^It prints$/, (expectedCertificate) => { - expect(certificate).toBe(expectedCertificate); - }); + then(/^It prints$/, expectedCertificate => { + expect(certificate).toBe(expectedCertificate); }); + }); }); diff --git a/examples/typescript/specs/step-definitions/using-dynamic-values.steps.ts b/examples/typescript/specs/step-definitions/using-dynamic-values.steps.ts index b31b239..413e9c0 100644 --- a/examples/typescript/specs/step-definitions/using-dynamic-values.steps.ts +++ b/examples/typescript/specs/step-definitions/using-dynamic-values.steps.ts @@ -1,27 +1,27 @@ -import { defineFeature, loadFeature } from '../../../../src/'; +import { defineFeature, loadFeature } from '../../../../src'; import { BankAccount } from '../../src/bank-account'; const feature = loadFeature('./examples/typescript/specs/features/using-dynamic-values.feature'); -defineFeature(feature, (test) => { - let myAccount: BankAccount; +defineFeature(feature, test => { + let myAccount: BankAccount; - beforeEach(() => { - myAccount = new BankAccount(); - }); + beforeEach(() => { + myAccount = new BankAccount(); + }); - test('Depositing a paycheck', ({ given, when, then, pending }) => { - given(/^my account balance is \$(\d+)$/, (balance) => { - myAccount.deposit(parseInt(balance, 10)); - }); + test('Depositing a paycheck', ({ given, when, then }) => { + given(/^my account balance is \$(\d+)$/, balance => { + myAccount.deposit(parseInt(balance, 10)); + }); - when(/^I get paid \$(\d+) for writing some awesome code$/, (paycheck) => { - myAccount.deposit(parseInt(paycheck, 10)); - }); + when(/^I get paid \$(\d+) for writing some awesome code$/, paycheck => { + myAccount.deposit(parseInt(paycheck, 10)); + }); - then(/^my account balance should be \$(\d+)$/, (expectedBalance) => { - expect(myAccount.balance).toBe(parseInt(expectedBalance, 10)); - }); + then(/^my account balance should be \$(\d+)$/, expectedBalance => { + expect(myAccount.balance).toBe(parseInt(expectedBalance, 10)); }); + }); }); diff --git a/examples/typescript/specs/step-definitions/using-gherkin-tables.steps.ts b/examples/typescript/specs/step-definitions/using-gherkin-tables.steps.ts index 8e33a45..cf11aa1 100644 --- a/examples/typescript/specs/step-definitions/using-gherkin-tables.steps.ts +++ b/examples/typescript/specs/step-definitions/using-gherkin-tables.steps.ts @@ -1,39 +1,44 @@ -import { defineFeature, loadFeature } from '../../../../src/'; +import { defineFeature, loadFeature } from '../../../../src'; import { TodoList } from '../../src/todo-list'; const feature = loadFeature('./examples/typescript/specs/features/using-gherkin-tables.feature'); -defineFeature(feature, (test) => { - let todoList: TodoList; +type TestDate = { + TaskName: string; + Priority: string; +}; - beforeEach(() => { - todoList = new TodoList(); - }); +defineFeature(feature, test => { + let todoList: TodoList; - test('Adding an item to my todo list', ({ given, when, then }) => { - given('my todo list currently looks as follows:', (table: any[]) => { - table.forEach((row: any) => { - todoList.add({ - name: row.TaskName, - priority: row.Priority, - }); - }); - }); + beforeEach(() => { + todoList = new TodoList(); + }); - when('I add the following task:', (table: any) => { - todoList.add({ - name: table[0].TaskName, - priority: table[0].Priority, - }); + test('Adding an item to my todo list', ({ given, when, then }) => { + given('my todo list currently looks as follows:', (table: TestDate[]) => { + table.forEach(row => { + todoList.add({ + name: row.TaskName, + priority: row.Priority, }); + }); + }); - then('I should see the following todo list:', (table: any[]) => { - expect(todoList.items.length).toBe(table.length); + when('I add the following task:', (table: TestDate[]) => { + todoList.add({ + name: table[0].TaskName, + priority: table[0].Priority, + }); + }); - table.forEach((row: any, index) => { - expect(todoList.items[index].name).toBe(table[index].TaskName); - expect(todoList.items[index].priority).toBe(table[index].Priority); - }); - }); + then('I should see the following todo list:', (table: TestDate[]) => { + expect(todoList.items).toHaveLength(table.length); + + table.forEach((_, index) => { + expect(todoList.items[index].name).toBe(table[index].TaskName); + expect(todoList.items[index].priority).toBe(table[index].Priority); + }); }); + }); }); diff --git a/examples/typescript/specs/step-definitions/using-latest-gherkin-keywords.steps.ts b/examples/typescript/specs/step-definitions/using-latest-gherkin-keywords.steps.ts index cb76718..f8f74dc 100644 --- a/examples/typescript/specs/step-definitions/using-latest-gherkin-keywords.steps.ts +++ b/examples/typescript/specs/step-definitions/using-latest-gherkin-keywords.steps.ts @@ -1,79 +1,79 @@ -import { loadFeature, defineFeature, DefineStepFunction } from '../../../../src/'; - -import { Calculator, CalculatorOperator } from '../../src/calculator'; - -const feature = loadFeature('./examples/typescript/specs/features/using-latest-gherkin-keywords.feature'); - -defineFeature(feature, (test) => { - let calculator: Calculator; - let output: number | undefined; - - beforeEach(() => { - calculator = new Calculator(); - }); - - const givenIHaveEnteredXAsTheFirstOperand = (given: DefineStepFunction) => { - given(/^I have entered "(\d+)" as the first operand$/, (firstOperand: string) => { - calculator.setFirstOperand(parseFloat(firstOperand)); - }); - }; - - const andIHaveEnteredXAsTheOperator = (and: DefineStepFunction) => { - and(/^I have entered "([+-/*])" as the operator$/, (operator: CalculatorOperator) => { - calculator.setCalculatorOperator(operator); - }); - }; - - const andIHaveEnteredXAsTheSecondOperand = (and: DefineStepFunction) => { - and(/^I have entered "(\d+)" as the second operand$/, (secondOperand: string) => { - calculator.setSecondOperand(parseFloat(secondOperand)); - }); - }; - - const whenIPressTheEnterKey = (when: DefineStepFunction) => { - when('I press the equals key', () => { - output = calculator.computeOutput(); - }); - }; - - const thenTheOutputOfXShouldBeDisplayed = (then: DefineStepFunction) => { - then(/^the output of "(\d+)" should be displayed$/, (expectedOutput: string) => { - if (!expectedOutput) { - expect(output).toBeFalsy(); - } else { - expect(output).toBe(parseFloat(expectedOutput)); - } - }); - }; - - test('Subtracting two numbers', ({ given, and, when, then }) => { - givenIHaveEnteredXAsTheFirstOperand(given); - andIHaveEnteredXAsTheOperator(and); - andIHaveEnteredXAsTheSecondOperand(and); - whenIPressTheEnterKey(when); - thenTheOutputOfXShouldBeDisplayed(then); - }); - - test('Attempting to subtract without entering a second number', ({ given, and, when, then }) => { - givenIHaveEnteredXAsTheFirstOperand(given); - andIHaveEnteredXAsTheOperator(and); - - and('I have not entered a second operand', () => { - // Nothing to do here - }); - - whenIPressTheEnterKey(when); - - then('no output should be displayed', () => { - expect(output).toBeFalsy(); - }); - }); - - test('Division operations', ({ given, and, when, then }) => { - givenIHaveEnteredXAsTheFirstOperand(given); - andIHaveEnteredXAsTheOperator(and); - andIHaveEnteredXAsTheSecondOperand(and); - whenIPressTheEnterKey(when); - thenTheOutputOfXShouldBeDisplayed(then); - }); -}); +import { loadFeature, defineFeature, DefineStepFunction } from '../../../../src'; + +import { Calculator, CalculatorOperator } from '../../src/calculator'; + +const feature = loadFeature('./examples/typescript/specs/features/using-latest-gherkin-keywords.feature'); + +defineFeature(feature, test => { + let calculator: Calculator; + let output: number | null; + + beforeEach(() => { + calculator = new Calculator(); + }); + + const givenIHaveEnteredXAsTheFirstOperand = (given: DefineStepFunction) => { + given(/^I have entered "(\d+)" as the first operand$/, (firstOperand: string) => { + calculator.setFirstOperand(parseFloat(firstOperand)); + }); + }; + + const andIHaveEnteredXAsTheOperator = (and: DefineStepFunction) => { + and(/^I have entered "([+-/*])" as the operator$/, (operator: CalculatorOperator) => { + calculator.setCalculatorOperator(operator); + }); + }; + + const andIHaveEnteredXAsTheSecondOperand = (and: DefineStepFunction) => { + and(/^I have entered "(\d+)" as the second operand$/, (secondOperand: string) => { + calculator.setSecondOperand(parseFloat(secondOperand)); + }); + }; + + const whenIPressTheEnterKey = (when: DefineStepFunction) => { + when('I press the equals key', () => { + output = calculator.computeOutput(); + }); + }; + + const thenTheOutputOfXShouldBeDisplayed = (then: DefineStepFunction) => { + then(/^the output of "(\d+)" should be displayed$/, (expectedOutput: string) => { + if (!expectedOutput) { + expect(output).toBeFalsy(); + } else { + expect(output).toBe(parseFloat(expectedOutput)); + } + }); + }; + + test('Subtracting two numbers', ({ given, and, when, then }) => { + givenIHaveEnteredXAsTheFirstOperand(given); + andIHaveEnteredXAsTheOperator(and); + andIHaveEnteredXAsTheSecondOperand(and); + whenIPressTheEnterKey(when); + thenTheOutputOfXShouldBeDisplayed(then); + }); + + test('Attempting to subtract without entering a second number', ({ given, and, when, then }) => { + givenIHaveEnteredXAsTheFirstOperand(given); + andIHaveEnteredXAsTheOperator(and); + + and('I have not entered a second operand', () => { + // Nothing to do here + }); + + whenIPressTheEnterKey(when); + + then('no output should be displayed', () => { + expect(output).toBeFalsy(); + }); + }); + + test('Division operations', ({ given, and, when, then }) => { + givenIHaveEnteredXAsTheFirstOperand(given); + andIHaveEnteredXAsTheOperator(and); + andIHaveEnteredXAsTheSecondOperand(and); + whenIPressTheEnterKey(when); + thenTheOutputOfXShouldBeDisplayed(then); + }); +}); diff --git a/examples/typescript/src/arcade-machine.ts b/examples/typescript/src/arcade-machine.ts index 579609b..594700d 100644 --- a/examples/typescript/src/arcade-machine.ts +++ b/examples/typescript/src/arcade-machine.ts @@ -1,39 +1,35 @@ -export type IssuingNation = - 'USA' | - 'Canada' | - 'Unknown'; - -export type CoinStatus = - 'CoinAccepted' | - 'CoinReturned'; - -export type CoinType = { - value: number; - issuingNation: IssuingNation; -}; - -export const COIN_TYPES: { [coinName: string]: CoinType } = { - USQuarter: { value: 0.25, issuingNation: 'USA' }, - CanadianQuarter: { value: 0.25, issuingNation: 'Canada' }, - Unknown: { value: 0, issuingNation: 'Unknown' }, -}; - -export class ArcadeMachine { - public acceptedCoinType: CoinType | null = null; - public balance: number = 0; - public requireCoins = true; - - public insertCoin(coinType: CoinType): CoinStatus { - if (!this.requireCoins) { - return 'CoinReturned'; - } - - if (coinType === this.acceptedCoinType) { - this.balance += coinType.value; - - return 'CoinAccepted'; - } else { - return 'CoinReturned'; - } - } -} +export type IssuingNation = 'USA' | 'Canada' | 'Unknown'; + +export type CoinStatus = 'CoinAccepted' | 'CoinReturned'; + +export type CoinType = { + value: number; + issuingNation: IssuingNation; +}; + +export const COIN_TYPES: { [coinName: string]: CoinType } = { + USQuarter: { value: 0.25, issuingNation: 'USA' }, + CanadianQuarter: { value: 0.25, issuingNation: 'Canada' }, + Unknown: { value: 0, issuingNation: 'Unknown' }, +}; + +export class ArcadeMachine { + public acceptedCoinType: CoinType | null = null; + + public balance: number = 0; + + public requireCoins = true; + + public insertCoin(coinType: CoinType): CoinStatus { + if (!this.requireCoins) { + return 'CoinReturned'; + } + + if (coinType === this.acceptedCoinType) { + this.balance += coinType.value; + + return 'CoinAccepted'; + } + return 'CoinReturned'; + } +} diff --git a/examples/typescript/src/bank-account.ts b/examples/typescript/src/bank-account.ts index 5932052..6ae58a4 100644 --- a/examples/typescript/src/bank-account.ts +++ b/examples/typescript/src/bank-account.ts @@ -1,11 +1,11 @@ export class BankAccount { - public balance: number = 0; + public balance: number = 0; - public deposit(amount: number) { - this.balance += amount; - } + public deposit(amount: number) { + this.balance += amount; + } - public withdraw(amount: number) { - this.balance -= amount; - } + public withdraw(amount: number) { + this.balance -= amount; + } } diff --git a/examples/typescript/src/calculator.ts b/examples/typescript/src/calculator.ts index 005c1cf..c39649d 100644 --- a/examples/typescript/src/calculator.ts +++ b/examples/typescript/src/calculator.ts @@ -1,40 +1,40 @@ -export type CalculatorOperator = - '+' | - '-' | - '*' | - '/'; - -export class Calculator { - private firstOperand: number | null = null; - private secondOperand: number | null = null; - private operator: CalculatorOperator | null = null; - - public setFirstOperand(operand: number) { - this.firstOperand = operand; - } - - public setSecondOperand(operand: number) { - this.secondOperand = operand; - } - - public setCalculatorOperator(operator: CalculatorOperator) { - this.operator = operator; - } - - public computeOutput() { - if (!this.firstOperand || !this.secondOperand || !this.operator) { - return; - } - - switch (this.operator) { - case '+': - return this.firstOperand + this.secondOperand; - case '-': - return this.firstOperand - this.secondOperand; - case '*': - return this.firstOperand * this.secondOperand; - case '/': - return this.firstOperand / this.secondOperand; - } - } -} +export type CalculatorOperator = '+' | '-' | '*' | '/'; + +export class Calculator { + private firstOperand: number | null = null; + + private secondOperand: number | null = null; + + private operator: CalculatorOperator | null = null; + + public setFirstOperand(operand: number) { + this.firstOperand = operand; + } + + public setSecondOperand(operand: number) { + this.secondOperand = operand; + } + + public setCalculatorOperator(operator: CalculatorOperator) { + this.operator = operator; + } + + public computeOutput() { + if (!this.firstOperand || !this.secondOperand || !this.operator) { + return null; + } + + switch (this.operator) { + case '+': + return this.firstOperand + this.secondOperand; + case '-': + return this.firstOperand - this.secondOperand; + case '*': + return this.firstOperand * this.secondOperand; + case '/': + return this.firstOperand / this.secondOperand; + default: + return null; + } + } +} diff --git a/examples/typescript/src/certificate-factory.ts b/examples/typescript/src/certificate-factory.ts index 1be6a93..6f2ae77 100644 --- a/examples/typescript/src/certificate-factory.ts +++ b/examples/typescript/src/certificate-factory.ts @@ -1,31 +1,34 @@ export class CertificateFactory { - private title = ''; - private lastName = ''; - private score = 0; - private rank = 'Novice'; + private title = ''; - public setReceiver(title: string, name: string, score: string) { - this.title = title; - this.lastName = name; - this.score = Number.parseInt(score, 10); - if (this.score > 2700) { - this.rank = 'Super Grandmaster'; - } else if (this.score > 2500) { - this.rank = 'Grandmaster'; - } else if (this.score > 2000) { - this.rank = 'Expert'; - } - } + private lastName = ''; + + private score = 0; - public printCertificate() { - const pieces = [ - `Certificate of Mastery`, - `The title of ${this.rank} is hereby awarded to:`, - `${this.title} ${this.lastName}`, - `For achieving a score of ${this.score}, ${this.title} ${this.lastName}`, - `may henceforth use the title ${this.rank}.`, - ]; + private rank = 'Novice'; - return pieces.join('\n'); + public setReceiver(title: string, name: string, score: string) { + this.title = title; + this.lastName = name; + this.score = Number.parseInt(score, 10); + if (this.score > 2700) { + this.rank = 'Super Grandmaster'; + } else if (this.score > 2500) { + this.rank = 'Grandmaster'; + } else if (this.score > 2000) { + this.rank = 'Expert'; } + } + + public printCertificate() { + const pieces = [ + `Certificate of Mastery`, + `The title of ${this.rank} is hereby awarded to:`, + `${this.title} ${this.lastName}`, + `For achieving a score of ${this.score}, ${this.title} ${this.lastName}`, + `may henceforth use the title ${this.rank}.`, + ]; + + return pieces.join('\n'); + } } diff --git a/examples/typescript/src/online-sales.ts b/examples/typescript/src/online-sales.ts index 224affc..2be65fe 100644 --- a/examples/typescript/src/online-sales.ts +++ b/examples/typescript/src/online-sales.ts @@ -1,25 +1,24 @@ const itemPrices: { [itemName: string]: number } = { - 'Autographed Neil deGrasse Tyson book': 100, - 'Rick Astley t-shirt': 22, - 'An idea to replace EVERYTHING with blockchains': 0, + 'Autographed Neil deGrasse Tyson book': 100, + 'Rick Astley t-shirt': 22, + 'An idea to replace EVERYTHING with blockchains': 0, }; export class OnlineSales { - private listedItems: string[] = []; + private listedItems: string[] = []; - public listItem(name: string) { - this.listedItems.push(name); - } + public listItem(name: string) { + this.listedItems.push(name); + } - public sellItem(name: string) { - const itemIndex = this.listedItems.indexOf(name); + public sellItem(name: string) { + const itemIndex = this.listedItems.indexOf(name); - if (itemIndex !== -1) { - this.listedItems.splice(itemIndex, 1); + if (itemIndex !== -1) { + this.listedItems.splice(itemIndex, 1); - return itemPrices[name]; - } else { - return null; - } + return itemPrices[name]; } + return null; + } } diff --git a/examples/typescript/src/password-validator.ts b/examples/typescript/src/password-validator.ts index 9ab25f1..f3596ff 100644 --- a/examples/typescript/src/password-validator.ts +++ b/examples/typescript/src/password-validator.ts @@ -1,11 +1,11 @@ -export class PasswordValidator { - private password: string | null = null; - - public setPassword(password: string) { - this.password = password; - } - - public validatePassword(claimedPassword: string) { - return this.password === claimedPassword; - } -} +export class PasswordValidator { + private password: string | null = null; + + public setPassword(password: string) { + this.password = password; + } + + public validatePassword(claimedPassword: string) { + return this.password === claimedPassword; + } +} diff --git a/examples/typescript/src/todo-list.ts b/examples/typescript/src/todo-list.ts index 2908260..edc2ebb 100644 --- a/examples/typescript/src/todo-list.ts +++ b/examples/typescript/src/todo-list.ts @@ -1,21 +1,21 @@ export interface ITodo { - name: string; - priority: string; + name: string; + priority: string; } export class TodoList { - public items: ITodo[] = []; + public items: ITodo[] = []; - public add(todo: ITodo) { - if (todo.name.toLocaleLowerCase().indexOf('youtube')) { - this.items = []; - this.items.push(todo); - this.items.push({ - name: 'Sign up for unemployment', - priority: 'high', - }); - } else { - this.items.push(todo); - } + public add(todo: ITodo) { + if (todo.name.toLocaleLowerCase().indexOf('youtube')) { + this.items = []; + this.items.push(todo); + this.items.push({ + name: 'Sign up for unemployment', + priority: 'high', + }); + } else { + this.items.push(todo); } + } } diff --git a/examples/typescript/src/vending-machine.ts b/examples/typescript/src/vending-machine.ts index 3cf5f10..f682a5c 100644 --- a/examples/typescript/src/vending-machine.ts +++ b/examples/typescript/src/vending-machine.ts @@ -1,23 +1,24 @@ -const ITEM_COST = 0.50; - -export class VendingMachine { - public balance: number = 0; - public items: { [itemName: string]: number } = {}; - - public stockItem(itemName: string, count: number) { - this.items[itemName] = this.items[itemName] || 0; - this.items[itemName] += count; - } - - public insertMoney(amount: number) { - this.balance += amount; - } - - public dispenseItem(itemName: string) { - if (this.balance >= ITEM_COST && this.items[itemName] > 0) { - this.balance -= ITEM_COST; - } - - this.items[itemName]--; - } -} +const ITEM_COST = 0.5; + +export class VendingMachine { + public balance: number = 0; + + public items: { [itemName: string]: number } = {}; + + public stockItem(itemName: string, count: number) { + this.items[itemName] = this.items[itemName] || 0; + this.items[itemName] += count; + } + + public insertMoney(amount: number) { + this.balance += amount; + } + + public dispenseItem(itemName: string) { + if (this.balance >= ITEM_COST && this.items[itemName] > 0) { + this.balance -= ITEM_COST; + } + + this.items[itemName] -= 1; + } +} diff --git a/specs/step-definitions/step-execution.steps.ts b/specs/step-definitions/step-execution.steps.ts index ce9e900..9344ee4 100644 --- a/specs/step-definitions/step-execution.steps.ts +++ b/specs/step-definitions/step-execution.steps.ts @@ -1,116 +1,119 @@ import { loadFeature, defineFeature, DefineStepFunction } from '../../src'; -import { asyncStep, failingAsyncStep, failingSynchronousStep, featureToExecute, synchronousSteps } from '../test-data/step-execution'; +import { + asyncStep, + failingAsyncStep, + failingSynchronousStep, + featureToExecute, + synchronousSteps, +} from '../test-data/step-execution'; import { MockTestRunner } from '../utils/mock-test-runner/mock-test-runner'; import { MockStepDefinitions, wireUpMockFeature } from '../utils/wire-up-mock-scenario'; const feature = loadFeature('./specs/features/steps/step-execution.feature'); -defineFeature(feature, (test) => { - let mockTestRunner: MockTestRunner; - let errorMessage = ''; - let stepDefinitions: MockStepDefinitions | null = null; - let featureFile: string | null = null; - let logs: string[]; - - beforeEach(() => { - mockTestRunner = new MockTestRunner(); - errorMessage = ''; - logs = []; +defineFeature(feature, test => { + let mockTestRunner: MockTestRunner; + let errorMessage = ''; + let stepDefinitions: MockStepDefinitions | null = null; + let featureFile: string | null = null; + let logs: string[]; + + beforeEach(() => { + mockTestRunner = new MockTestRunner(); + errorMessage = ''; + logs = []; + }); + + const whenIExecuteThatScenarioInJestCucumber = (when: DefineStepFunction) => { + when('I execute that scenario in Jest Cucumber', async () => { + try { + wireUpMockFeature(mockTestRunner, featureFile as string, stepDefinitions); + + await mockTestRunner.execute(); + } catch (err) { + errorMessage = err.message; + } }); + }; - const whenIExecuteThatScenarioInJestCucumber = (when: DefineStepFunction) => { - when('I execute that scenario in Jest Cucumber', async () => { - try { - wireUpMockFeature(mockTestRunner, - featureFile as string, - stepDefinitions, - ); - - await mockTestRunner.execute(); - } catch (err) { - errorMessage = err.message; - } - }); - }; - - const andIShouldSeeWhichStepFailed = (and: DefineStepFunction) => { - and('I should see which step failed', () => { - expect(errorMessage.toLowerCase()).toContain('i run the when step'); - }); - }; - - const thenIShouldSeeTheErrorThatOccurred = (then: DefineStepFunction) => { - then('I should see the error that occurred', () => { - expect(errorMessage).toBeTruthy(); - expect(errorMessage).toContain('when step failure'); - }); - }; - - test('Scenario with multiple step definitions', ({ given, when, then }) => { - given('a scenario with multiple step definitions', () => { - featureFile = featureToExecute; - stepDefinitions = synchronousSteps(logs); - }); - - whenIExecuteThatScenarioInJestCucumber(when); - - then('all steps should be executed in order', () => { - expect(errorMessage).toBeFalsy(); - expect(logs.length).toBe(3); - expect(logs[0]).toBe('given step'); - expect(logs[1]).toBe('when step'); - expect(logs[2]).toBe('then step'); - }); + const andIShouldSeeWhichStepFailed = (and: DefineStepFunction) => { + and('I should see which step failed', () => { + expect(errorMessage.toLowerCase()).toContain('i run the when step'); }); + }; - test('Scenario with a failing synchronous step', ({ given, when, then, and }) => { - given('a scenario with a failing synchronous step', () => { - featureFile = featureToExecute; - stepDefinitions = failingSynchronousStep(logs); - }); - - whenIExecuteThatScenarioInJestCucumber(when); - thenIShouldSeeTheErrorThatOccurred(then); - andIShouldSeeWhichStepFailed(and); - - and('no more steps should execute', () => { - expect(logs.length).toBe(2); - expect(logs[0]).toBe('given step'); - expect(logs[1]).toBe('when step'); - }); + const thenIShouldSeeTheErrorThatOccurred = (then: DefineStepFunction) => { + then('I should see the error that occurred', () => { + expect(errorMessage).toBeTruthy(); + expect(errorMessage).toContain('when step failure'); }); + }; - test('Scenario with an async step', ({ given, when, then }) => { - given('a scenario with an async step', () => { - featureFile = featureToExecute; - stepDefinitions = asyncStep(logs); - }); - - whenIExecuteThatScenarioInJestCucumber(when); - - then('the next step should not execute until the promise resolves', () => { - expect(logs.length).toBe(4); - expect(logs[0]).toBe('given step'); - expect(logs[1]).toBe('when step started'); - expect(logs[2]).toBe('when step completed'); - expect(logs[3]).toBe('then step'); - }); + test('Scenario with multiple step definitions', ({ given, when, then }) => { + given('a scenario with multiple step definitions', () => { + featureFile = featureToExecute; + stepDefinitions = synchronousSteps(logs); }); - test('Scenario with a failing async step', ({ given, when, then, and }) => { - given('a scenario with a failing async step', () => { - featureFile = featureToExecute; - stepDefinitions = failingAsyncStep(logs); - }); - - whenIExecuteThatScenarioInJestCucumber(when); - thenIShouldSeeTheErrorThatOccurred(then); - andIShouldSeeWhichStepFailed(and); - - and('no more steps should execute', () => { - expect(logs.length).toBe(2); - expect(logs[0]).toBe('given step'); - expect(logs[1]).toBe('when step started'); - }); + whenIExecuteThatScenarioInJestCucumber(when); + + then('all steps should be executed in order', () => { + expect(errorMessage).toBeFalsy(); + expect(logs).toHaveLength(3); + expect(logs[0]).toBe('given step'); + expect(logs[1]).toBe('when step'); + expect(logs[2]).toBe('then step'); + }); + }); + + test('Scenario with a failing synchronous step', ({ given, when, then, and }) => { + given('a scenario with a failing synchronous step', () => { + featureFile = featureToExecute; + stepDefinitions = failingSynchronousStep(logs); + }); + + whenIExecuteThatScenarioInJestCucumber(when); + thenIShouldSeeTheErrorThatOccurred(then); + andIShouldSeeWhichStepFailed(and); + + and('no more steps should execute', () => { + expect(logs).toHaveLength(2); + expect(logs[0]).toBe('given step'); + expect(logs[1]).toBe('when step'); + }); + }); + + test('Scenario with an async step', ({ given, when, then }) => { + given('a scenario with an async step', () => { + featureFile = featureToExecute; + stepDefinitions = asyncStep(logs); + }); + + whenIExecuteThatScenarioInJestCucumber(when); + + then('the next step should not execute until the promise resolves', () => { + expect(logs).toHaveLength(4); + expect(logs[0]).toBe('given step'); + expect(logs[1]).toBe('when step started'); + expect(logs[2]).toBe('when step completed'); + expect(logs[3]).toBe('then step'); + }); + }); + + test('Scenario with a failing async step', ({ given, when, then, and }) => { + given('a scenario with a failing async step', () => { + featureFile = featureToExecute; + stepDefinitions = failingAsyncStep(logs); + }); + + whenIExecuteThatScenarioInJestCucumber(when); + thenIShouldSeeTheErrorThatOccurred(then); + andIShouldSeeWhichStepFailed(and); + + and('no more steps should execute', () => { + expect(logs).toHaveLength(2); + expect(logs[0]).toBe('given step'); + expect(logs[1]).toBe('when step started'); }); + }); }); diff --git a/specs/step-definitions/step-matching.steps.ts b/specs/step-definitions/step-matching.steps.ts index acbcde3..7fd4a91 100644 --- a/specs/step-definitions/step-matching.steps.ts +++ b/specs/step-definitions/step-matching.steps.ts @@ -5,67 +5,64 @@ import { MockStepDefinitions, wireUpMockFeature } from '../utils/wire-up-mock-sc const feature = loadFeature('./specs/features/steps/step-matching.feature'); -defineFeature(feature, (test) => { - let mockTestRunner: MockTestRunner; - let errorMessage = ''; - let stepDefinitions: MockStepDefinitions | null = null; - let featureFile: string | null = null; - let stepArguments: any[]; +defineFeature(feature, test => { + let mockTestRunner: MockTestRunner; + let errorMessage = ''; + let stepDefinitions: MockStepDefinitions | null = null; + let featureFile: string | null = null; + let stepArguments: string[]; - beforeEach(() => { - mockTestRunner = new MockTestRunner(); - errorMessage = ''; - stepArguments = []; - }); + beforeEach(() => { + mockTestRunner = new MockTestRunner(); + errorMessage = ''; + stepArguments = []; + }); - const whenIRunMyJestCucumberTests = (when: DefineStepFunction) => { - when('I run my Jest Cucumber tests', async () => { - try { - wireUpMockFeature(mockTestRunner, - featureFile as string, - stepDefinitions, - ); + const whenIRunMyJestCucumberTests = (when: DefineStepFunction) => { + when('I run my Jest Cucumber tests', async () => { + try { + wireUpMockFeature(mockTestRunner, featureFile as string, stepDefinitions); - await mockTestRunner.execute(); - } catch (err) { - errorMessage = err.message; - } - }); - }; + await mockTestRunner.execute(); + } catch (err) { + errorMessage = err.message; + } + }); + }; - const thenTheStepShouldMatchCorrectly = (then: DefineStepFunction) => { - then('the step should match correctly', () => { - expect(errorMessage).toBeFalsy(); - }); - }; + const thenTheStepShouldMatchCorrectly = (then: DefineStepFunction) => { + then('the step should match correctly', () => { + expect(errorMessage).toBeFalsy(); + }); + }; - test('Step definition with plain string', ({ given, when, then, and }) => { - given('a step matched with a plain string in a step definition', () => { - featureFile = featureWithStepsToMatch; - stepDefinitions = stringStepMatcher(stepArguments); - }); + test('Step definition with plain string', ({ given, when, then, and }) => { + given('a step matched with a plain string in a step definition', () => { + featureFile = featureWithStepsToMatch; + stepDefinitions = stringStepMatcher(stepArguments); + }); - whenIRunMyJestCucumberTests(when); - thenTheStepShouldMatchCorrectly(then); + whenIRunMyJestCucumberTests(when); + thenTheStepShouldMatchCorrectly(then); - and('no step arguments should be passed to the step definition', () => { - expect(stepArguments.length).toBe(0); - }); + and('no step arguments should be passed to the step definition', () => { + expect(stepArguments).toHaveLength(0); }); + }); - test('Regex step definition with 2 capture groups', ({ given, when, then, and }) => { - given('a step matched with a regex that has 2 capture groups', () => { - featureFile = featureWithStepsToMatch; - stepDefinitions = regexStepMatcher(stepArguments); - }); + test('Regex step definition with 2 capture groups', ({ given, when, then, and }) => { + given('a step matched with a regex that has 2 capture groups', () => { + featureFile = featureWithStepsToMatch; + stepDefinitions = regexStepMatcher(stepArguments); + }); - whenIRunMyJestCucumberTests(when); - thenTheStepShouldMatchCorrectly(then); + whenIRunMyJestCucumberTests(when); + thenTheStepShouldMatchCorrectly(then); - and('2 step arguments should be passed to the step definition', () => { - expect(stepArguments.length).toBe(2); - expect(stepArguments[0]).toBe('1'); - expect(stepArguments[1]).toBe('2'); - }); + and('2 step arguments should be passed to the step definition', () => { + expect(stepArguments).toHaveLength(2); + expect(stepArguments[0]).toBe('1'); + expect(stepArguments[1]).toBe('2'); }); + }); }); diff --git a/specs/step-definitions/table-step-arguments.steps.ts b/specs/step-definitions/table-step-arguments.steps.ts index 239b10f..8dcc4c9 100644 --- a/specs/step-definitions/table-step-arguments.steps.ts +++ b/specs/step-definitions/table-step-arguments.steps.ts @@ -1,78 +1,79 @@ import { loadFeature, defineFeature, DefineStepFunction } from '../../src'; -import { featureWithTableArgument, tableStepWithoutStepArgs, tableStepWithStepArgs } from '../test-data/step-table-arguments'; +import { + featureWithTableArgument, + tableStepWithoutStepArgs, + tableStepWithStepArgs, +} from '../test-data/step-table-arguments'; import { MockTestRunner } from '../utils/mock-test-runner/mock-test-runner'; import { MockStepDefinitions, wireUpMockFeature } from '../utils/wire-up-mock-scenario'; const feature = loadFeature('./specs/features/steps/table-step-arguments.feature'); -defineFeature(feature, (test) => { - let mockTestRunner: MockTestRunner; - let errorMessage = ''; - let stepDefinitions: MockStepDefinitions | null = null; - let featureFile: string | null = null; - let stepArguments: any[]; +defineFeature(feature, test => { + let mockTestRunner: MockTestRunner; + let errorMessage = ''; + let stepDefinitions: MockStepDefinitions | null = null; + let featureFile: string | null = null; + let stepArguments: unknown[]; - beforeEach(() => { - mockTestRunner = new MockTestRunner(); - errorMessage = ''; - stepArguments = []; - }); + beforeEach(() => { + mockTestRunner = new MockTestRunner(); + errorMessage = ''; + stepArguments = []; + }); - const whenIRunMyJestCucumberTests = (when: DefineStepFunction) => { - when('I run my Jest Cucumber tests', async () => { - try { - wireUpMockFeature(mockTestRunner, - featureFile as string, - stepDefinitions, - ); + const whenIRunMyJestCucumberTests = (when: DefineStepFunction) => { + when('I run my Jest Cucumber tests', async () => { + try { + wireUpMockFeature(mockTestRunner, featureFile as string, stepDefinitions); - await mockTestRunner.execute(); - } catch (err) { - errorMessage = err.message; - } - }); - }; + await mockTestRunner.execute(); + } catch (err) { + errorMessage = err.message; + } + }); + }; - const checkTable = (table: any) => { - expect(table.length).toBe(2); - expect(table[0]).toEqual({ foo: 'baz', bar: 'boo' }); - expect(table[1]).toEqual({ foo: 'ban', bar: 'bat' }); - }; + const checkTable = (table: object[]) => { + expect(table).toHaveLength(2); + expect(table[0]).toStrictEqual({ foo: 'baz', bar: 'boo' }); + expect(table[1]).toStrictEqual({ foo: 'ban', bar: 'bat' }); + }; - test('Step definition with a table argument', ({ given, when, then }) => { - given('a step with a table argument', () => { - featureFile = featureWithTableArgument; - stepDefinitions = tableStepWithoutStepArgs(stepArguments); - }); + test('Step definition with a table argument', ({ given, when, then }) => { + given('a step with a table argument', () => { + featureFile = featureWithTableArgument; + stepDefinitions = tableStepWithoutStepArgs(stepArguments); + }); - whenIRunMyJestCucumberTests(when); + whenIRunMyJestCucumberTests(when); - then('my step definitions should get an argument with array of table row objects', () => { - expect(errorMessage).toBeFalsy(); - expect(stepArguments.length).toBe(1); - const table = stepArguments[0]; - checkTable(table); - }); + then('my step definitions should get an argument with array of table row objects', () => { + expect(errorMessage).toBeFalsy(); + expect(stepArguments).toHaveLength(1); + const table = stepArguments[0] as object[]; + checkTable(table); }); + }); - test('Step definition with regex capture groups and a table argument', ({ given, when, then, and }) => { - given('a step with a table argument \/ 2 regex capture groups', () => { - featureFile = featureWithTableArgument; - stepDefinitions = tableStepWithStepArgs(stepArguments); - }); + test('Step definition with regex capture groups and a table argument', ({ given, when, then, and }) => { + given('a step with a table argument / 2 regex capture groups', () => { + featureFile = featureWithTableArgument; + stepDefinitions = tableStepWithStepArgs(stepArguments); + }); - whenIRunMyJestCucumberTests(when); + whenIRunMyJestCucumberTests(when); - then('the first 2 arguments should be the regex capture groups', () => { - expect(errorMessage).toBeFalsy(); - expect(stepArguments.length).toBe(3); - expect(stepArguments[0]).toBe('1'); - expect(stepArguments[1]).toBe('2'); - }); + then('the first 2 arguments should be the regex capture groups', () => { + expect(errorMessage).toBeFalsy(); + expect(stepArguments).toHaveLength(3); + expect(stepArguments[0]).toBe('1'); + expect(stepArguments[1]).toBe('2'); + }); - and('the third argument should be the array of table row objects', () => { - const table = stepArguments[2]; - checkTable(table); - }); + and('the third argument should be the array of table row objects', () => { + const table = stepArguments[2] as object[]; + checkTable(table); }); + }); }); diff --git a/specs/step-definitions/validation-and-code-generation.steps.ts b/specs/step-definitions/validation-and-code-generation.steps.ts index 5414e22..faa79d6 100644 --- a/specs/step-definitions/validation-and-code-generation.steps.ts +++ b/specs/step-definitions/validation-and-code-generation.steps.ts @@ -2,264 +2,267 @@ import { loadFeature, defineFeature, DefineStepFunction } from '../../src'; import { MockTestRunner } from '../utils/mock-test-runner/mock-test-runner'; import { MockStepDefinitions, wireUpMockFeature } from '../utils/wire-up-mock-scenario'; import { - emptyStepDefinitions, - featureWithMultipleScenarios, - featureWithSingleScenario, - featureWithSteplessScenario, - steplessStepDefinitions, - stepsForfeatureWithMultipleScenarios, - stepsWithMismatchedSecondStep, - stepsWithMissingStep, - stepsWithScenariosOutOfOrder, - stepsWithStepsOutOfOrder, + emptyStepDefinitions, + featureWithMultipleScenarios, + featureWithSingleScenario, + featureWithSteplessScenario, + steplessStepDefinitions, + stepsForfeatureWithMultipleScenarios, + stepsWithMismatchedSecondStep, + stepsWithMissingStep, + stepsWithScenariosOutOfOrder, + stepsWithStepsOutOfOrder, } from '../test-data/validation-and-code-generation'; import { defaultConfiguration, defaultErrorSettings, ErrorOptions, Options } from '../../src/configuration'; const feature = loadFeature('./specs/features/validation-and-code-generation.feature'); -defineFeature(feature, (test) => { - let mockTestRunner: MockTestRunner; - let errorMessage = ''; - let options: Options; - let stepDefinitions: MockStepDefinitions | null = null; - let featureFile: string | null = null; - - beforeEach(() => { - mockTestRunner = new MockTestRunner(); - errorMessage = ''; - options = { ...defaultConfiguration }; - options.errors = { ...defaultErrorSettings }; +defineFeature(feature, test => { + let mockTestRunner: MockTestRunner; + let errorMessage = ''; + let options: Options; + let stepDefinitions: MockStepDefinitions | null = null; + let featureFile: string | null = null; + + beforeEach(() => { + mockTestRunner = new MockTestRunner(); + errorMessage = ''; + options = { ...defaultConfiguration }; + options.errors = { ...defaultErrorSettings }; + }); + + const givenScenariosMustMatchFeatureFileIsEnabled = (given: DefineStepFunction) => { + given(/`scenariosMustMatchFeatureFile` is (enabled|disabled)/, enabledOrDisabled => { + (options.errors as ErrorOptions).scenariosMustMatchFeatureFile = enabledOrDisabled === 'enabled'; }); + }; - const givenScenariosMustMatchFeatureFileIsEnabled = (given: DefineStepFunction) => { - given(/`scenariosMustMatchFeatureFile` is (enabled|disabled)/, (enabledOrDisabled) => { - (options.errors as ErrorOptions).scenariosMustMatchFeatureFile = - enabledOrDisabled === 'enabled'; - }); - }; - - const givenScenariosMustMatchFeatureFileIsDisabled = givenScenariosMustMatchFeatureFileIsEnabled; - - const givenStepsMustMatchFeatureFileIsEnabled = (given: DefineStepFunction) => { - given(/`stepsMustMatchFeatureFile` is (enabled|disabled)/, (enabledOrDisabled) => { - (options.errors as ErrorOptions).stepsMustMatchFeatureFile = - enabledOrDisabled === 'enabled'; - }); - }; - - const givenAllowScenariosNotInFeatureFileIsEnabled = (given: DefineStepFunction) => { - given(/`allowScenariosNotInFeatureFile` is (enabled|disabled)/, (enabledOrDisabled) => { - (options.errors as ErrorOptions).allowScenariosNotInFeatureFile = - enabledOrDisabled === 'enabled'; - }); - }; - - const givenAllowScenariosNotInFeatureFileIsDisabled = givenAllowScenariosNotInFeatureFileIsEnabled; - - const givenStepsMustMatchFeatureFileIsDisabled = givenStepsMustMatchFeatureFileIsEnabled; - - const whenIRunMyJestCucumberTests = (when: DefineStepFunction) => { - when('I run my Jest Cucumber tests', () => { - try { - wireUpMockFeature(mockTestRunner, - featureFile as string, - stepDefinitions, - options, - ); - } catch (err) { - errorMessage = err.message; - } - }); - }; - - const thenIShouldSeeAValidationErrorAndGeneratedCode = (then: DefineStepFunction) => { - then(/I should (see|not see) a validation error \/ generated code/, (seeOrNotSee) => { - if (seeOrNotSee === 'see') { - expect(errorMessage).toBeTruthy(); - expect(errorMessage).toMatchSnapshot(); - } else { - expect(errorMessage).toBeFalsy(); - } - }); - }; - - const thenIShouldNotSeeAValidationErrorAndGeneratedCode = thenIShouldSeeAValidationErrorAndGeneratedCode; - - const thenIShouldSeeAValidationError = (then: DefineStepFunction) => { - then(/I should (see|not see) a validation error/, (seeOrNotSee) => { - if (seeOrNotSee === 'see') { - expect(errorMessage).toBeTruthy(); - expect(errorMessage).toMatchSnapshot(); - } else { - expect(errorMessage).toBeFalsy(); - } - }); - }; - - const thenIShouldNotSeeAValidationError = thenIShouldSeeAValidationError; - - const andAScenarioInAFeatureFileHasNoStepDefinitions = (and: DefineStepFunction) => { - and('a scenario in a feature file has no step definitions', () => { - featureFile = featureWithSingleScenario; - stepDefinitions = emptyStepDefinitions; - }); - }; - - const andTheStepOrderDiffersBetweenTheFeatureAndStepDefinitions = (and: DefineStepFunction) => { - and('the step order differs between the feature / step definitions', () => { - featureFile = featureWithSingleScenario; - stepDefinitions = stepsWithStepsOutOfOrder; - }); - }; - - const andTheStepCountDiffersBetweenTheFeatureAndStepDefinitions = (and: DefineStepFunction) => { - and('the step count differs between the feature / step definitions', () => { - featureFile = featureWithSingleScenario; - stepDefinitions = stepsWithMissingStep; - }); - }; - - const andIHaveAScenarioWhereTheStepMatcherForTheSecondStepDoesntMatchTheStep = (and: DefineStepFunction) => { - and('I have a scenario where the step matcher for the second step doesn\'t match the step', () => { - featureFile = featureWithSingleScenario; - stepDefinitions = stepsWithMismatchedSecondStep; - }); - }; - - const andThereIsAnExtraScenarioInMyStepDefinitionsNotInMyFeatureFile = (and: DefineStepFunction) => { - and('there is an extra scenario in my step definitions not in my feature file', () => { - featureFile = featureWithSingleScenario; - stepDefinitions = stepsForfeatureWithMultipleScenarios; - }); - }; - - test('Enabled and scenario missing step definitions', ({ given, and, when, then }) => { - givenScenariosMustMatchFeatureFileIsEnabled(given); - andAScenarioInAFeatureFileHasNoStepDefinitions(and); - whenIRunMyJestCucumberTests(when); - thenIShouldSeeAValidationErrorAndGeneratedCode(then); - }); + const givenScenariosMustMatchFeatureFileIsDisabled = givenScenariosMustMatchFeatureFileIsEnabled; - test('Disabled and scenario missing step definitions', ({ given, and, when, then }) => { - givenScenariosMustMatchFeatureFileIsDisabled(given); - andAScenarioInAFeatureFileHasNoStepDefinitions(and); - whenIRunMyJestCucumberTests(when); - thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + const givenStepsMustMatchFeatureFileIsEnabled = (given: DefineStepFunction) => { + given(/`stepsMustMatchFeatureFile` is (enabled|disabled)/, enabledOrDisabled => { + (options.errors as ErrorOptions).stepsMustMatchFeatureFile = enabledOrDisabled === 'enabled'; }); + }; - test('Enabled and scenario filtered via tag filter', ({ given, and, when, then }) => { - givenScenariosMustMatchFeatureFileIsEnabled(given); - andAScenarioInAFeatureFileHasNoStepDefinitions(and); - - and('that scenario is filtered via a tag filter', () => { - options.tagFilter = 'not @my-tag'; - }); - - whenIRunMyJestCucumberTests(when); - thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + const givenAllowScenariosNotInFeatureFileIsEnabled = (given: DefineStepFunction) => { + given(/`allowScenariosNotInFeatureFile` is (enabled|disabled)/, enabledOrDisabled => { + (options.errors as ErrorOptions).allowScenariosNotInFeatureFile = enabledOrDisabled === 'enabled'; }); + }; - test('Scenario order is the same', ({ given, and, when, then }) => { - givenScenariosMustMatchFeatureFileIsEnabled(given); + const givenAllowScenariosNotInFeatureFileIsDisabled = givenAllowScenariosNotInFeatureFileIsEnabled; - and('a set of scenarios is ordered the same in the feature / step definitions', () => { - featureFile = featureWithMultipleScenarios; - stepDefinitions = stepsForfeatureWithMultipleScenarios; - }); + const givenStepsMustMatchFeatureFileIsDisabled = givenStepsMustMatchFeatureFileIsEnabled; - whenIRunMyJestCucumberTests(when); - thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + const whenIRunMyJestCucumberTests = (when: DefineStepFunction) => { + when('I run my Jest Cucumber tests', () => { + try { + wireUpMockFeature(mockTestRunner, featureFile as string, stepDefinitions, options); + } catch (err) { + errorMessage = err.message; + } }); - - test('Scenario order is different', ({ given, and, when, then }) => { - givenScenariosMustMatchFeatureFileIsEnabled(given); - - and('a set of scenarios is ordered the differently in the feature / step definitions', () => { - featureFile = featureWithMultipleScenarios; - stepDefinitions = stepsWithScenariosOutOfOrder; - }); - - whenIRunMyJestCucumberTests(when); - thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + }; + + const thenIShouldSeeAValidationErrorAndGeneratedCode = (then: DefineStepFunction) => { + then(/I should (see|not see) a validation error \/ generated code/, seeOrNotSee => { + if (seeOrNotSee === 'see') { + expect(errorMessage).toBeTruthy(); + expect(errorMessage).toMatchSnapshot(); + } else { + expect(errorMessage).toBeFalsy(); + } }); + }; + + const thenIShouldNotSeeAValidationErrorAndGeneratedCode = thenIShouldSeeAValidationErrorAndGeneratedCode; + + const thenIShouldSeeAValidationError = (then: DefineStepFunction) => { + then(/I should (see|not see) a validation error/, seeOrNotSee => { + if (seeOrNotSee === 'see') { + expect(errorMessage).toBeTruthy(); + expect(errorMessage).toMatchSnapshot(); + } else { + expect(errorMessage).toBeFalsy(); + } + }); + }; - test('Enabled and step order / count are the same', ({ given, and, when, then }) => { - givenStepsMustMatchFeatureFileIsEnabled(given); - - and('the step definitions exactly match the feature file', () => { - featureFile = featureWithMultipleScenarios; - stepDefinitions = stepsForfeatureWithMultipleScenarios; - }); + const thenIShouldNotSeeAValidationError = thenIShouldSeeAValidationError; - whenIRunMyJestCucumberTests(when); - thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + const andAScenarioInAFeatureFileHasNoStepDefinitions = (and: DefineStepFunction) => { + and('a scenario in a feature file has no step definitions', () => { + featureFile = featureWithSingleScenario; + stepDefinitions = emptyStepDefinitions; }); + }; - test('Enabled and step order is different', ({ given, and, when, then }) => { - givenStepsMustMatchFeatureFileIsEnabled(given); - andTheStepOrderDiffersBetweenTheFeatureAndStepDefinitions(and); - whenIRunMyJestCucumberTests(when); - thenIShouldSeeAValidationErrorAndGeneratedCode(then); + const andTheStepOrderDiffersBetweenTheFeatureAndStepDefinitions = (and: DefineStepFunction) => { + and('the step order differs between the feature / step definitions', () => { + featureFile = featureWithSingleScenario; + stepDefinitions = stepsWithStepsOutOfOrder; }); + }; - test('Enabled and step count is different', ({ given, and, when, then }) => { - givenStepsMustMatchFeatureFileIsEnabled(given); - andTheStepCountDiffersBetweenTheFeatureAndStepDefinitions(and); - whenIRunMyJestCucumberTests(when); - thenIShouldSeeAValidationErrorAndGeneratedCode(then); + const andTheStepCountDiffersBetweenTheFeatureAndStepDefinitions = (and: DefineStepFunction) => { + and('the step count differs between the feature / step definitions', () => { + featureFile = featureWithSingleScenario; + stepDefinitions = stepsWithMissingStep; }); + }; - test('Disabled and step order is different', ({ given, and, when, then }) => { - givenStepsMustMatchFeatureFileIsDisabled(given); - andTheStepOrderDiffersBetweenTheFeatureAndStepDefinitions(and); - whenIRunMyJestCucumberTests(when); - thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + const andIHaveAScenarioWhereTheStepMatcherForTheSecondStepDoesntMatchTheStep = (and: DefineStepFunction) => { + and("I have a scenario where the step matcher for the second step doesn't match the step", () => { + featureFile = featureWithSingleScenario; + stepDefinitions = stepsWithMismatchedSecondStep; }); + }; - test('Disabled and step count is different', ({ given, and, when, then }) => { - givenStepsMustMatchFeatureFileIsDisabled(given); - andTheStepCountDiffersBetweenTheFeatureAndStepDefinitions(and); - whenIRunMyJestCucumberTests(when); - thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + const andThereIsAnExtraScenarioInMyStepDefinitionsNotInMyFeatureFile = (and: DefineStepFunction) => { + and('there is an extra scenario in my step definitions not in my feature file', () => { + featureFile = featureWithSingleScenario; + stepDefinitions = stepsForfeatureWithMultipleScenarios; }); - - test('Enabled and a step in the step definitions doesn\'t match the step in the feature', ({ given, and, when, then }) => { - givenStepsMustMatchFeatureFileIsEnabled(given); - andIHaveAScenarioWhereTheStepMatcherForTheSecondStepDoesntMatchTheStep(and); - whenIRunMyJestCucumberTests(when); - thenIShouldSeeAValidationErrorAndGeneratedCode(then); + }; + + test('Enabled and scenario missing step definitions', ({ given, and, when, then }) => { + givenScenariosMustMatchFeatureFileIsEnabled(given); + andAScenarioInAFeatureFileHasNoStepDefinitions(and); + whenIRunMyJestCucumberTests(when); + thenIShouldSeeAValidationErrorAndGeneratedCode(then); + }); + + test('Disabled and scenario missing step definitions', ({ given, and, when, then }) => { + givenScenariosMustMatchFeatureFileIsDisabled(given); + andAScenarioInAFeatureFileHasNoStepDefinitions(and); + whenIRunMyJestCucumberTests(when); + thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + }); + + test('Enabled and scenario filtered via tag filter', ({ given, and, when, then }) => { + givenScenariosMustMatchFeatureFileIsEnabled(given); + andAScenarioInAFeatureFileHasNoStepDefinitions(and); + + and('that scenario is filtered via a tag filter', () => { + options.tagFilter = 'not @my-tag'; }); - test('Disabled and a step in the step definitions doesn\'t match the step in the feature', ({ given, and, when, then }) => { - givenStepsMustMatchFeatureFileIsDisabled(given); - andIHaveAScenarioWhereTheStepMatcherForTheSecondStepDoesntMatchTheStep(and); - whenIRunMyJestCucumberTests(when); - thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + whenIRunMyJestCucumberTests(when); + thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + }); + + test('Scenario order is the same', ({ given, and, when, then }) => { + givenScenariosMustMatchFeatureFileIsEnabled(given); + + and('a set of scenarios is ordered the same in the feature / step definitions', () => { + featureFile = featureWithMultipleScenarios; + stepDefinitions = stepsForfeatureWithMultipleScenarios; }); - test('Scenario with no steps', ({ given, and, when, then }) => { - givenStepsMustMatchFeatureFileIsDisabled(given); + whenIRunMyJestCucumberTests(when); + thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + }); - and('I have a scenario with no steps', () => { - featureFile = featureWithSteplessScenario; - stepDefinitions = steplessStepDefinitions; - }); + test('Scenario order is different', ({ given, and, when, then }) => { + givenScenariosMustMatchFeatureFileIsEnabled(given); - whenIRunMyJestCucumberTests(when); - thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + and('a set of scenarios is ordered the differently in the feature / step definitions', () => { + featureFile = featureWithMultipleScenarios; + stepDefinitions = stepsWithScenariosOutOfOrder; }); - test('Enabled and step definitions have an extra scenario', ({ given, and, when, then }) => { - givenAllowScenariosNotInFeatureFileIsEnabled(given); - andThereIsAnExtraScenarioInMyStepDefinitionsNotInMyFeatureFile(and); - whenIRunMyJestCucumberTests(when); - thenIShouldNotSeeAValidationError(then); + whenIRunMyJestCucumberTests(when); + thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + }); + + test('Enabled and step order / count are the same', ({ given, and, when, then }) => { + givenStepsMustMatchFeatureFileIsEnabled(given); + + and('the step definitions exactly match the feature file', () => { + featureFile = featureWithMultipleScenarios; + stepDefinitions = stepsForfeatureWithMultipleScenarios; }); - test('Disabled and step definitions have an extra scenario', ({ given, and, when, then }) => { - givenAllowScenariosNotInFeatureFileIsDisabled(given); - andThereIsAnExtraScenarioInMyStepDefinitionsNotInMyFeatureFile(and); - whenIRunMyJestCucumberTests(when); - thenIShouldSeeAValidationError(then); + whenIRunMyJestCucumberTests(when); + thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + }); + + test('Enabled and step order is different', ({ given, and, when, then }) => { + givenStepsMustMatchFeatureFileIsEnabled(given); + andTheStepOrderDiffersBetweenTheFeatureAndStepDefinitions(and); + whenIRunMyJestCucumberTests(when); + thenIShouldSeeAValidationErrorAndGeneratedCode(then); + }); + + test('Enabled and step count is different', ({ given, and, when, then }) => { + givenStepsMustMatchFeatureFileIsEnabled(given); + andTheStepCountDiffersBetweenTheFeatureAndStepDefinitions(and); + whenIRunMyJestCucumberTests(when); + thenIShouldSeeAValidationErrorAndGeneratedCode(then); + }); + + test('Disabled and step order is different', ({ given, and, when, then }) => { + givenStepsMustMatchFeatureFileIsDisabled(given); + andTheStepOrderDiffersBetweenTheFeatureAndStepDefinitions(and); + whenIRunMyJestCucumberTests(when); + thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + }); + + test('Disabled and step count is different', ({ given, and, when, then }) => { + givenStepsMustMatchFeatureFileIsDisabled(given); + andTheStepCountDiffersBetweenTheFeatureAndStepDefinitions(and); + whenIRunMyJestCucumberTests(when); + thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + }); + + test("Enabled and a step in the step definitions doesn't match the step in the feature", ({ + given, + and, + when, + then, + }) => { + givenStepsMustMatchFeatureFileIsEnabled(given); + andIHaveAScenarioWhereTheStepMatcherForTheSecondStepDoesntMatchTheStep(and); + whenIRunMyJestCucumberTests(when); + thenIShouldSeeAValidationErrorAndGeneratedCode(then); + }); + + test("Disabled and a step in the step definitions doesn't match the step in the feature", ({ + given, + and, + when, + then, + }) => { + givenStepsMustMatchFeatureFileIsDisabled(given); + andIHaveAScenarioWhereTheStepMatcherForTheSecondStepDoesntMatchTheStep(and); + whenIRunMyJestCucumberTests(when); + thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + }); + + test('Scenario with no steps', ({ given, and, when, then }) => { + givenStepsMustMatchFeatureFileIsDisabled(given); + + and('I have a scenario with no steps', () => { + featureFile = featureWithSteplessScenario; + stepDefinitions = steplessStepDefinitions; }); + + whenIRunMyJestCucumberTests(when); + thenIShouldNotSeeAValidationErrorAndGeneratedCode(then); + }); + + test('Enabled and step definitions have an extra scenario', ({ given, and, when, then }) => { + givenAllowScenariosNotInFeatureFileIsEnabled(given); + andThereIsAnExtraScenarioInMyStepDefinitionsNotInMyFeatureFile(and); + whenIRunMyJestCucumberTests(when); + thenIShouldNotSeeAValidationError(then); + }); + + test('Disabled and step definitions have an extra scenario', ({ given, and, when, then }) => { + givenAllowScenariosNotInFeatureFileIsDisabled(given); + andThereIsAnExtraScenarioInMyStepDefinitionsNotInMyFeatureFile(and); + whenIRunMyJestCucumberTests(when); + thenIShouldSeeAValidationError(then); + }); }); diff --git a/specs/test-data/step-execution.ts b/specs/test-data/step-execution.ts index af258b3..d03f656 100644 --- a/specs/test-data/step-execution.ts +++ b/specs/test-data/step-execution.ts @@ -12,107 +12,95 @@ Feature: Executing a feature `; export const synchronousSteps = (logs: string[]): MockStepDefinitions => { - return ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, - ) => { - defineMockFeature(mockFeature, (test) => { - test('Executing a scenario', ({ given, when, then }) => { - given('a given step', () => { - logs.push('given step'); - }); - - when('i run the when step', () => { - logs.push('when step'); - }); - - then('it should run the then step', () => { - logs.push('then step'); - }); - }); + return (mockFeature: ParsedFeature, defineMockFeature: DefineFeatureFunction) => { + defineMockFeature(mockFeature, test => { + test('Executing a scenario', ({ given, when, then }) => { + given('a given step', () => { + logs.push('given step'); }); - }; + + when('i run the when step', () => { + logs.push('when step'); + }); + + then('it should run the then step', () => { + logs.push('then step'); + }); + }); + }); + }; }; export const failingSynchronousStep = (logs: string[]): MockStepDefinitions => { - return ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, - ) => { - defineMockFeature(mockFeature, (test) => { - test('Executing a scenario', ({ given, when, then }) => { - given('a given step', () => { - logs.push('given step'); - }); - - when('i run the when step', () => { - logs.push('when step'); - throw new Error('when step failure'); - }); - - then('it should run the then step', () => { - logs.push('then step'); - }); - }); + return (mockFeature: ParsedFeature, defineMockFeature: DefineFeatureFunction) => { + defineMockFeature(mockFeature, test => { + test('Executing a scenario', ({ given, when, then }) => { + given('a given step', () => { + logs.push('given step'); }); - }; + + when('i run the when step', () => { + logs.push('when step'); + throw new Error('when step failure'); + }); + + then('it should run the then step', () => { + logs.push('then step'); + }); + }); + }); + }; }; export const asyncStep = (logs: string[]): MockStepDefinitions => { - return ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, - ) => { - defineMockFeature(mockFeature, (test) => { - test('Executing a scenario', ({ given, when, then }) => { - given('a given step', () => { - logs.push('given step'); - }); - - when('i run the when step', async () => { - logs.push('when step started'); - - await new Promise((resolve) => { - setTimeout(() => { - logs.push('when step completed'); - resolve(); - }, 5); - }); - }); - - then('it should run the then step', () => { - logs.push('then step'); - }); - }); + return (mockFeature: ParsedFeature, defineMockFeature: DefineFeatureFunction) => { + defineMockFeature(mockFeature, test => { + test('Executing a scenario', ({ given, when, then }) => { + given('a given step', () => { + logs.push('given step'); + }); + + when('i run the when step', async () => { + logs.push('when step started'); + + await new Promise(resolve => { + setTimeout(() => { + logs.push('when step completed'); + resolve(); + }, 5); + }); }); - }; + + then('it should run the then step', () => { + logs.push('then step'); + }); + }); + }); + }; }; export const failingAsyncStep = (logs: string[]): MockStepDefinitions => { - return ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, - ) => { - defineMockFeature(mockFeature, (test) => { - test('Executing a scenario', ({ given, when, then }) => { - given('a given step', () => { - logs.push('given step'); - }); - - when('i run the when step', async () => { - logs.push('when step started'); - - await new Promise((resolve, reject) => { - setTimeout(() => { - reject(new Error('when step failure')); - }, 5); - }); - }); - - then('it should run the then step', () => { - logs.push('then step'); - }); - }); + return (mockFeature: ParsedFeature, defineMockFeature: DefineFeatureFunction) => { + defineMockFeature(mockFeature, test => { + test('Executing a scenario', ({ given, when, then }) => { + given('a given step', () => { + logs.push('given step'); + }); + + when('i run the when step', async () => { + logs.push('when step started'); + + await new Promise((resolve, reject) => { + setTimeout(() => { + reject(new Error('when step failure')); + }, 5); + }); + }); + + then('it should run the then step', () => { + logs.push('then step'); }); - }; + }); + }); + }; }; diff --git a/specs/test-data/step-matching.ts b/specs/test-data/step-matching.ts index d70a3f5..0a0e3bb 100644 --- a/specs/test-data/step-matching.ts +++ b/specs/test-data/step-matching.ts @@ -9,32 +9,26 @@ Feature: Matching steps Given a given step with step arguments "1" and "2" `; -export const stringStepMatcher = (stepArgs: any[]): MockStepDefinitions => { - return ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, - ) => { - defineMockFeature(mockFeature, (test) => { - test('Matching steps', ({ given }) => { - given('a given step with step arguments "1" and "2"', (...args: any[]) => { - args.forEach((arg) => stepArgs.push(arg)); - }); - }); +export const stringStepMatcher = (stepArgs: unknown[]): MockStepDefinitions => { + return (mockFeature: ParsedFeature, defineMockFeature: DefineFeatureFunction) => { + defineMockFeature(mockFeature, test => { + test('Matching steps', ({ given }) => { + given('a given step with step arguments "1" and "2"', (...args: unknown[]) => { + args.forEach(arg => stepArgs.push(arg)); }); - }; + }); + }); + }; }; -export const regexStepMatcher = (stepArgs: any[]): MockStepDefinitions => { - return ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, - ) => { - defineMockFeature(mockFeature, (test) => { - test('Matching steps', ({ given }) => { - given(/a given step with step arguments "(\d+)" and "(\d+)"/, (...args: any[]) => { - args.forEach((arg) => stepArgs.push(arg)); - }); - }); +export const regexStepMatcher = (stepArgs: unknown[]): MockStepDefinitions => { + return (mockFeature: ParsedFeature, defineMockFeature: DefineFeatureFunction) => { + defineMockFeature(mockFeature, test => { + test('Matching steps', ({ given }) => { + given(/a given step with step arguments "(\d+)" and "(\d+)"/, (...args: unknown[]) => { + args.forEach(arg => stepArgs.push(arg)); }); - }; + }); + }); + }; }; diff --git a/specs/test-data/step-table-arguments.ts b/specs/test-data/step-table-arguments.ts index 9b777e1..34743e8 100644 --- a/specs/test-data/step-table-arguments.ts +++ b/specs/test-data/step-table-arguments.ts @@ -12,32 +12,26 @@ Feature: Table arguments | ban | bat | `; -export const tableStepWithoutStepArgs = (stepArgs: any[]): MockStepDefinitions => { - return ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, - ) => { - defineMockFeature(mockFeature, (test) => { - test('Matching steps', ({ given }) => { - given('a given step with step arguments "1" and "2" and this:', (...args: any[]) => { - args.forEach((arg) => stepArgs.push(arg)); - }); - }); +export const tableStepWithoutStepArgs = (stepArgs: unknown[]): MockStepDefinitions => { + return (mockFeature: ParsedFeature, defineMockFeature: DefineFeatureFunction) => { + defineMockFeature(mockFeature, test => { + test('Matching steps', ({ given }) => { + given('a given step with step arguments "1" and "2" and this:', (...args: unknown[]) => { + args.forEach(arg => stepArgs.push(arg)); }); - }; + }); + }); + }; }; -export const tableStepWithStepArgs = (stepArgs: any[]): MockStepDefinitions => { - return ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, - ) => { - defineMockFeature(mockFeature, (test) => { - test('Matching steps', ({ given }) => { - given(/a given step with step arguments "(\d+)" and "(\d+)"/, (...args: any[]) => { - args.forEach((arg) => stepArgs.push(arg)); - }); - }); +export const tableStepWithStepArgs = (stepArgs: unknown[]): MockStepDefinitions => { + return (mockFeature: ParsedFeature, defineMockFeature: DefineFeatureFunction) => { + defineMockFeature(mockFeature, test => { + test('Matching steps', ({ given }) => { + given(/a given step with step arguments "(\d+)" and "(\d+)"/, (...args: unknown[]) => { + args.forEach(arg => stepArgs.push(arg)); }); - }; + }); + }); + }; }; diff --git a/specs/test-data/validation-and-code-generation.ts b/specs/test-data/validation-and-code-generation.ts index 801f67c..1e70565 100644 --- a/specs/test-data/validation-and-code-generation.ts +++ b/specs/test-data/validation-and-code-generation.ts @@ -34,150 +34,150 @@ Feature: Test `; export const emptyStepDefinitions: MockStepDefinitions = ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, + mockFeature: ParsedFeature, + defineMockFeature: DefineFeatureFunction, ) => { - defineMockFeature(mockFeature, () => { - // No step definitions defined - }); + defineMockFeature(mockFeature, () => { + // No step definitions defined + }); }; export const stepsForfeatureWithMultipleScenarios: MockStepDefinitions = ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, + mockFeature: ParsedFeature, + defineMockFeature: DefineFeatureFunction, ) => { - defineMockFeature(mockFeature, (test) => { - test('Doing some stuff', ({ given, when, then }) => { - given('I did some stuff', () => { - // Nothing to do here - }); - - when('I do some stuff', () => { - // Nothing to do here - }); - - then('I should have done some stuff', () => { - // Nothing to do here - }); - }); - - test('Doing some more stuff', ({ given, when, then }) => { - given('I did some stuff', () => { - // Nothing to do here - }); - - when('I do some stuff', () => { - // Nothing to do here - }); - - then('I should have done some stuff', () => { - // Nothing to do here - }); - }); + defineMockFeature(mockFeature, test => { + test('Doing some stuff', ({ given, when, then }) => { + given('I did some stuff', () => { + // Nothing to do here + }); + + when('I do some stuff', () => { + // Nothing to do here + }); + + then('I should have done some stuff', () => { + // Nothing to do here + }); + }); + + test('Doing some more stuff', ({ given, when, then }) => { + given('I did some stuff', () => { + // Nothing to do here + }); + + when('I do some stuff', () => { + // Nothing to do here + }); + + then('I should have done some stuff', () => { + // Nothing to do here + }); }); + }); }; export const stepsWithScenariosOutOfOrder: MockStepDefinitions = ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, + mockFeature: ParsedFeature, + defineMockFeature: DefineFeatureFunction, ) => { - defineMockFeature(mockFeature, (test) => { - test('Doing some more stuff', ({ given, when, then }) => { - given('I did some stuff', () => { - // Nothing to do here - }); - - when('I do some stuff', () => { - // Nothing to do here - }); - - then('I should have done some stuff', () => { - // Nothing to do here - }); - }); - - test('Doing some stuff', ({ given, when, then }) => { - given('I did some stuff', () => { - // Nothing to do here - }); - - when('I do some stuff', () => { - // Nothing to do here - }); - - then('I should have done some stuff', () => { - // Nothing to do here - }); - }); + defineMockFeature(mockFeature, test => { + test('Doing some more stuff', ({ given, when, then }) => { + given('I did some stuff', () => { + // Nothing to do here + }); + + when('I do some stuff', () => { + // Nothing to do here + }); + + then('I should have done some stuff', () => { + // Nothing to do here + }); + }); + + test('Doing some stuff', ({ given, when, then }) => { + given('I did some stuff', () => { + // Nothing to do here + }); + + when('I do some stuff', () => { + // Nothing to do here + }); + + then('I should have done some stuff', () => { + // Nothing to do here + }); }); + }); }; export const stepsWithStepsOutOfOrder: MockStepDefinitions = ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, + mockFeature: ParsedFeature, + defineMockFeature: DefineFeatureFunction, ) => { - defineMockFeature(mockFeature, (test) => { - test('Doing some stuff', ({ given, when, then }) => { - given('I did some stuff', () => { - // Nothing to do here - }); - - then('I should have done some stuff', () => { - // Nothing to do here - }); - - when('I do some stuff', () => { - // Nothing to do here - }); - }); + defineMockFeature(mockFeature, test => { + test('Doing some stuff', ({ given, when, then }) => { + given('I did some stuff', () => { + // Nothing to do here + }); + + then('I should have done some stuff', () => { + // Nothing to do here + }); + + when('I do some stuff', () => { + // Nothing to do here + }); }); + }); }; export const stepsWithMissingStep: MockStepDefinitions = ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, + mockFeature: ParsedFeature, + defineMockFeature: DefineFeatureFunction, ) => { - defineMockFeature(mockFeature, (test) => { - test('Doing some stuff', ({ given, when, then }) => { - given('I did some stuff', () => { - // Nothing to do here - }); - - when('I do some stuff', () => { - // Nothing to do here - }); - }); + defineMockFeature(mockFeature, test => { + test('Doing some stuff', ({ given, when }) => { + given('I did some stuff', () => { + // Nothing to do here + }); + + when('I do some stuff', () => { + // Nothing to do here + }); }); + }); }; export const stepsWithMismatchedSecondStep: MockStepDefinitions = ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, + mockFeature: ParsedFeature, + defineMockFeature: DefineFeatureFunction, ) => { - defineMockFeature(mockFeature, (test) => { - test('Doing some stuff', ({ given, when, then }) => { - given('I did some stuff', () => { - // Nothing to do here - }); - - when('I don\'t do some stuff', () => { - // Nothing to do here - }); - - then('I should have done some stuff', () => { - // Nothing to do here - }); - }); + defineMockFeature(mockFeature, test => { + test('Doing some stuff', ({ given, when, then }) => { + given('I did some stuff', () => { + // Nothing to do here + }); + + when("I don't do some stuff", () => { + // Nothing to do here + }); + + then('I should have done some stuff', () => { + // Nothing to do here + }); }); + }); }; export const steplessStepDefinitions: MockStepDefinitions = ( - mockFeature: ParsedFeature, - defineMockFeature: DefineFeatureFunction, + mockFeature: ParsedFeature, + defineMockFeature: DefineFeatureFunction, ) => { - defineMockFeature(mockFeature, (test) => { - test('Doing nothing at all', ({ given, when, then }) => { - // No steps to define - }); + defineMockFeature(mockFeature, test => { + test('Doing nothing at all', () => { + // No steps to define }); + }); }; diff --git a/specs/utils/mock-test-runner/mock-describe-block.ts b/specs/utils/mock-test-runner/mock-describe-block.ts index a1b01a0..8946d13 100644 --- a/specs/utils/mock-test-runner/mock-describe-block.ts +++ b/specs/utils/mock-test-runner/mock-describe-block.ts @@ -1,21 +1,20 @@ import { MockTest } from './mock-test'; export class MockDescribeBlock { - public description: string | null = null; - public skip: boolean = false; - public concurrent: boolean = false; - public only: boolean = false; - public children: Array = []; + public description: string | null = null; - constructor( - description: string | null, - skip: boolean, - concurrent: boolean, - only: boolean, - ) { - this.description = description; - this.skip = skip; - this.concurrent = concurrent; - this.only = only; - } + public skip: boolean = false; + + public concurrent: boolean = false; + + public only: boolean = false; + + public children: Array = []; + + constructor(description: string | null, skip: boolean, concurrent: boolean, only: boolean) { + this.description = description; + this.skip = skip; + this.concurrent = concurrent; + this.only = only; + } } diff --git a/specs/utils/mock-test-runner/mock-test-runner.ts b/specs/utils/mock-test-runner/mock-test-runner.ts index bfac106..4112484 100644 --- a/specs/utils/mock-test-runner/mock-test-runner.ts +++ b/specs/utils/mock-test-runner/mock-test-runner.ts @@ -1,112 +1,101 @@ -import { IJestLike } from '../../../src/feature-definition-creation'; -import { MockDescribeBlock } from './mock-describe-block'; -import { MockTest } from './mock-test'; - -export class MockTestRunner implements IJestLike { - public rootDescribeBlock: MockDescribeBlock; - private currentDescribeBlock: MockDescribeBlock; - - constructor() { - this.rootDescribeBlock = new MockDescribeBlock(null, false, false, false); - this.currentDescribeBlock = this.rootDescribeBlock; - } - - public get describe() { - const createDescribeFunc = ( - skip: boolean, - concurrent: boolean, - only: boolean, - ) => { - return ( - description: number - | string - | ((...args: any[]) => any) - | jest.FunctionLike, - func: jest.EmptyFunction, - ) => { - const newDescribeBlock = new MockDescribeBlock( - description as string, - skip, - concurrent, - only, - ); - - this.currentDescribeBlock.children.push(newDescribeBlock); - this.currentDescribeBlock = newDescribeBlock; - - func(); - }; - }; - - const describeFunc: any = createDescribeFunc(false, false, false); - - describeFunc.only = createDescribeFunc(false, false, true); - describeFunc.skip = createDescribeFunc(true, false, false); - describeFunc.concurrent = createDescribeFunc(false, true, false); - describeFunc.each = (arr: any[][]) => { - throw new Error('Not implemented'); - }; - - return describeFunc as jest.Describe; - } - - public get test() { - const createTestFunc = ( - skip: boolean, - concurrent: boolean, - only: boolean, - ) => { - return (description: string, func: jest.ProvidesCallback) => { - this.currentDescribeBlock.children.push(new MockTest( - description, - func, - skip, - concurrent, - only, - )); - }; - }; - - const testFunc: any = createTestFunc(false, false, false); - - testFunc.only = createTestFunc(false, false, true); - testFunc.skip = createTestFunc(true, false, false); - testFunc.concurrent = createTestFunc(false, true, false); - testFunc.each = () => { - throw new Error('Not implemented'); - }; - - return testFunc as jest.It; - } - - public execute(describeBlock?: MockDescribeBlock) { - if (!describeBlock) { - describeBlock = this.rootDescribeBlock; - } - - const testOutputs = describeBlock.children.map((child) => { - if (child instanceof MockTest) { - const cb: any = () => { throw new Error('Callbacks not supported'); }; - cb.fail = (message: string) => { throw new Error('Callback failure (callbacks not supported)'); }; - - return child.executionFunc(cb as jest.DoneCallback); - } else if (child instanceof MockDescribeBlock) { - return this.execute(child); - } - }); - - const testPromises: Array> = testOutputs.filter((testOutput: any) => { - if ((testOutput as PromiseLike).then !== undefined) { - return true; - } else { - return false; - } - }); - - if (!testPromises.length) { - testPromises.push(Promise.resolve()); - } - - return Promise.all(testPromises); - } -} +import { IJestLike } from '../../../src/feature-definition-creation'; +import { MockDescribeBlock } from './mock-describe-block'; +import { MockTest } from './mock-test'; + +export class MockTestRunner implements IJestLike { + public rootDescribeBlock: MockDescribeBlock; + + private currentDescribeBlock: MockDescribeBlock; + + constructor() { + this.rootDescribeBlock = new MockDescribeBlock(null, false, false, false); + this.currentDescribeBlock = this.rootDescribeBlock; + } + + public get describe() { + const createDescribeFunc = (skip: boolean, concurrent: boolean, only: boolean) => { + return ( + description: number | string | ((...args: unknown[]) => unknown) | jest.FunctionLike, + func: jest.EmptyFunction, + ) => { + const newDescribeBlock = new MockDescribeBlock(description as string, skip, concurrent, only); + + this.currentDescribeBlock.children.push(newDescribeBlock); + this.currentDescribeBlock = newDescribeBlock; + + func(); + }; + }; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const describeFunc: any = createDescribeFunc(false, false, false); + + describeFunc.only = createDescribeFunc(false, false, true); + describeFunc.skip = createDescribeFunc(true, false, false); + describeFunc.concurrent = createDescribeFunc(false, true, false); + describeFunc.each = () => { + throw new Error('Not implemented'); + }; + + return describeFunc as jest.Describe; + } + + public get test() { + const createTestFunc = (skip: boolean, concurrent: boolean, only: boolean) => { + return (description: string, func: jest.ProvidesCallback) => { + this.currentDescribeBlock.children.push(new MockTest(description, func, skip, concurrent, only)); + }; + }; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const testFunc: any = createTestFunc(false, false, false); + + testFunc.only = createTestFunc(false, false, true); + testFunc.skip = createTestFunc(true, false, false); + testFunc.concurrent = createTestFunc(false, true, false); + testFunc.each = () => { + throw new Error('Not implemented'); + }; + + return testFunc as jest.It; + } + + public execute(describeBlock?: MockDescribeBlock) { + if (!describeBlock) { + // eslint-disable-next-line no-param-reassign + describeBlock = this.rootDescribeBlock; + } + + const testOutputs = describeBlock.children.map(child => { + if (child instanceof MockTest) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const cb: any = () => { + throw new Error('Callbacks not supported'); + }; + cb.fail = () => { + throw new Error('Callback failure (callbacks not supported)'); + }; + + return child.executionFunc(cb as jest.DoneCallback); + } + if (child instanceof MockDescribeBlock) { + return this.execute(child); + } + return null; + }); + + const testPromises: (void | undefined | PromiseLike | Promise[]> | null)[] = + testOutputs.filter((testOutput: unknown) => { + if ((testOutput as PromiseLike).then !== undefined) { + return true; + } + return false; + }); + + if (!testPromises.length) { + testPromises.push(Promise.resolve()); + } + + return Promise.all(testPromises); + } +} diff --git a/specs/utils/mock-test-runner/mock-test.ts b/specs/utils/mock-test-runner/mock-test.ts index 1474b89..7d81774 100644 --- a/specs/utils/mock-test-runner/mock-test.ts +++ b/specs/utils/mock-test-runner/mock-test.ts @@ -1,21 +1,25 @@ export class MockTest { - public description: string; - public executionFunc: jest.ProvidesCallback; - public skip: boolean = false; - public concurrent: boolean = false; - public only: boolean = false; + public description: string; - constructor( - description: string, - executionFunc: jest.ProvidesCallback, - skip: boolean, - concurrent: boolean, - only: boolean, - ) { - this.description = description; - this.executionFunc = executionFunc; - this.skip = skip; - this.concurrent = concurrent; - this.only = only; - } + public executionFunc: jest.ProvidesCallback; + + public skip: boolean = false; + + public concurrent: boolean = false; + + public only: boolean = false; + + constructor( + description: string, + executionFunc: jest.ProvidesCallback, + skip: boolean, + concurrent: boolean, + only: boolean, + ) { + this.description = description; + this.executionFunc = executionFunc; + this.skip = skip; + this.concurrent = concurrent; + this.only = only; + } } diff --git a/specs/utils/wire-up-mock-scenario.ts b/specs/utils/wire-up-mock-scenario.ts index 4aef5ba..a8fad53 100644 --- a/specs/utils/wire-up-mock-scenario.ts +++ b/specs/utils/wire-up-mock-scenario.ts @@ -7,15 +7,15 @@ import { MockTestRunner } from './mock-test-runner/mock-test-runner'; export type MockStepDefinitions = (feature: ParsedFeature, defineFeature: DefineFeatureFunction) => void; export const wireUpMockFeature = ( - mockTestRunner: MockTestRunner, - featureFile: string, - mockStepDefinitions: MockStepDefinitions | null, - options?: Options, + mockTestRunner: MockTestRunner, + featureFile: string, + mockStepDefinitions: MockStepDefinitions | null, + options?: Options, ) => { - const defineMockFeature = createDefineFeature(mockTestRunner); - const mockFeature = parseFeature(featureFile, options); + const defineMockFeature = createDefineFeature(mockTestRunner); + const mockFeature = parseFeature(featureFile, options); - if (mockStepDefinitions) { - mockStepDefinitions(mockFeature, defineMockFeature); - } + if (mockStepDefinitions) { + mockStepDefinitions(mockFeature, defineMockFeature); + } }; diff --git a/src/automatic-step-binding.ts b/src/automatic-step-binding.ts index 608c965..698447d 100644 --- a/src/automatic-step-binding.ts +++ b/src/automatic-step-binding.ts @@ -1,66 +1,70 @@ -import { ParsedFeature } from './models'; -import { matchSteps } from './validation/step-definition-validation'; -import { StepsDefinitionCallbackFunction, createDefineFeature, IJestLike } from './feature-definition-creation'; -import { generateStepCode } from './code-generation/step-generation'; - -const globalSteps: Array<{ stepMatcher: string | RegExp, stepFunction: () => any }> = []; - -const registerStep = (stepMatcher: string | RegExp, stepFunction: () => any) => { - globalSteps.push({ stepMatcher, stepFunction }); -}; - -export const createAutoBindSteps = (jestLike: IJestLike) => { - const defineFeature = createDefineFeature(jestLike); - - return (features: ParsedFeature[], stepDefinitions: StepsDefinitionCallbackFunction[]) => { - stepDefinitions.forEach((stepDefinitionCallback) => { - stepDefinitionCallback({ - defineStep: registerStep, - given: registerStep, - when: registerStep, - then: registerStep, - and: registerStep, - but: registerStep, - pending: () => { - // Nothing to do - }, - }); - }); - - const errors: string[] = []; - - features.forEach((feature) => { - defineFeature(feature, (test) => { - const scenarioOutlineScenarios = feature.scenarioOutlines - .map((scenarioOutline) => scenarioOutline.scenarios[0]); - - const scenarios = [...feature.scenarios, ...scenarioOutlineScenarios]; - - scenarios.forEach((scenario) => { - test(scenario.title, (options) => { - scenario.steps.forEach((step, stepIndex) => { - const matches = globalSteps - .filter((globalStep) => matchSteps(step.stepText, globalStep.stepMatcher)); - - if (matches.length === 1) { - const match = matches[0]; - - options.defineStep(match.stepMatcher, match.stepFunction); - } else if (matches.length === 0) { - const stepCode = generateStepCode(scenario.steps, stepIndex, false); - errors.push(`No matching step found for step "${step.stepText}" in scenario "${scenario.title}" in feature "${feature.title}". Please add the following step code: \n\n${stepCode}`); - } else { - const matchingCode = matches.map((match) => `${match.stepMatcher.toString()}\n\n${match.stepFunction.toString()}`); - errors.push(`${matches.length} step definition matches were found for step "${step.stepText}" in scenario "${scenario.title}" in feature "${feature.title}". Each step can only have one matching step definition. The following step definition matches were found:\n\n${matchingCode.join('\n\n')}`); - } - }); - }); - }); - }); - }); - - if (errors.length) { - throw new Error(errors.join('\n\n')); - } - }; -}; +import { ParsedFeature } from './models'; +import { matchSteps } from './validation/step-definition-validation'; +import { StepsDefinitionCallbackFunction, createDefineFeature, IJestLike } from './feature-definition-creation'; +import { generateStepCode } from './code-generation/step-generation'; + +const globalSteps: Array<{ stepMatcher: string | RegExp; stepFunction: () => unknown }> = []; + +const registerStep = (stepMatcher: string | RegExp, stepFunction: () => unknown) => { + globalSteps.push({ stepMatcher, stepFunction }); +}; + +export const createAutoBindSteps = (jestLike: IJestLike) => { + const defineFeature = createDefineFeature(jestLike); + + return (features: ParsedFeature[], stepDefinitions: StepsDefinitionCallbackFunction[]) => { + stepDefinitions.forEach(stepDefinitionCallback => { + stepDefinitionCallback({ + defineStep: registerStep, + given: registerStep, + when: registerStep, + then: registerStep, + and: registerStep, + but: registerStep, + pending: () => { + // Nothing to do + }, + }); + }); + + const errors: string[] = []; + + features.forEach(feature => { + defineFeature(feature, test => { + const scenarioOutlineScenarios = feature.scenarioOutlines.map(scenarioOutline => scenarioOutline.scenarios[0]); + + const scenarios = [...feature.scenarios, ...scenarioOutlineScenarios]; + + scenarios.forEach(scenario => { + test(scenario.title, options => { + scenario.steps.forEach((step, stepIndex) => { + const matches = globalSteps.filter(globalStep => matchSteps(step.stepText, globalStep.stepMatcher)); + + if (matches.length === 1) { + const match = matches[0]; + + options.defineStep(match.stepMatcher, match.stepFunction); + } else if (matches.length === 0) { + const stepCode = generateStepCode(scenario.steps, stepIndex, false); + errors.push( + `No matching step found for step "${step.stepText}" in scenario "${scenario.title}" in feature "${feature.title}". Please add the following step code: \n\n${stepCode}`, + ); + } else { + const matchingCode = matches.map( + match => `${match.stepMatcher.toString()}\n\n${match.stepFunction.toString()}`, + ); + errors.push( + `${matches.length} step definition matches were found for step "${step.stepText}" in scenario "${scenario.title}" in feature "${feature.title}". Each step can only have one matching step definition. The following step definition matches were found:\n\n${matchingCode.join('\n\n')}`, + ); + } + }); + }); + }); + }); + }); + + if (errors.length) { + throw new Error(errors.join('\n\n')); + } + }; +}; diff --git a/src/code-generation/generate-code-by-line-number.ts b/src/code-generation/generate-code-by-line-number.ts index 55ac25a..6bf7c82 100644 --- a/src/code-generation/generate-code-by-line-number.ts +++ b/src/code-generation/generate-code-by-line-number.ts @@ -1,85 +1,91 @@ -import { ParsedFeature } from '../models'; +import { ParsedFeature, ParsedScenario, ParsedScenarioOutline, ParsedStep } from '../models'; import { generateScenarioCodeWithSeparateStepFunctions, generateScenarioCode } from './scenario-generation'; import { generateStepCode } from './step-generation'; export enum ObjectTypeEnum { - scenario, - scenarioOutline, - step, + scenario, + scenarioOutline, + step, } const findObjectByLineNumber = ( - feature: ParsedFeature, - lineNumber: number, -): { object: any, type: ObjectTypeEnum } | null => { - let found: any = null; - let type: ObjectTypeEnum = ObjectTypeEnum.scenario; + feature: ParsedFeature, + lineNumber: number, +): { object: unknown; type: ObjectTypeEnum } | null => { + let found: unknown = null; + let type: ObjectTypeEnum = ObjectTypeEnum.scenario; - feature.scenarioOutlines.forEach((scenarioOutline) => { - if (scenarioOutline.lineNumber === lineNumber) { - found = scenarioOutline; - type = ObjectTypeEnum.scenarioOutline; - } + feature.scenarioOutlines.forEach(scenarioOutline => { + if (scenarioOutline.lineNumber === lineNumber) { + found = scenarioOutline; + type = ObjectTypeEnum.scenarioOutline; + } - scenarioOutline.steps.forEach((step, index) => { - if (step.lineNumber === lineNumber) { - found = { steps: scenarioOutline.steps, index }; - type = ObjectTypeEnum.step; - } - }); + scenarioOutline.steps.forEach((step, index) => { + if (step.lineNumber === lineNumber) { + found = { steps: scenarioOutline.steps, index }; + type = ObjectTypeEnum.step; + } }); + }); - feature.scenarios.forEach((scenario) => { - if (scenario.lineNumber === lineNumber) { - found = scenario; - type = ObjectTypeEnum.scenario; - } + feature.scenarios.forEach(scenario => { + if (scenario.lineNumber === lineNumber) { + found = scenario; + type = ObjectTypeEnum.scenario; + } - scenario.steps.forEach((step, index) => { - if (step.lineNumber === lineNumber) { - found = { steps: scenario.steps, index }; - type = ObjectTypeEnum.step; - } - }); + scenario.steps.forEach((step, index) => { + if (step.lineNumber === lineNumber) { + found = { steps: scenario.steps, index }; + type = ObjectTypeEnum.step; + } }); + }); - return found ? { object: found, type } : null; + return found ? { object: found, type } : null; }; -export const generateCodeFromFeature = ( - feature: ParsedFeature, - lineNumber: number, -) => { - const objectAtLine = findObjectByLineNumber(feature, lineNumber); +export const generateCodeFromFeature = (feature: ParsedFeature, lineNumber: number) => { + const objectAtLine = findObjectByLineNumber(feature, lineNumber); - if (objectAtLine === null) { - return null; - } else { - switch (objectAtLine.type) { - case ObjectTypeEnum.scenario: - case ObjectTypeEnum.scenarioOutline: - return generateScenarioCode(objectAtLine.object); - case ObjectTypeEnum.step: - return generateStepCode(objectAtLine.object.steps, objectAtLine.object.index, false); - } - } + if (objectAtLine === null) { + return null; + } + switch (objectAtLine.type) { + case ObjectTypeEnum.scenario: + case ObjectTypeEnum.scenarioOutline: + return generateScenarioCode(objectAtLine.object as ParsedScenario | ParsedScenarioOutline); + case ObjectTypeEnum.step: + return generateStepCode( + (objectAtLine.object as { steps: ParsedStep[] }).steps, + (objectAtLine.object as { index: number }).index, + false, + ); + default: + return null; + } }; -export const generateCodeWithSeparateFunctionsFromFeature = ( - feature: ParsedFeature, - lineNumber: number, -) => { - const objectAtLine = findObjectByLineNumber(feature, lineNumber); +export const generateCodeWithSeparateFunctionsFromFeature = (feature: ParsedFeature, lineNumber: number) => { + const objectAtLine = findObjectByLineNumber(feature, lineNumber); - if (objectAtLine === null) { - return null; - } else { - switch (objectAtLine.type) { - case ObjectTypeEnum.scenario: - case ObjectTypeEnum.scenarioOutline: - return generateScenarioCodeWithSeparateStepFunctions(objectAtLine.object); - case ObjectTypeEnum.step: - return generateStepCode(objectAtLine.object.steps, objectAtLine.object.index, true); - } - } + if (objectAtLine === null) { + return null; + } + switch (objectAtLine.type) { + case ObjectTypeEnum.scenario: + case ObjectTypeEnum.scenarioOutline: + return generateScenarioCodeWithSeparateStepFunctions( + objectAtLine.object as ParsedScenario | ParsedScenarioOutline, + ); + case ObjectTypeEnum.step: + return generateStepCode( + (objectAtLine.object as { steps: ParsedStep[] }).steps, + (objectAtLine.object as { index: number }).index, + true, + ); + default: + return null; + } }; diff --git a/src/code-generation/scenario-generation.ts b/src/code-generation/scenario-generation.ts index 1e4ed25..5c71153 100644 --- a/src/code-generation/scenario-generation.ts +++ b/src/code-generation/scenario-generation.ts @@ -3,32 +3,32 @@ import { generateStepCode, generateStepFunctionCall } from './step-generation'; import { indent } from './utils'; const scenarioTemplate = (scenarioTitle: string, steps: string, stepKeywords: string[]) => { - return `test('${scenarioTitle.replace(/'+/g, `\\'`)}', ({ ${stepKeywords.join(', ')} }) => {\n${indent(steps, 1).slice(0, -1)}\n});`; + return `test('${scenarioTitle.replace(/'+/g, `\\'`)}', ({ ${stepKeywords.join(', ')} }) => {\n${indent(steps, 1).slice(0, -1)}\n});`; }; const getStepKeywords = (scenario: ParsedScenario | ParsedScenarioOutline) => { - const stepKeywords: string[] = []; + const stepKeywords: string[] = []; - scenario.steps.forEach((step) => { - if (stepKeywords.indexOf(step.keyword) === -1) { - stepKeywords.push(step.keyword); - } - }); + scenario.steps.forEach(step => { + if (stepKeywords.indexOf(step.keyword) === -1) { + stepKeywords.push(step.keyword); + } + }); - return stepKeywords; + return stepKeywords; }; export const generateScenarioCode = (scenario: ParsedScenario | ParsedScenarioOutline) => { - const stepsCode = scenario.steps.map((step, index) => generateStepCode(scenario.steps, index)); - const stepKeywords = getStepKeywords(scenario); + const stepsCode = scenario.steps.map((step, index) => generateStepCode(scenario.steps, index)); + const stepKeywords = getStepKeywords(scenario); - return scenarioTemplate(scenario.title, stepsCode.join('\n\n'), stepKeywords); + return scenarioTemplate(scenario.title, stepsCode.join('\n\n'), stepKeywords); }; export const generateScenarioCodeWithSeparateStepFunctions = (scenario: ParsedScenario | ParsedScenarioOutline) => { - const stepFunctionCode = scenario.steps.map((step, index) => generateStepCode(scenario.steps, index, true)); - const stepFunctionCalls = scenario.steps.map((step, index) => generateStepFunctionCall(scenario.steps, index)); - const stepKeywords = getStepKeywords(scenario); + const stepFunctionCode = scenario.steps.map((step, index) => generateStepCode(scenario.steps, index, true)); + const stepFunctionCalls = scenario.steps.map((step, index) => generateStepFunctionCall(scenario.steps, index)); + const stepKeywords = getStepKeywords(scenario); - return `${stepFunctionCode.join('\n\n')}\n\n${scenarioTemplate(scenario.title, stepFunctionCalls.join('\n'), stepKeywords)}`; + return `${stepFunctionCode.join('\n\n')}\n\n${scenarioTemplate(scenario.title, stepFunctionCalls.join('\n'), stepKeywords)}`; }; diff --git a/src/code-generation/step-generation.ts b/src/code-generation/step-generation.ts index 74c9c13..ca751bf 100644 --- a/src/code-generation/step-generation.ts +++ b/src/code-generation/step-generation.ts @@ -1,12 +1,17 @@ import { ParsedStep } from '../models'; import { indent } from './utils'; +const stepTextArgumentRegex = /([-+]?[0-9]*\.?[0-9]+)|"([^"<]+)"|"?<([^"<]*)>"?/g; + const stepTemplate = (stepKeyword: string, stepMatcher: string, stepArgumentVariables: string[]) => { - return `${stepKeyword}(${stepMatcher}, (${stepArgumentVariables.join(', ')}) => {\n\n});`; + return `${stepKeyword}(${stepMatcher}, (${stepArgumentVariables.join(', ')}) => {\n\n});`; }; const getStepFunctionWrapperName = (stepKeyword: string, stepText: string) => { - return `${stepKeyword}_${stepText.replace(stepTextArgumentRegex, 'X').replace(/\s/g, '_').replace(/[^A-Za-z0-9_]/g, '')}`; + return `${stepKeyword}_${stepText + .replace(stepTextArgumentRegex, 'X') + .replace(/\s/g, '_') + .replace(/[^A-Za-z0-9_]/g, '')}`; }; const stepWrapperFunctionTemplate = ( @@ -15,96 +20,91 @@ const stepWrapperFunctionTemplate = ( stepMatcher: string, stepArgumentVariables: string[], ) => { - return `export const ${getStepFunctionWrapperName(stepKeyword, stepText)} = (${stepKeyword}) => {\n${indent(stepTemplate(stepKeyword, stepMatcher, stepArgumentVariables), 1).slice(0, -1)}\n}`; + return `export const ${getStepFunctionWrapperName(stepKeyword, stepText)} = (${stepKeyword}) => {\n${indent(stepTemplate(stepKeyword, stepMatcher, stepArgumentVariables), 1).slice(0, -1)}\n}`; }; const stepWrapperFunctionCallTemplate = (stepText: string, stepKeyword: string) => { - return `${getStepFunctionWrapperName(stepKeyword, stepText)}(${stepKeyword})`; + return `${getStepFunctionWrapperName(stepKeyword, stepText)}(${stepKeyword})`; }; -const stepTextArgumentRegex = /([-+]?[0-9]*\.?[0-9]+)|\"([^"<]+)\"|\"?\<([^"<]*)\>\"?/g; - const escapeRegexCharacters = (text: string) => { - return text - .replace(/\$/g, '\\$') - .replace(/\(/g, '\\(') - .replace(/\)/g, '\\)'); + return text.replace(/\$/g, '\\$').replace(/\(/g, '\\(').replace(/\)/g, '\\)'); }; const convertStepTextToRegex = (step: ParsedStep) => { - const stepText = escapeRegexCharacters(step.stepText); - let matches: RegExpExecArray | null; - let finalStepText = stepText; - - while (matches = stepTextArgumentRegex.exec(stepText)) { - const [fullMatch, numberMatch, stringMatch] = matches; - - if (numberMatch) { - finalStepText = finalStepText.replace(numberMatch, '(\\d+)'); - } else if (stringMatch) { - finalStepText = finalStepText.replace(stringMatch, '(.*)'); - } else { - finalStepText = finalStepText.replace(fullMatch, '(.*)'); - } + const stepText = escapeRegexCharacters(step.stepText); + let matches: RegExpExecArray | null = stepTextArgumentRegex.exec(stepText); + let finalStepText = stepText; + + while (matches) { + const [fullMatch, numberMatch, stringMatch] = matches; + + if (numberMatch) { + finalStepText = finalStepText.replace(numberMatch, '(\\d+)'); + } else if (stringMatch) { + finalStepText = finalStepText.replace(stringMatch, '(.*)'); + } else { + finalStepText = finalStepText.replace(fullMatch, '(.*)'); } - return `/^${finalStepText}$/`; + matches = stepTextArgumentRegex.exec(stepText); + } + + return `/^${finalStepText}$/`; }; const getStepArguments = (step: ParsedStep) => { - const stepArgumentVariables: string[] = []; + const stepArgumentVariables: string[] = []; - let match: RegExpExecArray | null; - let index: number = 0; + let index: number = 0; - while (match = stepTextArgumentRegex.exec(step.stepText)) { - stepArgumentVariables.push(`arg${index}`); - index++; - } + while (stepTextArgumentRegex.exec(step.stepText)) { + stepArgumentVariables.push(`arg${index}`); + index += 1; + } - if (step.stepArgument) { - if (typeof step.stepArgument === 'string') { - stepArgumentVariables.push('docString'); - } else { - stepArgumentVariables.push('table'); - } + if (step.stepArgument) { + if (typeof step.stepArgument === 'string') { + stepArgumentVariables.push('docString'); + } else { + stepArgumentVariables.push('table'); } + } - return stepArgumentVariables; + return stepArgumentVariables; }; const getStepMatcher = (step: ParsedStep) => { - let stepMatcher: string = ''; + let stepMatcher: string = ''; - if (step.stepText.match(stepTextArgumentRegex)) { - stepMatcher = convertStepTextToRegex(step); - } else { - stepMatcher = `'${step.stepText.replace(/'+/g, `\\'`)}'`; - } + if (step.stepText.match(stepTextArgumentRegex)) { + stepMatcher = convertStepTextToRegex(step); + } else { + stepMatcher = `'${step.stepText.replace(/'+/g, `\\'`)}'`; + } - return stepMatcher; + return stepMatcher; }; export const getStepKeyword = (steps: ParsedStep[], stepPosition: number) => { - return steps[stepPosition].keyword; + return steps[stepPosition].keyword; }; export const generateStepCode = (steps: ParsedStep[], stepPosition: number, generateWrapperFunction = false) => { - const step = steps[stepPosition]; - const stepKeyword = getStepKeyword(steps, stepPosition); - const stepMatcher = getStepMatcher(step); - const stepArguments = getStepArguments(step); - - if (generateWrapperFunction) { - return stepWrapperFunctionTemplate(stepKeyword, step.stepText, stepMatcher, stepArguments); - } else { - return stepTemplate(stepKeyword, stepMatcher, stepArguments); - } + const step = steps[stepPosition]; + const stepKeyword = getStepKeyword(steps, stepPosition); + const stepMatcher = getStepMatcher(step); + const stepArguments = getStepArguments(step); + + if (generateWrapperFunction) { + return stepWrapperFunctionTemplate(stepKeyword, step.stepText, stepMatcher, stepArguments); + } + return stepTemplate(stepKeyword, stepMatcher, stepArguments); }; export const generateStepFunctionCall = (steps: ParsedStep[], stepPosition: number) => { - const step = steps[stepPosition]; - const stepKeyword = getStepKeyword(steps, stepPosition); + const step = steps[stepPosition]; + const stepKeyword = getStepKeyword(steps, stepPosition); - return stepWrapperFunctionCallTemplate(step.stepText, stepKeyword); + return stepWrapperFunctionCallTemplate(step.stepText, stepKeyword); }; diff --git a/src/code-generation/utils.ts b/src/code-generation/utils.ts index e6ceb5d..1300bc0 100644 --- a/src/code-generation/utils.ts +++ b/src/code-generation/utils.ts @@ -2,14 +2,16 @@ export const indent = (stringToIndent: string, tabsToIndent: number) => { let tabs = ''; for (let i = 0; i < tabsToIndent; i++) { - tabs = tabs + '\t'; + tabs = `${tabs}\t`; } - return stringToIndent.split('\n').map((line) => { + return stringToIndent + .split('\n') + .map(line => { if (line !== '') { - return `${tabs}${line}\n`; - } else { - return '\n'; + return `${tabs}${line}\n`; } - }).join(''); + return '\n'; + }) + .join(''); }; diff --git a/src/configuration.ts b/src/configuration.ts index 0cc4066..f0cc989 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -1,47 +1,47 @@ export type ErrorOptions = { - scenariosMustMatchFeatureFile: boolean; - stepsMustMatchFeatureFile: boolean; - allowScenariosNotInFeatureFile: boolean; + scenariosMustMatchFeatureFile: boolean; + stepsMustMatchFeatureFile: boolean; + allowScenariosNotInFeatureFile: boolean; }; export type Options = { - loadRelativePath?: boolean; - tagFilter?: string; - errors?: ErrorOptions | boolean; - scenarioNameTemplate?: (vars: ScenarioNameTemplateVars) => string; + loadRelativePath?: boolean; + tagFilter?: string; + errors?: ErrorOptions | boolean; + scenarioNameTemplate?: (vars: ScenarioNameTemplateVars) => string; }; export type ScenarioNameTemplateVars = { - featureTitle: string; - scenarioTitle: string; - scenarioTags: string[]; - featureTags: string[]; + featureTitle: string; + scenarioTitle: string; + scenarioTags: string[]; + featureTags: string[]; }; export const defaultErrorSettings = { - scenariosMustMatchFeatureFile: true, - stepsMustMatchFeatureFile: true, - allowScenariosNotInFeatureFile: false, + scenariosMustMatchFeatureFile: true, + stepsMustMatchFeatureFile: true, + allowScenariosNotInFeatureFile: false, }; export const defaultConfiguration: Options = { - tagFilter: undefined, - scenarioNameTemplate: undefined, - errors: defaultErrorSettings, + tagFilter: undefined, + scenarioNameTemplate: undefined, + errors: defaultErrorSettings, }; let globalConfiguration: Options = {} as Options; export const getJestCucumberConfiguration = (options?: Options) => { - const mergedOptions = { ...defaultConfiguration, ...globalConfiguration, ...options || {} }; + const mergedOptions = { ...defaultConfiguration, ...globalConfiguration, ...(options || {}) }; - if (mergedOptions.errors === true) { - mergedOptions.errors = defaultErrorSettings; - } + if (mergedOptions.errors === true) { + mergedOptions.errors = defaultErrorSettings; + } - return mergedOptions; + return mergedOptions; }; export const setJestCucumberConfiguration = (options: Options) => { - globalConfiguration = options; + globalConfiguration = options; }; diff --git a/src/feature-definition-creation.ts b/src/feature-definition-creation.ts index 6900ad3..c045666 100644 --- a/src/feature-definition-creation.ts +++ b/src/feature-definition-creation.ts @@ -1,88 +1,93 @@ import { checkThatFeatureFileAndStepDefinitionsHaveSameScenarios } from './validation/scenario-validation'; import { - ScenarioFromStepDefinitions, - FeatureFromStepDefinitions, - StepFromStepDefinitions, - ParsedFeature, - ParsedScenario, - ParsedScenarioOutline, + ScenarioFromStepDefinitions, + FeatureFromStepDefinitions, + StepFromStepDefinitions, + ParsedFeature, + ParsedScenario, + ParsedScenarioOutline, } from './models'; import { - ensureFeatureFileAndStepDefinitionScenarioHaveSameSteps, - matchSteps, + ensureFeatureFileAndStepDefinitionScenarioHaveSameSteps, + matchSteps, } from './validation/step-definition-validation'; import { applyTagFilters } from './tag-filtering'; import { Options } from './configuration'; export type StepsDefinitionCallbackOptions = { - defineStep: DefineStepFunction; - given: DefineStepFunction; - when: DefineStepFunction; - then: DefineStepFunction; - and: DefineStepFunction; - but: DefineStepFunction; - pending: () => void; + defineStep: DefineStepFunction; + given: DefineStepFunction; + when: DefineStepFunction; + then: DefineStepFunction; + and: DefineStepFunction; + but: DefineStepFunction; + pending: () => void; }; export interface IJestLike { - describe: jest.Describe; - test: jest.It; + describe: jest.Describe; + test: jest.It; } export type ScenariosDefinitionCallbackFunction = (defineScenario: DefineScenarioFunctionWithAliases) => void; export type DefineScenarioFunction = ( - scenarioTitle: string, - stepsDefinitionCallback: StepsDefinitionCallbackFunction, - timeout?: number, + scenarioTitle: string, + stepsDefinitionCallback: StepsDefinitionCallbackFunction, + timeout?: number, ) => void; export type DefineScenarioFunctionWithAliases = DefineScenarioFunction & { - skip: DefineScenarioFunction; - only: DefineScenarioFunction; - concurrent: DefineScenarioFunction; + skip: DefineScenarioFunction; + only: DefineScenarioFunction; + concurrent: DefineScenarioFunction; }; export type StepsDefinitionCallbackFunction = (options: StepsDefinitionCallbackOptions) => void; +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type DefineStepFunction = (stepMatcher: string | RegExp, stepDefinitionCallback: (...args: any[]) => any) => any; export type DefineFeatureFunction = ( - featureFromFile: ParsedFeature, - scenariosDefinitionCallback: ScenariosDefinitionCallbackFunction, + featureFromFile: ParsedFeature, + scenariosDefinitionCallback: ScenariosDefinitionCallbackFunction, ) => void; export const createDefineFeature = (jestLike: IJestLike): DefineFeatureFunction => { - const processScenarioTitleTemplate = ( - scenarioTitle: string, - parsedFeature: ParsedFeature, - options: Options, - parsedScenario: ParsedScenario, - parsedScenarioOutline: ParsedScenarioOutline, - ) => { - if (options && options.scenarioNameTemplate) { - try { - return options && options.scenarioNameTemplate({ - featureTitle: parsedFeature.title, - scenarioTitle: scenarioTitle.toString(), - featureTags: parsedFeature.tags, - scenarioTags: (parsedScenario || parsedScenarioOutline).tags, - }); - } catch (err) { - throw new Error( - `An error occurred while executing a scenario name template. \nTemplate:\n${options.scenarioNameTemplate}\nError:${err.message}`, - ); - } - } + const processScenarioTitleTemplate = ( + scenarioTitle: string, + parsedFeature: ParsedFeature, + options: Options, + parsedScenario: ParsedScenario, + parsedScenarioOutline: ParsedScenarioOutline, + ) => { + if (options && options.scenarioNameTemplate) { + try { + return ( + options && + options.scenarioNameTemplate({ + featureTitle: parsedFeature.title, + scenarioTitle: scenarioTitle.toString(), + featureTags: parsedFeature.tags, + scenarioTags: (parsedScenario || parsedScenarioOutline).tags, + }) + ); + } catch (err) { + throw new Error( + `An error occurred while executing a scenario name template. \nTemplate:\n${options.scenarioNameTemplate}\nError:${err.message}`, + ); + } + } - return scenarioTitle; - }; + return scenarioTitle; + }; - const checkForPendingSteps = (scenarioFromStepDefinitions: ScenarioFromStepDefinitions) => { - let scenarioPending = false; + const checkForPendingSteps = (scenarioFromStepDefinitions: ScenarioFromStepDefinitions) => { + let scenarioPending = false; - scenarioFromStepDefinitions.steps.forEach((step) => { - try { - if (step.stepFunction.toString().indexOf('pending()') !== -1) { - const pendingTest = new Function(` + scenarioFromStepDefinitions.steps.forEach(step => { + try { + if (step.stepFunction.toString().indexOf('pending()') !== -1) { + // eslint-disable-next-line no-new-func + const pendingTest = new Function(` let isPending = false; const pending = function () { @@ -94,232 +99,231 @@ export const createDefineFeature = (jestLike: IJestLike): DefineFeatureFunction return isPending; `); - scenarioPending = pendingTest(); - } - } catch (err) { - // Ignore - } - }); - - return scenarioPending; - }; - - const getTestFunction = (skippedViaTagFilter: boolean, only: boolean, skip: boolean, concurrent: boolean) => { - if (skip || skippedViaTagFilter) { - return jestLike.test.skip; - } else if (only) { - return jestLike.test.only; - } else if (concurrent) { - return jestLike.test.concurrent; - } else { - return jestLike.test; + scenarioPending = pendingTest(); } + } catch (err) { + // Ignore + } + }); + + return scenarioPending; + }; + + const getTestFunction = (skippedViaTagFilter: boolean, only: boolean, skip: boolean, concurrent: boolean) => { + if (skip || skippedViaTagFilter) { + return jestLike.test.skip; + } + if (only) { + return jestLike.test.only; + } + if (concurrent) { + return jestLike.test.concurrent; + } + return jestLike.test; + }; + + const defineScenario = ( + scenarioTitle: string, + scenarioFromStepDefinitions: ScenarioFromStepDefinitions, + parsedScenario: ParsedScenario, + only: boolean = false, + skip: boolean = false, + + concurrent: boolean = false, + timeout: number | undefined = undefined, + ) => { + const testFunction = getTestFunction(parsedScenario.skippedViaTagFilter, only, skip, concurrent); + + testFunction( + scenarioTitle, + () => { + return scenarioFromStepDefinitions.steps.reduce((promiseChain, nextStep, index) => { + const parsedStep = parsedScenario.steps[index]; + const { stepArgument } = parsedStep; + const matches = matchSteps(parsedStep.stepText, scenarioFromStepDefinitions.steps[index].stepMatcher); + + let matchArgs: string[] = []; + + if (matches && (matches as RegExpMatchArray).length) { + matchArgs = (matches as RegExpMatchArray).slice(1); + } + + const args = [...matchArgs]; + + if (stepArgument !== undefined && stepArgument !== null) { + args.push(stepArgument as string); + } + + return promiseChain.then(() => { + return Promise.resolve() + .then(() => nextStep.stepFunction(...args)) + .catch(error => { + const formattedError = error; + formattedError.message = `Failing step: "${parsedStep.stepText}"\n\nStep arguments: ${JSON.stringify(args)}\n\nError: ${error.message}`; + throw formattedError; + }); + }); + }, Promise.resolve()); + }, + timeout, + ); + }; + + const createDefineStepFunction = (scenarioFromStepDefinitions: ScenarioFromStepDefinitions) => { + return (stepMatcher: string | RegExp, stepFunction: (stepArguments?: unknown) => void | PromiseLike) => { + const stepDefinition: StepFromStepDefinitions = { + stepMatcher, + stepFunction, + }; + + scenarioFromStepDefinitions.steps.push(stepDefinition); }; - - const defineScenario = ( - scenarioTitle: string, - scenarioFromStepDefinitions: ScenarioFromStepDefinitions, - parsedScenario: ParsedScenario, - only: boolean = false, - skip: boolean = false, - concurrent: boolean = false, - timeout: number | undefined = undefined, - ) => { - const testFunction = getTestFunction(parsedScenario.skippedViaTagFilter, only, skip, concurrent); - - testFunction(scenarioTitle, () => { - return scenarioFromStepDefinitions.steps.reduce((promiseChain, nextStep, index) => { - const parsedStep = parsedScenario.steps[index]; - const stepArgument = parsedStep.stepArgument; - const matches = matchSteps( - parsedStep.stepText, - scenarioFromStepDefinitions.steps[index].stepMatcher, - ); - - let matchArgs: string[] = []; - - if (matches && (matches as RegExpMatchArray).length) { - matchArgs = (matches as RegExpMatchArray).slice(1); - } - - const args = [...matchArgs]; - - if (stepArgument !== undefined && stepArgument !== null) { - args.push(stepArgument as string); - } - - return promiseChain.then(() => { - return Promise.resolve() - .then(() => nextStep.stepFunction(...args)) - .catch((error) => { - error.message = `Failing step: "${parsedStep.stepText}"\n\nStep arguments: ${JSON.stringify(args)}\n\nError: ${error.message}`; - throw error; - }); - }); - }, Promise.resolve()); - }, timeout); - }; - - const createDefineScenarioFunction = ( - featureFromStepDefinitions: FeatureFromStepDefinitions, - parsedFeature: ParsedFeature, - only: boolean = false, - skip: boolean = false, - concurrent: boolean = false, - ) => { - const defineScenarioFunction: DefineScenarioFunction = ( - scenarioTitle: string, - stepsDefinitionFunctionCallback: StepsDefinitionCallbackFunction, - timeout?: number, - ) => { - const scenarioFromStepDefinitions: ScenarioFromStepDefinitions = { - title: scenarioTitle, - steps: [], - }; - - featureFromStepDefinitions.scenarios.push(scenarioFromStepDefinitions); - - stepsDefinitionFunctionCallback({ - defineStep: createDefineStepFunction(scenarioFromStepDefinitions), - given: createDefineStepFunction(scenarioFromStepDefinitions), - when: createDefineStepFunction(scenarioFromStepDefinitions), - then: createDefineStepFunction(scenarioFromStepDefinitions), - and: createDefineStepFunction(scenarioFromStepDefinitions), - but: createDefineStepFunction(scenarioFromStepDefinitions), - pending: () => { - // Nothing to do - }, - }); - - const parsedScenario = parsedFeature.scenarios - .filter((s) => s.title.toLowerCase() === scenarioTitle.toLowerCase())[0]; - - const parsedScenarioOutline = parsedFeature.scenarioOutlines - .filter((s) => s.title.toLowerCase() === scenarioTitle.toLowerCase())[0]; - - const options = parsedFeature.options; - - scenarioTitle = processScenarioTitleTemplate( - scenarioTitle, - parsedFeature, - options, - parsedScenario, - parsedScenarioOutline, - ); - - ensureFeatureFileAndStepDefinitionScenarioHaveSameSteps( - options, - parsedScenario || parsedScenarioOutline, - scenarioFromStepDefinitions, - ); - - if (checkForPendingSteps(scenarioFromStepDefinitions)) { - xtest(scenarioTitle, () => { - // Nothing to do - }, undefined); - } else if (parsedScenario) { - defineScenario( - scenarioTitle, - scenarioFromStepDefinitions, - parsedScenario, - only, - skip, - concurrent, - timeout, - ); - } else if (parsedScenarioOutline) { - parsedScenarioOutline.scenarios.forEach((scenario) => { - defineScenario( - (scenario.title || scenarioTitle), - scenarioFromStepDefinitions, - scenario, - only, - skip, - concurrent, - timeout, - ); - }); - } - }; - - return defineScenarioFunction; - }; - - const createDefineScenarioFunctionWithAliases = ( - featureFromStepDefinitions: FeatureFromStepDefinitions, - parsedFeature: ParsedFeature, + }; + + const createDefineScenarioFunction = ( + featureFromStepDefinitions: FeatureFromStepDefinitions, + parsedFeature: ParsedFeature, + only: boolean = false, + skip: boolean = false, + concurrent: boolean = false, + ) => { + const defineScenarioFunction: DefineScenarioFunction = ( + scenarioTitle: string, + stepsDefinitionFunctionCallback: StepsDefinitionCallbackFunction, + timeout?: number, ) => { - const defineScenarioFunctionWithAliases = createDefineScenarioFunction( - featureFromStepDefinitions, - parsedFeature, + const scenarioFromStepDefinitions: ScenarioFromStepDefinitions = { + title: scenarioTitle, + steps: [], + }; + + featureFromStepDefinitions.scenarios.push(scenarioFromStepDefinitions); + + stepsDefinitionFunctionCallback({ + defineStep: createDefineStepFunction(scenarioFromStepDefinitions), + given: createDefineStepFunction(scenarioFromStepDefinitions), + when: createDefineStepFunction(scenarioFromStepDefinitions), + then: createDefineStepFunction(scenarioFromStepDefinitions), + and: createDefineStepFunction(scenarioFromStepDefinitions), + but: createDefineStepFunction(scenarioFromStepDefinitions), + pending: () => { + // Nothing to do + }, + }); + + const parsedScenario = parsedFeature.scenarios.filter( + s => s.title.toLowerCase() === scenarioTitle.toLowerCase(), + )[0]; + + const parsedScenarioOutline = parsedFeature.scenarioOutlines.filter( + s => s.title.toLowerCase() === scenarioTitle.toLowerCase(), + )[0]; + + const { options } = parsedFeature; + + // eslint-disable-next-line no-param-reassign + scenarioTitle = processScenarioTitleTemplate( + scenarioTitle, + parsedFeature, + options, + parsedScenario, + parsedScenarioOutline, + ); + + ensureFeatureFileAndStepDefinitionScenarioHaveSameSteps( + options, + parsedScenario || parsedScenarioOutline, + scenarioFromStepDefinitions, + ); + + if (checkForPendingSteps(scenarioFromStepDefinitions)) { + xtest( + scenarioTitle, + () => { + // Nothing to do + }, + undefined, ); - - (defineScenarioFunctionWithAliases as DefineScenarioFunctionWithAliases).only = createDefineScenarioFunction( - featureFromStepDefinitions, - parsedFeature, - true, - false, - false, - ); - - (defineScenarioFunctionWithAliases as DefineScenarioFunctionWithAliases).skip = createDefineScenarioFunction( - featureFromStepDefinitions, - parsedFeature, - false, - true, - false, - ); - - (defineScenarioFunctionWithAliases as DefineScenarioFunctionWithAliases).concurrent = - createDefineScenarioFunction( - featureFromStepDefinitions, - parsedFeature, - false, - false, - true, - ); - - return defineScenarioFunctionWithAliases as DefineScenarioFunctionWithAliases; + } else if (parsedScenario) { + defineScenario(scenarioTitle, scenarioFromStepDefinitions, parsedScenario, only, skip, concurrent, timeout); + } else if (parsedScenarioOutline) { + parsedScenarioOutline.scenarios.forEach(scenario => { + defineScenario( + scenario.title || scenarioTitle, + scenarioFromStepDefinitions, + scenario, + only, + skip, + concurrent, + timeout, + ); + }); + } }; - const createDefineStepFunction = (scenarioFromStepDefinitions: ScenarioFromStepDefinitions) => { - return (stepMatcher: string | RegExp, stepFunction: () => any) => { - const stepDefinition: StepFromStepDefinitions = { - stepMatcher, - stepFunction, - }; - - scenarioFromStepDefinitions.steps.push(stepDefinition); - }; + return defineScenarioFunction; + }; + + const createDefineScenarioFunctionWithAliases = ( + featureFromStepDefinitions: FeatureFromStepDefinitions, + parsedFeature: ParsedFeature, + ) => { + const defineScenarioFunctionWithAliases = createDefineScenarioFunction(featureFromStepDefinitions, parsedFeature); + + (defineScenarioFunctionWithAliases as DefineScenarioFunctionWithAliases).only = createDefineScenarioFunction( + featureFromStepDefinitions, + parsedFeature, + true, + false, + false, + ); + + (defineScenarioFunctionWithAliases as DefineScenarioFunctionWithAliases).skip = createDefineScenarioFunction( + featureFromStepDefinitions, + parsedFeature, + false, + true, + false, + ); + + (defineScenarioFunctionWithAliases as DefineScenarioFunctionWithAliases).concurrent = createDefineScenarioFunction( + featureFromStepDefinitions, + parsedFeature, + false, + false, + true, + ); + + return defineScenarioFunctionWithAliases as DefineScenarioFunctionWithAliases; + }; + + return function defineFeature( + featureFromFile: ParsedFeature, + scenariosDefinitionCallback: ScenariosDefinitionCallbackFunction, + ) { + const featureFromDefinedSteps: FeatureFromStepDefinitions = { + title: featureFromFile.title, + scenarios: [], }; - return function defineFeature( - featureFromFile: ParsedFeature, - scenariosDefinitionCallback: ScenariosDefinitionCallbackFunction, - ) { - const featureFromDefinedSteps: FeatureFromStepDefinitions = { - title: featureFromFile.title, - scenarios: [], - }; - - const parsedFeatureWithTagFiltersApplied = applyTagFilters(featureFromFile); - - if ( - parsedFeatureWithTagFiltersApplied.scenarios.length === 0 - && parsedFeatureWithTagFiltersApplied.scenarioOutlines.length === 0 - ) { - return; - } + const parsedFeatureWithTagFiltersApplied = applyTagFilters(featureFromFile); - jestLike.describe(featureFromFile.title, () => { - scenariosDefinitionCallback( - createDefineScenarioFunctionWithAliases(featureFromDefinedSteps, parsedFeatureWithTagFiltersApplied), - ); - - checkThatFeatureFileAndStepDefinitionsHaveSameScenarios( - parsedFeatureWithTagFiltersApplied, - featureFromDefinedSteps, - ); - }); - }; + if ( + parsedFeatureWithTagFiltersApplied.scenarios.length === 0 && + parsedFeatureWithTagFiltersApplied.scenarioOutlines.length === 0 + ) { + return; + } + + jestLike.describe(featureFromFile.title, () => { + scenariosDefinitionCallback( + createDefineScenarioFunctionWithAliases(featureFromDefinedSteps, parsedFeatureWithTagFiltersApplied), + ); + + checkThatFeatureFileAndStepDefinitionsHaveSameScenarios( + parsedFeatureWithTagFiltersApplied, + featureFromDefinedSteps, + ); + }); + }; }; diff --git a/src/index.ts b/src/index.ts index 4e0ac8d..7264f70 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,6 @@ +import { createDefineFeature, IJestLike } from './feature-definition-creation'; +import { createAutoBindSteps } from './automatic-step-binding'; + export { loadFeature, loadFeatures, parseFeature } from './parsed-feature-loading'; export { DefineStepFunction } from './feature-definition-creation'; export { setJestCucumberConfiguration } from './configuration'; @@ -7,9 +10,6 @@ export { } from './code-generation/generate-code-by-line-number'; export { StepsDefinitionCallbackFunction as StepDefinitions, IJestLike } from './feature-definition-creation'; -import { createDefineFeature, IJestLike } from './feature-definition-creation'; -import { createAutoBindSteps } from './automatic-step-binding'; - const jestLike: IJestLike = { describe, test, diff --git a/src/models.ts b/src/models.ts index ba358ae..dea109d 100644 --- a/src/models.ts +++ b/src/models.ts @@ -1,48 +1,48 @@ import { Options } from './configuration'; export type StepFromStepDefinitions = { - stepMatcher: string | RegExp; - stepFunction(stepArguments?: any): void | PromiseLike; + stepMatcher: string | RegExp; + stepFunction(stepArguments?: unknown): void | PromiseLike; }; export type ScenarioFromStepDefinitions = { - title: string; - steps: StepFromStepDefinitions[]; + title: string; + steps: StepFromStepDefinitions[]; }; export type FeatureFromStepDefinitions = { - title: string; - scenarios: ScenarioFromStepDefinitions[]; + title: string; + scenarios: ScenarioFromStepDefinitions[]; }; export type ParsedStep = { - keyword: string; - stepText: string; - stepArgument: string | {}; - lineNumber: number; + keyword: string; + stepText: string; + stepArgument: string | NonNullable; + lineNumber: number; }; export type ParsedScenario = { - title: string; - steps: ParsedStep[]; - tags: string[]; - lineNumber: number; - skippedViaTagFilter: boolean; + title: string; + steps: ParsedStep[]; + tags: string[]; + lineNumber: number; + skippedViaTagFilter: boolean; }; export type ParsedScenarioOutline = { - title: string; - tags: string[]; - scenarios: ParsedScenario[]; - steps: ParsedStep[]; - lineNumber: number; - skippedViaTagFilter: boolean; + title: string; + tags: string[]; + scenarios: ParsedScenario[]; + steps: ParsedStep[]; + lineNumber: number; + skippedViaTagFilter: boolean; }; export type ParsedFeature = { - title: string; - scenarios: ParsedScenario[]; - scenarioOutlines: ParsedScenarioOutline[]; - options: Options; - tags: string[]; + title: string; + scenarios: ParsedScenario[]; + scenarioOutlines: ParsedScenarioOutline[]; + options: Options; + tags: string[]; }; diff --git a/src/parsed-feature-loading.ts b/src/parsed-feature-loading.ts index 19e070e..bfb8b58 100644 --- a/src/parsed-feature-loading.ts +++ b/src/parsed-feature-loading.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { readFileSync } from 'fs'; import { sync as globSync } from 'glob'; import { dirname, resolve } from 'path'; @@ -9,375 +10,359 @@ import { getJestCucumberConfiguration, Options } from './configuration'; import { ParsedFeature, ParsedScenario, ParsedStep, ParsedScenarioOutline } from './models'; const parseDataTableRow = (astDataTableRow: any) => { - return astDataTableRow.cells.map((col: any) => col.value) as string[]; + return astDataTableRow.cells.map((col: any) => col.value) as string[]; }; const parseDataTable = (astDataTable: any, astDataTableHeader?: any) => { - let headerRow: string[]; - let bodyRows: string[]; - - if (astDataTableHeader) { - headerRow = parseDataTableRow(astDataTableHeader); - bodyRows = astDataTable; - } else { - headerRow = parseDataTableRow(astDataTable.rows[0]); - bodyRows = astDataTable && astDataTable.rows && astDataTable.rows.length && astDataTable.rows.slice(1); - } - - if (bodyRows && bodyRows.length > 0) { - return bodyRows.map((nextRow) => { - const parsedRow = parseDataTableRow(nextRow); - - return parsedRow.reduce((rowObj, nextCol, index) => { - return { - ...rowObj, - [headerRow[index]]: nextCol, - }; - }, {}); - }); - } else { - return []; - } + let headerRow: string[]; + let bodyRows: string[]; + + if (astDataTableHeader) { + headerRow = parseDataTableRow(astDataTableHeader); + bodyRows = astDataTable; + } else { + headerRow = parseDataTableRow(astDataTable.rows[0]); + bodyRows = astDataTable && astDataTable.rows && astDataTable.rows.length && astDataTable.rows.slice(1); + } + + if (bodyRows && bodyRows.length > 0) { + return bodyRows.map(nextRow => { + const parsedRow = parseDataTableRow(nextRow); + + return parsedRow.reduce((rowObj, nextCol, index) => { + return { + ...rowObj, + [headerRow[index]]: nextCol, + }; + }, {}); + }); + } + return []; }; const parseStepArgument = (astStep: any) => { - if (astStep) { - switch (astStep.argument) { - case 'dataTable': - return parseDataTable(astStep.dataTable); - case 'docString': - return astStep.docString.content; - default: - return null; - } - } else { + if (astStep) { + switch (astStep.argument) { + case 'dataTable': + return parseDataTable(astStep.dataTable); + case 'docString': + return astStep.docString.content; + default: return null; } + } else { + return null; + } }; const parseStep = (astStep: any) => { - return { - stepText: astStep.text, - keyword: (astStep.keyword).trim().toLowerCase() as string, - stepArgument: parseStepArgument(astStep), - lineNumber: astStep.location.line, - } as ParsedStep; + return { + stepText: astStep.text, + keyword: astStep.keyword.trim().toLowerCase() as string, + stepArgument: parseStepArgument(astStep), + lineNumber: astStep.location.line, + } as ParsedStep; }; const parseSteps = (astScenario: any) => { - return astScenario.steps.map((astStep: any) => parseStep(astStep)); + return astScenario.steps.map((astStep: any) => parseStep(astStep)); }; const parseTags = (ast: any) => { - if (!ast.tags) { - return [] as string[]; - } else { - return ast.tags.map((tag: any) => tag.name.toLowerCase()); - } + if (!ast.tags) { + return [] as string[]; + } + return ast.tags.map((tag: any) => tag.name.toLowerCase()); }; const parseScenario = (astScenario: any) => { - return { - title: astScenario.name, - steps: parseSteps(astScenario), - tags: parseTags(astScenario), - lineNumber: astScenario.location.line, - } as ParsedScenario; + return { + title: astScenario.name, + steps: parseSteps(astScenario), + tags: parseTags(astScenario), + lineNumber: astScenario.location.line, + } as ParsedScenario; }; const parseScenarioOutlineExampleSteps = (exampleTableRow: any, scenarioSteps: ParsedStep[]) => { - return scenarioSteps.map((scenarioStep) => { - const stepText = Object.keys(exampleTableRow).reduce((processedStepText, nextTableColumn) => { - return processedStepText.replace(new RegExp(`<${nextTableColumn}>`, 'g'), exampleTableRow[nextTableColumn]); - }, scenarioStep.stepText); - - let stepArgument: string | {} = ''; - - if (scenarioStep.stepArgument) { - if (Array.isArray(scenarioStep.stepArgument)) { - stepArgument = (scenarioStep.stepArgument as any).map((stepArgumentRow: any) => { - const modifiedStepArgumentRow = { ...stepArgumentRow }; - - Object.keys(exampleTableRow).forEach((nextTableColumn) => { - Object.keys(modifiedStepArgumentRow).forEach((prop) => { - modifiedStepArgumentRow[prop] = - modifiedStepArgumentRow[prop].replace( - new RegExp(`<${nextTableColumn}>`, 'g'), - exampleTableRow[nextTableColumn], - ); - }); - }); - - return modifiedStepArgumentRow; - }); - } else { - stepArgument = scenarioStep.stepArgument; - - if ( - typeof scenarioStep.stepArgument === 'string' || - scenarioStep.stepArgument instanceof String - ) { - Object.keys(exampleTableRow).forEach((nextTableColumn) => { - stepArgument = (stepArgument as string).replace( - new RegExp(`<${nextTableColumn}>`, 'g'), - exampleTableRow[nextTableColumn], - ); - }); - } - } + return scenarioSteps.map(scenarioStep => { + const stepText = Object.keys(exampleTableRow).reduce((processedStepText, nextTableColumn) => { + return processedStepText.replace(new RegExp(`<${nextTableColumn}>`, 'g'), exampleTableRow[nextTableColumn]); + }, scenarioStep.stepText); + + let stepArgument: string | NonNullable = ''; + + if (scenarioStep.stepArgument) { + if (Array.isArray(scenarioStep.stepArgument)) { + stepArgument = (scenarioStep.stepArgument as any).map((stepArgumentRow: any) => { + const modifiedStepArgumentRow = { ...stepArgumentRow }; + + Object.keys(exampleTableRow).forEach(nextTableColumn => { + Object.keys(modifiedStepArgumentRow).forEach(prop => { + modifiedStepArgumentRow[prop] = modifiedStepArgumentRow[prop].replace( + new RegExp(`<${nextTableColumn}>`, 'g'), + exampleTableRow[nextTableColumn], + ); + }); + }); + + return modifiedStepArgumentRow; + }); + } else { + stepArgument = scenarioStep.stepArgument; + + if (typeof scenarioStep.stepArgument === 'string' || scenarioStep.stepArgument instanceof String) { + Object.keys(exampleTableRow).forEach(nextTableColumn => { + stepArgument = (stepArgument as string).replace( + new RegExp(`<${nextTableColumn}>`, 'g'), + exampleTableRow[nextTableColumn], + ); + }); } + } + } - return { - ...scenarioStep, - stepText, - stepArgument, - } as ParsedStep; - }); + return { + ...scenarioStep, + stepText, + stepArgument, + } as ParsedStep; + }); }; const getOutlineDynamicTitle = (exampleTableRow: any, title: string) => { - return title.replace(/<(\S*)>/g, (_, firstMatch) => { - return exampleTableRow[firstMatch || '']; - }); + return title.replace(/<(\S*)>/g, (_, firstMatch) => { + return exampleTableRow[firstMatch || '']; + }); }; const parseScenarioOutlineExample = ( - exampleTableRow: any, - outlineScenario: ParsedScenario, - exampleSetTags: string[], + exampleTableRow: any, + outlineScenario: ParsedScenario, + exampleSetTags: string[], ) => { - return { - title: getOutlineDynamicTitle(exampleTableRow, outlineScenario.title), - steps: parseScenarioOutlineExampleSteps(exampleTableRow, outlineScenario.steps), - tags: Array.from(new Set([...outlineScenario.tags, ...exampleSetTags])), - } as ParsedScenario; + return { + title: getOutlineDynamicTitle(exampleTableRow, outlineScenario.title), + steps: parseScenarioOutlineExampleSteps(exampleTableRow, outlineScenario.steps), + tags: Array.from(new Set([...outlineScenario.tags, ...exampleSetTags])), + } as ParsedScenario; }; const parseScenarioOutlineExampleSet = (astExampleSet: any, outlineScenario: ParsedScenario) => { - const exampleTable = parseDataTable(astExampleSet.tableBody, astExampleSet.tableHeader); + const exampleTable = parseDataTable(astExampleSet.tableBody, astExampleSet.tableHeader); - return exampleTable.map( - (tableRow) => parseScenarioOutlineExample(tableRow, outlineScenario, parseTags(astExampleSet)), - ); + return exampleTable.map(tableRow => parseScenarioOutlineExample(tableRow, outlineScenario, parseTags(astExampleSet))); }; const parseScenarioOutlineExampleSets = (astExampleSets: any, outlineScenario: ParsedScenario) => { - const exampleSets = astExampleSets.map((astExampleSet: any) => { - return parseScenarioOutlineExampleSet(astExampleSet, outlineScenario); - }); + const exampleSets = astExampleSets.map((astExampleSet: any) => { + return parseScenarioOutlineExampleSet(astExampleSet, outlineScenario); + }); - return exampleSets.reduce((scenarios: ParsedScenario[], nextExampleSet: ParsedScenario[][]) => { - return [ - ...scenarios, - ...nextExampleSet, - ]; - }, [] as ParsedScenario[]); + return exampleSets.reduce((scenarios: ParsedScenario[], nextExampleSet: ParsedScenario[][]) => { + return [...scenarios, ...nextExampleSet]; + }, [] as ParsedScenario[]); }; const parseScenarioOutline = (astScenarioOutline: any) => { - const outlineScenario = parseScenario(astScenarioOutline.scenario); - - return { - title: outlineScenario.title, - scenarios: parseScenarioOutlineExampleSets(astScenarioOutline.scenario.examples, outlineScenario), - tags: outlineScenario.tags, - steps: outlineScenario.steps, - lineNumber: astScenarioOutline.scenario.location.line, - } as ParsedScenarioOutline; + const outlineScenario = parseScenario(astScenarioOutline.scenario); + + return { + title: outlineScenario.title, + scenarios: parseScenarioOutlineExampleSets(astScenarioOutline.scenario.examples, outlineScenario), + tags: outlineScenario.tags, + steps: outlineScenario.steps, + lineNumber: astScenarioOutline.scenario.location.line, + } as ParsedScenarioOutline; }; const parseScenarios = (astFeature: any) => { - return astFeature.children - .filter((child: any) => { - const keywords = ['Scenario Outline', 'Scenario Template']; + return astFeature.children + .filter((child: any) => { + const keywords = ['Scenario Outline', 'Scenario Template']; - return child.scenario && keywords.indexOf(child.scenario.keyword) === -1; - }) - .map((astScenario: any) => parseScenario(astScenario.scenario)); + return child.scenario && keywords.indexOf(child.scenario.keyword) === -1; + }) + .map((astScenario: any) => parseScenario(astScenario.scenario)); }; const parseScenarioOutlines = (astFeature: any) => { - return astFeature.children - .filter((child: any) => { - const keywords = ['Scenario Outline', 'Scenario Template']; + return astFeature.children + .filter((child: any) => { + const keywords = ['Scenario Outline', 'Scenario Template']; - return child.scenario && keywords.indexOf(child.scenario.keyword) !== -1; - }) - .map((astScenarioOutline: any) => parseScenarioOutline(astScenarioOutline)); + return child.scenario && keywords.indexOf(child.scenario.keyword) !== -1; + }) + .map((astScenarioOutline: any) => parseScenarioOutline(astScenarioOutline)); }; const collapseBackgrounds = (astChildren: any[], backgrounds: any[]) => { - const backgroundSteps = backgrounds - .reduce((allBackgroundSteps, nextBackground) => { - return [ - ...allBackgroundSteps, - ...nextBackground.steps, - ]; - }, []); - - astChildren.forEach((child) => { - if (child.scenario) { - child.scenario.steps = [...backgroundSteps, ...child.scenario.steps]; - } - }); - - return astChildren; + const backgroundSteps = backgrounds.reduce((allBackgroundSteps, nextBackground) => { + return [...allBackgroundSteps, ...nextBackground.steps]; + }, []); + + return astChildren.map(child => { + const newChild = { ...child }; + if (newChild.scenario) { + newChild.scenario.steps = [...backgroundSteps, ...newChild.scenario.steps]; + } + return newChild; + }); }; const parseBackgrounds = (ast: any) => { - return ast.children - .filter((child: any) => child.background) - .map((child: any) => child.background); + return ast.children.filter((child: any) => child.background).map((child: any) => child.background); }; const collapseRulesAndBackgrounds = (astFeature: any) => { - const featureBackgrounds = parseBackgrounds(astFeature); - - const children = collapseBackgrounds(astFeature.children, featureBackgrounds) - .reduce((newChildren: [], nextChild: any) => { - if (nextChild.rule) { - const rule = nextChild.rule; - const ruleBackgrounds = parseBackgrounds(rule); - - return [ - ...newChildren, - ...collapseBackgrounds(rule.children, [...featureBackgrounds, ...ruleBackgrounds]), - ]; - } else { - return [...newChildren, nextChild]; - } - }, []); - - return { - ...astFeature, - children, - }; + const featureBackgrounds = parseBackgrounds(astFeature); + + const children = collapseBackgrounds(astFeature.children, featureBackgrounds).reduce( + (newChildren: [], nextChild: any) => { + if (nextChild.rule) { + const { rule } = nextChild; + const ruleBackgrounds = parseBackgrounds(rule); + + return [...newChildren, ...collapseBackgrounds(rule.children, [...featureBackgrounds, ...ruleBackgrounds])]; + } + return [...newChildren, nextChild]; + }, + [], + ); + + return { + ...astFeature, + children, + }; }; -const translateKeywords = (astFeature: any) => { - const languageDialect = dialects[astFeature.language]; - const translationMap = createTranslationMap(languageDialect); - - astFeature.language = 'en'; - astFeature.keyword = translationMap[astFeature.keyword] || astFeature.keyword; - - for (const child of astFeature.children) { - if (child.background) { - child.background.keyword = translationMap[child.background.keyword] || child.background.keyword; +const createTranslationMap = (translateDialect: Dialect) => { + const englishDialect = dialects.en; + const translationMap: { [word: string]: string } = {}; + + const props: Array = [ + 'and', + 'background', + 'but', + 'examples', + 'feature', + 'given', + 'scenario', + 'scenarioOutline', + 'then', + 'when', + 'rule', + ]; + + // eslint-disable-next-line no-restricted-syntax + for (const prop of props) { + const dialectWords = translateDialect[prop]; + const translationWords = englishDialect[prop]; + let index = 0; + let defaultWordIndex: number | null = null; + + // eslint-disable-next-line no-restricted-syntax + for (const dialectWord of dialectWords) { + // skip "* " word + if (dialectWord.indexOf('*') !== 0) { + if (translationWords[index] !== undefined) { + translationMap[dialectWord] = translationWords[index]; + if (defaultWordIndex === null) { + // set default when non is set yet + defaultWordIndex = index; + } + } else if (defaultWordIndex !== null) { + translationMap[dialectWord] = translationWords[defaultWordIndex]; + } else { + throw new Error(`No translation found for ${dialectWord}`); } + } - if (child.scenario) { - child.scenario.keyword = translationMap[child.scenario.keyword] || child.scenario.keyword; - - for (const step of child.scenario.steps) { - step.keyword = translationMap[step.keyword] || step.keyword; - } - - for (const example of child.scenario.examples) { - example.keyword = translationMap[example.keyword] || example.keyword; - } - } + index += 1; } + } - return astFeature; + return translationMap; }; -const createTranslationMap = (translateDialect: Dialect) => { - const englishDialect = dialects.en; - const translationMap: { [word: string]: string } = {}; - - const props: Array = [ - 'and', - 'background', - 'but', - 'examples', - 'feature', - 'given', - 'scenario', - 'scenarioOutline', - 'then', - 'when', - 'rule', - ]; - - for (const prop of props) { - const dialectWords = translateDialect[prop]; - const translationWords = englishDialect[prop]; - let index = 0; - let defaultWordIndex: number | null = null; - - for (const dialectWord of dialectWords) { - // skip "* " word - if (dialectWord.indexOf('*') !== 0) { - if (translationWords[index] !== undefined) { - translationMap[dialectWord] = translationWords[index]; - if (defaultWordIndex === null) { - // set default when non is set yet - defaultWordIndex = index; - } - } else { - // index has undefined value, translate to default word - if (defaultWordIndex !== null) { - translationMap[dialectWord] = translationWords[defaultWordIndex]; - } else { - throw new Error('No translation found for ' + dialectWord); - } - } - } - - index++; - } +const translateKeywords = (astFeature: any) => { + const languageDialect = dialects[astFeature.language]; + const translationMap = createTranslationMap(languageDialect); + + // eslint-disable-next-line no-param-reassign + astFeature.language = 'en'; + // eslint-disable-next-line no-param-reassign + astFeature.keyword = translationMap[astFeature.keyword] || astFeature.keyword; + + // eslint-disable-next-line no-restricted-syntax + for (const child of astFeature.children) { + if (child.background) { + child.background.keyword = translationMap[child.background.keyword] || child.background.keyword; } - return translationMap; -}; - -export const parseFeature = (featureText: string, options?: Options): ParsedFeature => { - let ast: any; - options = getJestCucumberConfiguration(options); - - try { - const builder = new AstBuilder(uuidv4 as any); - ast = new Parser(builder).parse(featureText); - } catch (err) { - throw new Error(`Error parsing feature Gherkin: ${err.message}`); - } + if (child.scenario) { + child.scenario.keyword = translationMap[child.scenario.keyword] || child.scenario.keyword; - let astFeature = collapseRulesAndBackgrounds(ast.feature); + // eslint-disable-next-line no-restricted-syntax + for (const step of child.scenario.steps) { + step.keyword = translationMap[step.keyword] || step.keyword; + } - if (astFeature.language !== 'en') { - astFeature = translateKeywords(astFeature); + // eslint-disable-next-line no-restricted-syntax + for (const example of child.scenario.examples) { + example.keyword = translationMap[example.keyword] || example.keyword; + } } + } - return { - title: astFeature.name, - scenarios: parseScenarios(astFeature), - scenarioOutlines: parseScenarioOutlines(astFeature), - tags: parseTags(astFeature), - options, - } as ParsedFeature; + return astFeature; }; -export const loadFeature = (featureFilePath: string, options?: Options) => { - const callSite = callsites()[1]; - const fileOfCaller = callSite && callSite.getFileName() || ''; - const dirOfCaller = dirname(fileOfCaller); - const absoluteFeatureFilePath = resolve(options && options.loadRelativePath ? dirOfCaller : '', featureFilePath); - - try { - const featureText: string = readFileSync(absoluteFeatureFilePath, 'utf8'); - return parseFeature(featureText, options); - } catch (err) { - if (err.code === 'ENOENT') { - throw new Error(`Feature file not found (${absoluteFeatureFilePath})`); - } +export const parseFeature = (featureText: string, options?: Options): ParsedFeature => { + let ast: any; + + try { + const builder = new AstBuilder(uuidv4 as any); + ast = new Parser(builder).parse(featureText); + } catch (err) { + throw new Error(`Error parsing feature Gherkin: ${err.message}`); + } + + let astFeature = collapseRulesAndBackgrounds(ast.feature); + + if (astFeature.language !== 'en') { + astFeature = translateKeywords(astFeature); + } + + return { + title: astFeature.name, + scenarios: parseScenarios(astFeature), + scenarioOutlines: parseScenarioOutlines(astFeature), + tags: parseTags(astFeature), + options: getJestCucumberConfiguration(options), + } as ParsedFeature; +}; - throw err; +export const loadFeature = (featureFilePath: string, options?: Options) => { + const callSite = callsites()[1]; + const fileOfCaller = (callSite && callSite.getFileName()) || ''; + const dirOfCaller = dirname(fileOfCaller); + const absoluteFeatureFilePath = resolve(options && options.loadRelativePath ? dirOfCaller : '', featureFilePath); + + try { + const featureText: string = readFileSync(absoluteFeatureFilePath, 'utf8'); + return parseFeature(featureText, options); + } catch (err) { + if (err.code === 'ENOENT') { + throw new Error(`Feature file not found (${absoluteFeatureFilePath})`); } + + throw err; + } }; export const loadFeatures = (globPattern: string, options?: Options) => { - const featureFiles = globSync(globPattern); + const featureFiles = globSync(globPattern); - return featureFiles.map((featureFilePath) => loadFeature(featureFilePath, options)); + return featureFiles.map(featureFilePath => loadFeature(featureFilePath, options)); }; diff --git a/src/tag-filtering.ts b/src/tag-filtering.ts index e27b52d..babc087 100644 --- a/src/tag-filtering.ts +++ b/src/tag-filtering.ts @@ -5,92 +5,93 @@ type TagFilterFunction = (tags: string[]) => boolean; const cachedTagFilterFunctions: { [tag: string]: TagFilterFunction } = {}; const convertTagFilterExpressionToFunction = (tagFilterExpression: string) => { - const tagRegex = /(\@[A-Za-z-_0-9]+)/g; - const tags: string[] = []; - let match: RegExpMatchArray | null = null; - let newTagFilterExpression = tagFilterExpression + ''; - - do { - match = tagRegex.exec(tagFilterExpression); - - if (match) { - newTagFilterExpression = newTagFilterExpression.replace(match[1], `(tags.indexOf("${match[1].toLowerCase()}")!==-1)`); - - if (tags.indexOf(match[1]) !== -1) { - tags.push(match[1]); - } - } - } while (match); - - newTagFilterExpression = newTagFilterExpression.replace(/(\s+not|not\s+|\s+not\s+)/g, ' ! '); - newTagFilterExpression = newTagFilterExpression.replace(/(\s+or|or\s+|\s+or\s+)/g, ' || '); - newTagFilterExpression = newTagFilterExpression.replace(/(\s+and|and\s+|\s+and\s+)/g, ' && '); - newTagFilterExpression = newTagFilterExpression.replace(/[ \t\n\r]+/g, ''); - - let tagFilterFunction: TagFilterFunction; - - try { - tagFilterFunction = new Function('tags', `return ${newTagFilterExpression};`) as TagFilterFunction; - tagFilterFunction([]); - } catch (error) { - throw new Error(`Could not parse tag filter "${tagFilterExpression}"`); + const tagRegex = /(@[A-Za-z-_0-9]+)/g; + const tags: string[] = []; + let match: RegExpMatchArray | null = null; + let newTagFilterExpression = `${tagFilterExpression}`; + + do { + match = tagRegex.exec(tagFilterExpression); + + if (match) { + newTagFilterExpression = newTagFilterExpression.replace( + match[1], + `(tags.indexOf("${match[1].toLowerCase()}")!==-1)`, + ); + + if (tags.indexOf(match[1]) !== -1) { + tags.push(match[1]); + } } + } while (match); - return tagFilterFunction; + newTagFilterExpression = newTagFilterExpression.replace(/(\s+not|not\s+|\s+not\s+)/g, ' ! '); + newTagFilterExpression = newTagFilterExpression.replace(/(\s+or|or\s+|\s+or\s+)/g, ' || '); + newTagFilterExpression = newTagFilterExpression.replace(/(\s+and|and\s+|\s+and\s+)/g, ' && '); + newTagFilterExpression = newTagFilterExpression.replace(/[ \t\n\r]+/g, ''); + + let tagFilterFunction: TagFilterFunction; + + try { + // eslint-disable-next-line no-new-func + tagFilterFunction = new Function('tags', `return ${newTagFilterExpression};`) as TagFilterFunction; + tagFilterFunction([]); + } catch (error) { + throw new Error(`Could not parse tag filter "${tagFilterExpression}"`); + } + + return tagFilterFunction; }; const checkIfScenarioMatchesTagFilter = ( - tagFilterExpression: string, - feature: ParsedFeature, - scenario: ParsedScenario | ParsedScenarioOutline, + tagFilterExpression: string, + feature: ParsedFeature, + scenario: ParsedScenario | ParsedScenarioOutline, ) => { - const featureAndScenarioTags = [ - ...scenario.tags.map((tag) => tag.toLowerCase()), - ...feature.tags.map((tag) => tag.toLowerCase()), - ]; + const featureAndScenarioTags = [ + ...scenario.tags.map(tag => tag.toLowerCase()), + ...feature.tags.map(tag => tag.toLowerCase()), + ]; - let tagFilterFunction = cachedTagFilterFunctions[tagFilterExpression]; + let tagFilterFunction = cachedTagFilterFunctions[tagFilterExpression]; - if (!tagFilterFunction) { - tagFilterFunction = convertTagFilterExpressionToFunction(tagFilterExpression); - cachedTagFilterFunctions[tagFilterExpression] = tagFilterFunction; - } + if (!tagFilterFunction) { + tagFilterFunction = convertTagFilterExpressionToFunction(tagFilterExpression); + cachedTagFilterFunctions[tagFilterExpression] = tagFilterFunction; + } - return tagFilterFunction(featureAndScenarioTags); + return tagFilterFunction(featureAndScenarioTags); }; const setScenarioSkipped = (parsedFeature: ParsedFeature, scenario: ParsedScenario) => { - const skippedViaTagFilter = !checkIfScenarioMatchesTagFilter( - parsedFeature.options.tagFilter as string, - parsedFeature, - scenario, - ); - - return { - ...scenario, - skippedViaTagFilter, - }; + const skippedViaTagFilter = !checkIfScenarioMatchesTagFilter( + parsedFeature.options.tagFilter as string, + parsedFeature, + scenario, + ); + + return { + ...scenario, + skippedViaTagFilter, + }; }; -export const applyTagFilters = ( - parsedFeature: ParsedFeature, -) => { - if (parsedFeature.options.tagFilter === undefined) { - return parsedFeature; - } - - const scenarios = parsedFeature.scenarios.map((scenario) => setScenarioSkipped(parsedFeature, scenario)); - const scenarioOutlines = parsedFeature.scenarioOutlines - .map((scenarioOutline) => { - return { - ...setScenarioSkipped(parsedFeature, scenarioOutline), - scenarios: scenarioOutline.scenarios.map((scenario) => setScenarioSkipped(parsedFeature, scenario)), - }; - }); +export const applyTagFilters = (parsedFeature: ParsedFeature) => { + if (parsedFeature.options.tagFilter === undefined) { + return parsedFeature; + } + const scenarios = parsedFeature.scenarios.map(scenario => setScenarioSkipped(parsedFeature, scenario)); + const scenarioOutlines = parsedFeature.scenarioOutlines.map(scenarioOutline => { return { - ...parsedFeature, - scenarios, - scenarioOutlines, - } as ParsedFeature; + ...setScenarioSkipped(parsedFeature, scenarioOutline), + scenarios: scenarioOutline.scenarios.map(scenario => setScenarioSkipped(parsedFeature, scenario)), + }; + }); + + return { + ...parsedFeature, + scenarios, + scenarioOutlines, + } as ParsedFeature; }; diff --git a/src/validation/scenario-validation.ts b/src/validation/scenario-validation.ts index b20d524..cc27268 100644 --- a/src/validation/scenario-validation.ts +++ b/src/validation/scenario-validation.ts @@ -1,112 +1,117 @@ import { - FeatureFromStepDefinitions, - ScenarioFromStepDefinitions, - ParsedFeature, - ParsedScenario, - ParsedScenarioOutline, + FeatureFromStepDefinitions, + ScenarioFromStepDefinitions, + ParsedFeature, + ParsedScenario, + ParsedScenarioOutline, } from '../models'; import { generateScenarioCode } from '../code-generation/scenario-generation'; import { ErrorOptions } from '../configuration'; const findScenarioFromParsedFeature = ( - errors: string[], - parsedScenarios: Array, - scenarioTitle: string, - errorOptions: ErrorOptions, + errors: string[], + parsedScenarios: Array, + scenarioTitle: string, + errorOptions: ErrorOptions, ) => { - let matchingScenarios: Array = []; + let matchingScenarios: Array = []; - if (parsedScenarios) { - matchingScenarios = parsedScenarios - .filter((parsedScenario) => parsedScenario.title.toLowerCase() === scenarioTitle.toLowerCase()); - } + if (parsedScenarios) { + matchingScenarios = parsedScenarios.filter( + parsedScenario => parsedScenario.title.toLowerCase() === scenarioTitle.toLowerCase(), + ); + } - if (matchingScenarios.length === 0 && !errorOptions.allowScenariosNotInFeatureFile) { - errors.push(`No scenarios found in feature file that match scenario title "${scenarioTitle}."`); + if (matchingScenarios.length === 0 && !errorOptions.allowScenariosNotInFeatureFile) { + errors.push(`No scenarios found in feature file that match scenario title "${scenarioTitle}."`); - return null; - } else if (matchingScenarios.length > 1 && errorOptions.scenariosMustMatchFeatureFile) { - errors.push(`More than one scenario found in feature file that match scenario title "${scenarioTitle}"`); + return null; + } + if (matchingScenarios.length > 1 && errorOptions.scenariosMustMatchFeatureFile) { + errors.push(`More than one scenario found in feature file that match scenario title "${scenarioTitle}"`); - return null; - } + return null; + } - return matchingScenarios[0]; + return matchingScenarios[0]; }; const findScenarioFromStepDefinitions = ( - errors: string[], - scenariosFromStepDefinitions: ScenarioFromStepDefinitions[], - scenario: ParsedScenario | ParsedScenarioOutline, - errorOptions: ErrorOptions, + errors: string[], + scenariosFromStepDefinitions: ScenarioFromStepDefinitions[], + scenario: ParsedScenario | ParsedScenarioOutline, + errorOptions: ErrorOptions, ) => { - const scenarioTitle = scenario.title; - const matchingScenarios = scenariosFromStepDefinitions - .filter((scenarioFromStepDefinitions) => { - return scenarioFromStepDefinitions.title.toLocaleLowerCase() === scenarioTitle.toLocaleLowerCase(); - }); + const scenarioTitle = scenario.title; + const matchingScenarios = scenariosFromStepDefinitions.filter(scenarioFromStepDefinitions => { + return scenarioFromStepDefinitions.title.toLocaleLowerCase() === scenarioTitle.toLocaleLowerCase(); + }); - if (matchingScenarios.length === 0 && errorOptions.scenariosMustMatchFeatureFile) { - errors.push(`Feature file has a scenario titled "${scenarioTitle}", but no match found in step definitions. Try adding the following code:\n\n${generateScenarioCode(scenario)}`); + if (matchingScenarios.length === 0 && errorOptions.scenariosMustMatchFeatureFile) { + errors.push( + `Feature file has a scenario titled "${scenarioTitle}", but no match found in step definitions. Try adding the following code:\n\n${generateScenarioCode(scenario)}`, + ); - return null; - } else if (matchingScenarios.length > 1 && errorOptions.scenariosMustMatchFeatureFile) { - errors.push(`More than one scenario found in step definitions matching scenario title "${scenarioTitle}"`); + return null; + } + if (matchingScenarios.length > 1 && errorOptions.scenariosMustMatchFeatureFile) { + errors.push(`More than one scenario found in step definitions matching scenario title "${scenarioTitle}"`); - return null; - } + return null; + } - return matchingScenarios[0]; + return matchingScenarios[0]; }; export const checkThatFeatureFileAndStepDefinitionsHaveSameScenarios = ( - parsedFeature: ParsedFeature, - featureFromStepDefinitions: FeatureFromStepDefinitions, + parsedFeature: ParsedFeature, + featureFromStepDefinitions: FeatureFromStepDefinitions, ) => { - const errors: string[] = []; - - let parsedScenarios: Array = []; - - if (parsedFeature && parsedFeature.scenarios && parsedFeature.scenarios.length) { - parsedScenarios = parsedScenarios.concat(parsedFeature.scenarios); - } - - if (parsedFeature && parsedFeature.scenarioOutlines && parsedFeature.scenarioOutlines.length) { - parsedScenarios = parsedScenarios.concat(parsedFeature.scenarioOutlines); - } - - if (parsedFeature.options && parsedFeature.options.errors === false) { - return; - } - - if (featureFromStepDefinitions - && featureFromStepDefinitions.scenarios - && featureFromStepDefinitions.scenarios.length - ) { - featureFromStepDefinitions.scenarios.forEach((scenarioFromStepDefinitions) => { - findScenarioFromParsedFeature( - errors, - parsedScenarios, - scenarioFromStepDefinitions.title, - parsedFeature.options.errors as ErrorOptions, - ); - }); - } - - parsedScenarios = parsedScenarios.filter((scenario) => !scenario.skippedViaTagFilter); - - if (parsedScenarios && parsedScenarios.length) { - parsedScenarios.forEach((parsedScenario) => { - findScenarioFromStepDefinitions( - errors, - featureFromStepDefinitions && featureFromStepDefinitions.scenarios, - parsedScenario, - parsedFeature.options.errors as ErrorOptions, - ); - }); - } - - if (errors.length) { - throw new Error(errors.join('\n\n')); - } + const errors: string[] = []; + + let parsedScenarios: Array = []; + + if (parsedFeature && parsedFeature.scenarios && parsedFeature.scenarios.length) { + parsedScenarios = parsedScenarios.concat(parsedFeature.scenarios); + } + + if (parsedFeature && parsedFeature.scenarioOutlines && parsedFeature.scenarioOutlines.length) { + parsedScenarios = parsedScenarios.concat(parsedFeature.scenarioOutlines); + } + + if (parsedFeature.options && parsedFeature.options.errors === false) { + return; + } + + if ( + featureFromStepDefinitions && + featureFromStepDefinitions.scenarios && + featureFromStepDefinitions.scenarios.length + ) { + featureFromStepDefinitions.scenarios.forEach(scenarioFromStepDefinitions => { + findScenarioFromParsedFeature( + errors, + parsedScenarios, + scenarioFromStepDefinitions.title, + parsedFeature.options.errors as ErrorOptions, + ); + }); + } + + parsedScenarios = parsedScenarios.filter(scenario => !scenario.skippedViaTagFilter); + + if (parsedScenarios && parsedScenarios.length) { + parsedScenarios.forEach(parsedScenario => { + findScenarioFromStepDefinitions( + errors, + featureFromStepDefinitions && featureFromStepDefinitions.scenarios, + parsedScenario, + parsedFeature.options.errors as ErrorOptions, + ); + }); + } + + if (errors.length) { + throw new Error(errors.join('\n\n')); + } }; diff --git a/src/validation/step-definition-validation.ts b/src/validation/step-definition-validation.ts index 092d061..a87f4be 100644 --- a/src/validation/step-definition-validation.ts +++ b/src/validation/step-definition-validation.ts @@ -4,63 +4,67 @@ import { generateStepCode } from '../code-generation/step-generation'; import { ErrorOptions, Options } from '../configuration'; export const matchSteps = (stepFromFeatureFile: string, stepMatcher: string | RegExp) => { - if (typeof stepMatcher === 'string') { - return stepFromFeatureFile.toLocaleLowerCase() === stepMatcher.toLocaleLowerCase(); - } else if (stepMatcher instanceof RegExp) { - return stepFromFeatureFile.match(stepMatcher); - } else { - return false; - } + if (typeof stepMatcher === 'string') { + return stepFromFeatureFile.toLocaleLowerCase() === stepMatcher.toLocaleLowerCase(); + } + if (stepMatcher instanceof RegExp) { + return stepFromFeatureFile.match(stepMatcher); + } + return false; }; export const ensureFeatureFileAndStepDefinitionScenarioHaveSameSteps = ( - options: Options, - parsedScenario: ParsedScenario | ParsedScenarioOutline, - scenarioFromStepDefinitions: ScenarioFromStepDefinitions, + options: Options, + parsedScenario: ParsedScenario | ParsedScenarioOutline, + scenarioFromStepDefinitions: ScenarioFromStepDefinitions, ) => { - if (options && options.errors === false) { - return; - } else if (options && options.errors && !(options.errors as ErrorOptions).stepsMustMatchFeatureFile) { - return; - } + if (options && options.errors === false) { + return; + } + if (options && options.errors && !(options.errors as ErrorOptions).stepsMustMatchFeatureFile) { + return; + } - if (!parsedScenario) { - return; - } + if (!parsedScenario) { + return; + } - const errors: string[] = []; + const errors: string[] = []; - let parsedScenarioSteps: ParsedStep[] = []; + let parsedScenarioSteps: ParsedStep[] = []; - if ((parsedScenario as ParsedScenarioOutline).scenarios) { - const parsedScenarioOutlineScenarios = (parsedScenario as ParsedScenarioOutline).scenarios; + if ((parsedScenario as ParsedScenarioOutline).scenarios) { + const parsedScenarioOutlineScenarios = (parsedScenario as ParsedScenarioOutline).scenarios; - if (parsedScenarioOutlineScenarios && parsedScenarioOutlineScenarios.length) { - parsedScenarioSteps = parsedScenarioOutlineScenarios[0].steps; - } else { - parsedScenarioSteps = []; - } - } else if ((parsedScenario as ParsedScenario).steps) { - parsedScenarioSteps = (parsedScenario as ParsedScenario).steps; + if (parsedScenarioOutlineScenarios && parsedScenarioOutlineScenarios.length) { + parsedScenarioSteps = parsedScenarioOutlineScenarios[0].steps; + } else { + parsedScenarioSteps = []; } + } else if ((parsedScenario as ParsedScenario).steps) { + parsedScenarioSteps = (parsedScenario as ParsedScenario).steps; + } - const parsedStepCount = parsedScenarioSteps.length; - const stepDefinitionCount = scenarioFromStepDefinitions.steps.length; + const parsedStepCount = parsedScenarioSteps.length; + const stepDefinitionCount = scenarioFromStepDefinitions.steps.length; - if ( - parsedStepCount !== stepDefinitionCount) { - errors.push(`Scenario "${parsedScenario.title}" has ${parsedStepCount} step(s) in the feature file, but ${stepDefinitionCount} step definition(s) defined. Try adding the following code:\n\n${generateScenarioCode(parsedScenario)}`); - } else { - parsedScenarioSteps.forEach((parsedStep, index) => { - const stepFromStepDefinitions = scenarioFromStepDefinitions.steps[index]; + if (parsedStepCount !== stepDefinitionCount) { + errors.push( + `Scenario "${parsedScenario.title}" has ${parsedStepCount} step(s) in the feature file, but ${stepDefinitionCount} step definition(s) defined. Try adding the following code:\n\n${generateScenarioCode(parsedScenario)}`, + ); + } else { + parsedScenarioSteps.forEach((parsedStep, index) => { + const stepFromStepDefinitions = scenarioFromStepDefinitions.steps[index]; - if (!stepFromStepDefinitions || !matchSteps(parsedStep.stepText, stepFromStepDefinitions.stepMatcher)) { - errors.push(`Expected step #${index + 1} in scenario "${parsedScenario.title}" to match "${parsedStep.stepText}". Try adding the following code:\n\n${generateStepCode(parsedScenario.steps, index)}`); - } - }); - } + if (!stepFromStepDefinitions || !matchSteps(parsedStep.stepText, stepFromStepDefinitions.stepMatcher)) { + errors.push( + `Expected step #${index + 1} in scenario "${parsedScenario.title}" to match "${parsedStep.stepText}". Try adding the following code:\n\n${generateStepCode(parsedScenario.steps, index)}`, + ); + } + }); + } - if (errors.length) { - throw new Error(errors.join('\n\n')); - } + if (errors.length) { + throw new Error(errors.join('\n\n')); + } }; From 2300d152fc8980e9ca833e1a50d80b8f57749e19 Mon Sep 17 00:00:00 2001 From: pplancq Date: Sat, 23 Mar 2024 15:34:47 +0100 Subject: [PATCH 4/4] chore(lint): add pre-commit hook with husky --- .husky/pre-commit | 1 + package-lock.json | 670 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 10 +- 3 files changed, 680 insertions(+), 1 deletion(-) create mode 100755 .husky/pre-commit diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..d0a7784 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index fc71022..d9ab1d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,9 +23,12 @@ "@types/uuid": "^8.3.0", "eslint": "^8.57.0", "eslint-plugin-prettier": "^5.1.3", + "husky": "^9.0.11", "jest": "^29.7.0", + "lint-staged": "^15.2.2", "prettier": "^3.2.5", "ts-jest": "^29.1.2", + "tsc-files": "^1.1.4", "typescript": "^5.4.3" }, "peerDependencies": { @@ -2372,6 +2375,87 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -2420,6 +2504,21 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3948,6 +4047,12 @@ "node": ">=0.10.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -4205,6 +4310,18 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -4469,6 +4586,21 @@ "node": ">=10.17.0" } }, + "node_modules/husky": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", + "dev": true, + "bin": { + "husky": "bin.mjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -5812,12 +5944,290 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/lint-staged": { + "version": "15.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", + "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", + "dev": true, + "dependencies": { + "chalk": "5.3.0", + "commander": "11.1.0", + "debug": "4.3.4", + "execa": "8.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.1", + "micromatch": "4.0.5", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.3.4" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/lint-staged/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", + "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", + "dev": true, + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.3.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -5842,6 +6252,162 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", + "dev": true, + "dependencies": { + "type-fest": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", @@ -6314,6 +6880,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -6658,6 +7236,22 @@ "node": ">=10" } }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -6668,6 +7262,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -6863,6 +7463,46 @@ "node": ">=8" } }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -6907,6 +7547,15 @@ "node": ">=8" } }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -7202,6 +7851,18 @@ } } }, + "node_modules/tsc-files": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/tsc-files/-/tsc-files-1.1.4.tgz", + "integrity": "sha512-RePsRsOLru3BPpnf237y1Xe1oCGta8rmSYzM76kYo5tLGsv5R2r3s64yapYorGTPuuLyfS9NVbh9ydzmvNie2w==", + "dev": true, + "bin": { + "tsc-files": "cli.js" + }, + "peerDependencies": { + "typescript": ">=3" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -7615,6 +8276,15 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index be2e6cb..58b2dc9 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "test": "npm run build & npm run lint & jest --color", "update-snapshots": "jest --updateSnapshot", "lint": "eslint src specs examples --ext js,jsx,ts,tsx", - "lint:fix": "eslint src specs examples --ext js,jsx,ts,tsx --fix" + "lint:fix": "eslint src specs examples --ext js,jsx,ts,tsx --fix", + "prepare": "husky" }, "repository": { "type": "git", @@ -51,9 +52,12 @@ "@types/uuid": "^8.3.0", "eslint": "^8.57.0", "eslint-plugin-prettier": "^5.1.3", + "husky": "^9.0.11", "jest": "^29.7.0", + "lint-staged": "^15.2.2", "prettier": "^3.2.5", "ts-jest": "^29.1.2", + "tsc-files": "^1.1.4", "typescript": "^5.4.3" }, "jest": { @@ -76,5 +80,9 @@ "@pplancq/eslint-config/jest", "@pplancq/eslint-config/prettier" ] + }, + "lint-staged": { + "*.{js,jsx,ts,tsx}": "eslint --fix", + "*.{ts,tsx}": "tsc-files --noEmit" } }