diff --git a/CHANGELOG.md b/CHANGELOG.md index f62d022..b171096 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.2.0] - 2023-10-27 + +### Changed + +- replace `tap-parser` with `tap-reader` for simpler i/o, shallower dependency graph, and smaller disk footprint +- single-line diffs now output to 2 lines: "Actual" and "Expected" for easier reading ## [1.1.0] - 2023-10-17 diff --git a/README.md b/README.md index 7040bef..7a6aad6 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,9 @@ ## Objectives -- minimal, informative spec-like output for all assertions -- minimal, maintained dependencies -- streaming in and out +- minimal, informative spec-like output for all assertion types - helpful diffing for failures +- shallow graph of maintained dependencies ![tap-arc output screen shot](./screen-shot.png) @@ -41,7 +40,8 @@ Example `npm test` script: } ``` -๐Ÿ’ `tap-arc` will format output from any tap reporter. [`tape`](https://github.com/ljharb/tape) is our favorite and was used for testing. +> [!IMPORTANT] +> ๐Ÿ’ `tap-arc` will format output from any tap reporter. [`tape`](https://github.com/ljharb/tape) is our favorite and was used for testing. ### `tap-arc --help` @@ -83,10 +83,7 @@ npm run tap-arc.simple # used to create the screen shot above ### Dev Tips -1. `./test/smoke.js` contains the bare minimum usage of `tap-parser` with `process.stdin`. -Helpful for understanding `tap-parser`'s behavior. - -2. To see previous exit code, run: +1. To see previous exit code, run: ```sh echo $? @@ -101,12 +98,12 @@ Testing could be improved by unit testing the printer and diff maker. ## FAQ
-"Expected n assertions, but found < n" +"Expected n tests, but found < n" _What happened?_ โœ… The TAP parser found zero failing tests โœ… The final tally from the raw TAP shows `n` of `n` passed -๐Ÿคจ But the TAP plan called for more assertions than were found, counted, and parsed. +๐Ÿคจ But the TAP plan called for more tests than were found, counted, and parsed. ๐Ÿ’โ€โ™€๏ธ Currently, when this case is detected, `tap-arc` will exit with a successful status code. This can be overridden with the `--fail-bad-count` flag. @@ -138,4 +135,3 @@ If you'd like to see different behavior from `tap-arc`, please open an issue or - [tap-spec](https://github.com/scottcorgan/tap-spec) ol' reliable, but a bit stale and vulnerable - [tap-difflet](https://github.com/namuol/tap-difflet) inspired output and diffing, also vulnerable -- [tap-min](https://github.com/derhuerst/tap-min) helpful approaches to streaming and exit codes, used to report `tap-arc`'s TAP diff --git a/package-lock.json b/package-lock.json index 1d53d3d..c2a7154 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21 +1,20 @@ { "name": "tap-arc", - "version": "1.1.0", + "version": "1.2.0-RC.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "tap-arc", - "version": "1.1.0", + "version": "1.2.0-RC.2", "license": "Apache-2.0", "dependencies": { "chalk": "^5.3.0", "diff": "^5.1.0", - "duplexer3": "^1.0.0", "json5": "^2.2.3", "minimist": "^1.2.8", "strip-ansi": "^7.1.0", - "tap-parser": "^15.2.1" + "tap-reader": "^0.1.0" }, "bin": { "tap-arc": "src/index.js" @@ -23,9 +22,8 @@ "devDependencies": { "@architect/eslint-config": "^2.1.2", "@types/node": "^16.18.55", - "eslint": "^8.51.0", - "tap-min": "^3.0.0", - "tape": "5.7.0" + "eslint": "^8.52.0", + "tape": "^5.7.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -69,9 +67,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", - "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", + "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" @@ -100,22 +98,45 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/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/@eslint/js": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", - "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -123,6 +144,29 @@ "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/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/@humanwhocodes/config-array/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/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -137,9 +181,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@ljharb/resumer": { @@ -155,10 +199,13 @@ } }, "node_modules/@ljharb/through": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.9.tgz", - "integrity": "sha512-yN599ZBuMPPK4tdoToLlvgJB4CLK8fGl7ntfy0Wn7U6ttNvHYurd81bfUiK/6sMkiIwm65R6ck4L6+Y3DfVbNQ==", + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.11.tgz", + "integrity": "sha512-ccfcIDlogiXNq5KcbAwbaO7lMh3Tm1i3khMPYpxlK8hH/W53zN81KM9coerRLOnTGu3nfXIniAmQbRI9OxbC0w==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, "engines": { "node": ">= 0.4" } @@ -205,9 +252,15 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.18.58", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.58.tgz", - "integrity": "sha512-YGncyA25/MaVtQkjWW9r0EFBukZ+JulsLcVZBlGUfIb96OBMjkoRWwQo5IEWJ8Fj06Go3GHw+bjYDitv6BaGsA==", + "version": "16.18.59", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.59.tgz", + "integrity": "sha512-PJ1w2cNeKUEdey4LiPra0ZuxZFOGvetswE8qHRriV/sUkL5Al4tTmPV9D2+Y/TPIxTHHgxTfRjZVKWhPw/ORhQ==", + "dev": true + }, + "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": { @@ -434,13 +487,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -517,20 +571,12 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "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.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "ms": "^2.1.1" } }, "node_modules/deep-equal": { @@ -569,9 +615,9 @@ "dev": true }, "node_modules/define-data-property": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", - "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", "dev": true, "dependencies": { "get-intrinsic": "^1.2.1", @@ -617,15 +663,15 @@ } }, "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "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": ">=6.0.0" + "node": ">=0.10.0" } }, "node_modules/dotignore": { @@ -640,38 +686,27 @@ "ignored": "bin/ignored" } }, - "node_modules/duplexer3": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-1.0.0.tgz", - "integrity": "sha512-6O5ndCyJ9CGF9cR2Yi3VFq1OvXXLEgX848InIOl8xUBPYwb8jn/93j10lGaZyLnMRa71IT5OHhURlOiVjH9OVg==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/es-abstract": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", - "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "arraybuffer.prototype.slice": "^1.0.2", "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.5", "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.1", + "get-intrinsic": "^1.2.2", "get-symbol-description": "^1.0.0", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", "has-property-descriptors": "^1.0.0", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", + "hasown": "^2.0.0", "internal-slot": "^1.0.5", "is-array-buffer": "^3.0.2", "is-callable": "^1.2.7", @@ -681,7 +716,7 @@ "is-string": "^1.0.7", "is-typed-array": "^1.1.12", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.5.1", @@ -695,7 +730,7 @@ "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -725,26 +760,26 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "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": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -777,18 +812,19 @@ } }, "node_modules/eslint": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", - "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.51.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", "@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", @@ -854,15 +890,6 @@ "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-module-utils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", @@ -880,15 +907,6 @@ } } }, - "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-filenames": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/eslint-plugin-filenames/-/eslint-plugin-filenames-1.3.2.tgz", @@ -923,26 +941,26 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", - "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz", + "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==", "dev": true, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "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.7", + "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.8.0", - "has": "^1.0.3", - "is-core-module": "^2.13.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", "semver": "^6.3.1", "tsconfig-paths": "^3.14.2" }, @@ -953,27 +971,6 @@ "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-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -1027,6 +1024,41 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/eslint/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/eslint/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/eslint/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/eslint/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -1098,14 +1130,6 @@ "node": ">=0.10.0" } }, - "node_modules/events-to-array": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-2.0.3.tgz", - "integrity": "sha512-f/qE2gImHRa4Cp2y1stEOSgw8wTFyUdVJX7G//bMwbaV9JqISFxg99NbmVQeP7YLnDUZ2un851jlaDrlpmGehQ==", - "engines": { - "node": ">=12" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1197,10 +1221,13 @@ "dev": true }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "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", @@ -1230,15 +1257,15 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1349,15 +1376,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -1390,12 +1408,12 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "get-intrinsic": "^1.2.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1440,13 +1458,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hirestime": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/hirestime/-/hirestime-7.0.3.tgz", - "integrity": "sha512-XmjAwwjLJlDjVVljWht/+Pb6vTfs6A0z2ZpaCkVmzEkwiZcO/+lbj1DsxpsDvkVprYHCmNBxTr7tUohdlxG2Hw==", + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, "engines": { - "node": ">=6.0" + "node": ">= 0.4" } }, "node_modules/ignore": { @@ -1500,13 +1521,13 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -1584,12 +1605,12 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "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": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1951,24 +1972,29 @@ } }, "node_modules/mock-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mock-property/-/mock-property-1.0.0.tgz", - "integrity": "sha512-imC60k5A55GPUU43PqczbubOyyxCudIgneACKzL3PKfsBk08dc1HgNNU8siQbEIAPPjVUhc+gb0v0ypZ/iP9pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mock-property/-/mock-property-1.0.3.tgz", + "integrity": "sha512-2emPTb1reeLLYwHxyVx993iYyCHEiRRO+y8NFXFPL5kl5q14sgTK76cXyEKkeKCHeRw35SfdkUJ10Q1KfHuiIQ==", "dev": true, "dependencies": { - "functions-have-names": "^1.2.2", - "has": "^1.0.3", + "define-data-property": "^1.1.1", + "functions-have-names": "^1.2.3", + "gopd": "^1.0.1", "has-property-descriptors": "^1.0.0", + "hasown": "^2.0.0", "isarray": "^2.0.5" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "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==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "node_modules/natural-compare": { @@ -1978,9 +2004,9 @@ "dev": true }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "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" @@ -2143,18 +2169,6 @@ "node": ">=6" } }, - "node_modules/parse-ms": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-3.0.0.tgz", - "integrity": "sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2197,21 +2211,6 @@ "node": ">= 0.8.0" } }, - "node_modules/pretty-ms": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-8.0.0.tgz", - "integrity": "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==", - "dev": true, - "dependencies": { - "parse-ms": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -2268,9 +2267,9 @@ } }, "node_modules/resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { "is-core-module": "^2.13.0", @@ -2382,6 +2381,21 @@ "semver": "bin/semver.js" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/set-function-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", @@ -2547,105 +2561,41 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tap-min": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tap-min/-/tap-min-3.0.0.tgz", - "integrity": "sha512-oEhFyYCUEmRLYwtlIkRgeVkX538yEQfoSg6BcWXMq05TFsnpsi3vtQZJeEBkXzMWlj1h/rKaRMaWPCvCTmIIXg==", - "dev": true, - "dependencies": { - "chalk": "^5.3.0", - "duplexer3": "^1.0.0", - "hirestime": "^7.0.3", - "pretty-ms": "^8.0.0", - "tap-parser": "^13.0.2-1" - }, - "bin": { - "tap-min": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/tap-min/node_modules/tap-parser": { - "version": "13.0.2-1", - "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-13.0.2-1.tgz", - "integrity": "sha512-A6U6TvfwEUFVivyZFiTth3LVrGw9aa4j4cSU8W6ui3sfrZBRNzE1y5YhBomz0+RIRURdspFJdaJvVgSXI68h0Q==", - "dev": true, - "dependencies": { - "events-to-array": "^2.0.3", - "tap-yaml": "2.1.1-1" - }, - "bin": { - "tap-parser": "bin/cmd.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/tap-min/node_modules/tap-yaml": { - "version": "2.1.1-1", - "resolved": "https://registry.npmjs.org/tap-yaml/-/tap-yaml-2.1.1-1.tgz", - "integrity": "sha512-acWZWpwstr0YMms30FW2nlFkJ0hSm/o2x32Hq5v10IKqYKwnRXARSx6TKbz/gzcSoODPi9PkFQYGYBgowxKDfA==", - "dev": true, - "dependencies": { - "yaml": "^2.3.0", - "yaml-types": "^0.3.0" - } - }, - "node_modules/tap-parser": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-15.2.1.tgz", - "integrity": "sha512-9163zwEecM7sYJyknuRznN7PGncke6CG5Ybat9xigg7ppTsQc5eO9J69tAG2ISM244hIbqv9H6SQ1jRUa9AvBA==", - "dependencies": { - "events-to-array": "^2.0.3", - "tap-yaml": "2.2.0" - }, + "node_modules/tap-reader": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tap-reader/-/tap-reader-0.1.0.tgz", + "integrity": "sha512-d8l2tzfRRBhxISlmPMmsRBiy9cTyBPJv1NX5qFyllD9U5TZUVsFOYcPhorY90+UWevo8gdGEcgWWANtv8l9XKQ==", "bin": { - "tap-parser": "bin/cmd.cjs" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/tap-yaml": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tap-yaml/-/tap-yaml-2.2.0.tgz", - "integrity": "sha512-o8I7WDNiGpuF04tGAVaNYY5rX9waCtqw9A7Y0YVSQBGcFwNUJWUPLkr2lbhgLRTxc+Tpnw4xUXlIanZc+ZAGnw==", - "dependencies": { - "yaml": "^2.3.0", - "yaml-types": "^0.3.0" - }, - "engines": { - "node": ">=16" + "tap-reader": "src/index.js" } }, "node_modules/tape": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/tape/-/tape-5.7.0.tgz", - "integrity": "sha512-6EZoHjMDUUhet8+k32w/9onULL1U8idXKvBCnZxuZF2iFe+tMYOsKo4bpCtXbTSngZmYBnkU08TMhJwsKaHhaw==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/tape/-/tape-5.7.2.tgz", + "integrity": "sha512-cvSyprYahyOYXbtBwV/B7nrx7kINeZ3VZ9fKoSywoPwZN3oQ1WVLvt+Vl0XCz/gi37CDrY3dlW790nzviIzoPw==", "dev": true, "dependencies": { "@ljharb/resumer": "^0.0.1", - "@ljharb/through": "^2.3.9", + "@ljharb/through": "^2.3.11", "array.prototype.every": "^1.1.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.5", "deep-equal": "^2.2.2", "defined": "^1.0.1", "dotignore": "^0.1.2", "for-each": "^0.3.3", "get-package-type": "^0.1.0", "glob": "^7.2.3", - "has": "^1.0.3", "has-dynamic-import": "^2.0.1", + "hasown": "^2.0.0", "inherits": "^2.0.4", "is-regex": "^1.1.4", "minimist": "^1.2.8", - "mock-property": "^1.0.0", - "object-inspect": "^1.12.3", + "mock-property": "^1.0.2", + "object-inspect": "^1.13.1", "object-is": "^1.1.5", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "resolve": "^2.0.0-next.4", + "resolve": "^2.0.0-next.5", "string.prototype.trim": "^1.2.8" }, "bin": { @@ -2656,12 +2606,12 @@ } }, "node_modules/tape/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "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.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -2862,13 +2812,13 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.4", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-tostringtag": "^1.0.0" @@ -2886,26 +2836,6 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "node_modules/yaml": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", - "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==", - "engines": { - "node": ">= 14" - } - }, - "node_modules/yaml-types": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/yaml-types/-/yaml-types-0.3.0.tgz", - "integrity": "sha512-i9RxAO/LZBiE0NJUy9pbN5jFz5EasYDImzRkj8Y81kkInTi1laia3P3K/wlMKzOxFQutZip8TejvQP/DwgbU7A==", - "engines": { - "node": ">= 16", - "npm": ">= 7" - }, - "peerDependencies": { - "yaml": "^2.3.0" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 8c40f94..abe2e6e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "tap-arc", "description": "spec-like TAP reporter", "author": "tbeseda", - "version": "1.1.0", + "version": "1.2.0-RC.2", "license": "Apache-2.0", "type": "module", "main": "src/index.js", @@ -47,24 +47,22 @@ "tape.throws": "tape test/mock/create-throws-tap.cjs", "tape.upstream-error": "tape test/mock/create-upstream-error-tap.cjs", "tape.runtime-error": "tape test/mock/create-runtime-error-tap.js", - "tape": "tape test/**/*-test.js | tap-min", + "tape": "tape test/**/*-test.js", "test": "npm run lint && npm run tape" }, "dependencies": { "chalk": "^5.3.0", "diff": "^5.1.0", - "duplexer3": "^1.0.0", "json5": "^2.2.3", "minimist": "^1.2.8", "strip-ansi": "^7.1.0", - "tap-parser": "^15.2.1" + "tap-reader": "^0.1.0" }, "devDependencies": { "@architect/eslint-config": "^2.1.2", "@types/node": "^16.18.55", - "eslint": "^8.51.0", - "tap-min": "^3.0.0", - "tape": "5.7.0" + "eslint": "^8.52.0", + "tape": "^5.7.2" }, "eslintConfig": { "extends": "@architect/eslint-config", diff --git a/screen-shot.png b/screen-shot.png index 2399a9c..e165c85 100644 Binary files a/screen-shot.png and b/screen-shot.png differ diff --git a/src/_make-diff.js b/src/_make-diff.js index a69d570..51c9a53 100644 --- a/src/_make-diff.js +++ b/src/_make-diff.js @@ -16,15 +16,20 @@ export default function ({ actual, expected }){ */ function diffLine (a, e) { const diff = Diff.diffWordsWithSpace(a, e) - const output = [] + + let aLine = 'Actual: ' + let eLine = 'Expected: ' for (const d of diff) { - if (d.added) output.push(`${expected(d.value)}`) - else if (d.removed) output.push(`${actual(d.value)}`) - else output.push(d.value) + if (d.added) eLine += expected(d.value) + else if (d.removed) aLine += actual(d.value) + else { + eLine += d.value + aLine += d.value + } } - return output.join('').split('\n') + return [ aLine, eLine ] } /** diff --git a/src/_printer.js b/src/_printer.js index d661b52..1420b1d 100644 --- a/src/_printer.js +++ b/src/_printer.js @@ -1,23 +1,24 @@ import { Chalk } from 'chalk' -const RIGHT = 'โ†ฆ' +const RIGHT = 'โ‡ฅ' const CHECK = 'โœ“' const CROSS = 'โœ—' +const BOX = 'โฃ' function prettyMs (start) { const ms = Date.now() - start return ms < 1000 ? `${ms} ms` : `${ms / 1000} s` } -export default function (options) { +export default function (output, options) { const { color, debug, verbose } = options const d = debug || verbose const { blue, bold, - cyan, dim, green, + italic, red, yellow, } = new Chalk({ level: color ? 3 : 0 }) @@ -26,26 +27,34 @@ export default function (options) { const actual = blue const passMark = bold.green(CHECK) const failMark = bold.red(CROSS) - const skipMark = RIGHT + const skipMark = bold.cyan(RIGHT) + const todoMark = bold.cyan(BOX) function pad (n = 1, c = ' ') { return dim(c).repeat(n) } + /** + * Print a line to the output stream + * @param {string} str + * @param {number} p padding + * @param {number} n newlines + * @returns void + */ + function print (str, p = 0, n = 1) { + output.write(`${pad(p)}${str}${'\n'.repeat(n)}`) + } + return { - pass ({ id, name }) { - return `${passMark}${d ? ` [${id}]` : ''} ${dim(name)}` - }, - fail ({ id, name, tapError }) { - return `${failMark} ${tapError ? red(`"${tapError}"`) : `[${id}] ${red(name)}`}` - }, - skip ({ id, name }) { - return cyan(`${skipMark}${d ? ` [${id}]` : ''} ${name}`) + pass ({ id, desc, skip, todo, reason }) { + const mark = skip ? skipMark : todo ? todoMark : passMark + return `${mark}${reason ? ` - ${reason}` : ''}${d ? ` [${id}]` : ''} ${dim(desc)}` }, - todo ({ id, name, ok: pass }) { - const method = pass ? dim : red - return method(`${skipMark}${d ? ` [${id}]` : ''} ${name}`) + fail ({ id, desc, skip, todo, reason }) { + const mark = skip ? skipMark : todo ? todoMark : failMark + return `${mark}${reason ? ` - ${reason}` : ''} [${id}] ${red(desc)}` }, + print, pad, prettyMs, actual, @@ -54,6 +63,7 @@ export default function (options) { dim, expected, good: green, + italic, strong: bold, title: bold.underline, } diff --git a/src/index.js b/src/index.js index b08538b..f89b356 100755 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ #!/usr/bin/env node import minimist from 'minimist' import helpText from './_help-text.js' -import tapArc from './tap-arc.js' +import TapArc from './tap-arc.js' const alias = { help: [ 'h', 'help' ], @@ -18,6 +18,7 @@ const defaultOptions = { pessimistic: false, failBadCount: false, verbose: false, + tap: false, debug: false, } const options = { @@ -30,25 +31,14 @@ if (options.help) { process.exit() } -const parser = tapArc(options) -// @ts-ignore - DuplexWrapper is not typed -parser.on('end', () => { - // @ts-ignore - const { results } = parser._writable +const tapArc = TapArc(process.stdin, process.stdout, options) - if (!results.ok) { - if ( - results.badCount && - results.failures.length === 0 && - !options.failBadCount - ) process.exit(0) - else process.exit(1) - } - if ( - results.count === 0 && - results.plan.comment.indexOf('no tests found') >= 0 - ) process.exit(1) +let badCount = false +tapArc.on('badCount', () => { + badCount = true }) -// @ts-ignore -process.stdin.pipe(parser).pipe(process.stdout) +tapArc.on('end', ({ ok }) => { + if (badCount && options.failBadCount) process.exit(1) + else process.exit(ok ? 0 : 1) +}) diff --git a/src/tap-arc.js b/src/tap-arc.js index fce0fa7..65ea3ec 100644 --- a/src/tap-arc.js +++ b/src/tap-arc.js @@ -1,75 +1,53 @@ -import { Parser } from 'tap-parser' -import { PassThrough } from 'stream' -import duplexer from 'duplexer3' // TODO: write a custom, simpler duplexer +import TapReader from 'tap-reader' import JSON5 from 'json5' import stripAnsi from 'strip-ansi' -import differ from './_make-diff.js' +import createDiffer from './_make-diff.js' import createPrinter from './_printer.js' const { parse } = JSON5 -const reservedCommentPrefixes = [ 'tests ', 'pass ', 'skip', 'todo', 'fail ', 'failed ', 'ok', 'test count' ] - -export default function createParser (options) { - const { debug, pessimistic, showDiff, verbose } = options - const output = new PassThrough() - const parser = new Parser({ bail: pessimistic }) - const stream = duplexer(parser, output) - const _ = createPrinter(options) - const { prettyMs, pad } = _ - const { diffArray, diffObject, diffString } = differ(_) - - /** - * Print a line to the output stream - * @param {string} str - * @param {number} p padding - * @param {number} n newlines - * @returns void - */ - function P (str, p = 0, n = 1) { - output.write(`${pad(p)}${str}${'\n'.repeat(n)}`) - } +const tapeCommentPrefixes = [ 'tests ', 'pass ', 'skip', 'todo', 'fail ', 'failed ', 'ok', 'test count' ] + +export default function createParser (input, output, options = {}) { + const { debug, pessimistic, showDiff, tap, verbose } = options + + const _ = createPrinter(output, options) + const { print: P, prettyMs } = _ + const { diffArray, diffObject, diffString } = createDiffer(_) + + const reader = TapReader({ input, bail: pessimistic }) const cwd = process.cwd() const start = Date.now() - const counter = { - pass: 0, - skip: 0, - todo: 0, - fail: 0, - } + const counter = { pass: 0, fail: 0, skip: 0, todo: 0 } - parser.on('comment', (comment) => { - if (!reservedCommentPrefixes.some((c) => comment.startsWith(c, 2))) { + reader.on('comment', ({ comment }) => { + if (!tapeCommentPrefixes.some((c) => comment.startsWith(c))) { // "comment" is generally a test group name - P(`\n${_.title(comment.trimEnd().replace(/^(# )/, ''))}`) + P(`\n${_.title(comment)}`) } }) - parser.on('extra', (extra) => { + reader.on('other', ({ line }) => { // typically `console.log` output from the test or program it tests - const stripped = stripAnsi(extra).trim() - const justAnsi = stripped.length === 0 && extra.length > 0 - if (!justAnsi) P(extra, 0, 0) + const stripped = stripAnsi(line).trim() + const justAnsi = stripped.length === 0 && line.length > 0 + if (!justAnsi) P(_.italic(line), 0) }) - parser.on('pass', (test) => { + reader.on('pass', (test) => { counter.pass++ - P(_.pass(test), 2) - }) - - parser.on('skip', (test) => { - counter.skip++ - P(_.skip(test), 2) - }) + if (test.skip) counter.skip++ + if (test.todo) counter.todo++ - parser.on('todo', (test) => { - counter.todo++ - P(_.todo(test), 2) + P(_.pass(test), 2) }) - parser.on('fail', (test) => { + reader.on('fail', (test) => { counter.fail++ + if (test.skip) counter.skip++ + if (test.todo) counter.todo++ + P(_.fail(test), 2) if (test.diag) { @@ -144,9 +122,9 @@ export default function createParser (options) { case 'throws': if ( actual - && typeof actual !== 'undefined' - && expected - && typeof expected !== 'undefined' + && typeof actual !== 'undefined' + && expected + && typeof expected !== 'undefined' ) // this weird combination is throws with expected/assertion P(`Expected ${_.expected(expected)} to match "${_.actual(actual.message || actual)}"`, indent) else if (actual && typeof actual !== 'undefined') // this combination is usually "doesNotThrow" @@ -175,71 +153,59 @@ export default function createParser (options) { } }) - parser.on('complete', (result) => { - if (!result.ok) { - const tapFailures = result.failures.filter((f) => f.tapError) - for (const tapFailure of tapFailures) { - const { tapError } = tapFailure - - if (tapError.startsWith('incorrect number of tests')) { - // custom failure was created by tap-parser - P(_.realBad(`\nExpected ${result.plan.end || '?'} assertions, parsed ${result.count || '?'}`)) - result.badCount = true // persisted to CLI process handler - result.failures.shift() - result.fail-- - } - else if (tapError.startsWith('no plan')) - P(_.realBad(`\nTAP test plan not found`)) - else - P(_.realBad(`\n${tapError}`)) - } + reader.on('done', ({ summary, plan, passing, failures, ok }) => { + if (summary && plan && summary.total < plan.end) { + P(_.realBad(`\nExpected ${plan.end} tests, parsed ${summary.total}`)) + reader.emit('badCount', { summary, plan }) + } - if (result.failures.length > 0) { - const singular = result.fail === 1 + if (!ok) { + if (summary.fail > 0) { + const singular = summary.fail === 1 let failureSummary = '\n' failureSummary += _.bad('Failed tests:') failureSummary += ` There ${singular ? 'was' : 'were'} ` - failureSummary += _.bad(result.fail) + failureSummary += _.bad(summary.fail) failureSummary += ` failure${singular ? '' : 's'}\n` P(failureSummary) - for (const test of result.failures) P(_.fail(test), 2) + for (const test in failures) P(_.fail(failures[test]), 2) } } - P(`\ntotal: ${result.count}`) - if (result.bailout) P(_.realBad('BAILED!')) - if (result.pass > 0) P(_.good(`passing: ${result.pass}`)) - if (result.fail > 0) P(_.bad(`failing: ${result.fail}`)) - if (result.skip > 0) P(`skipped: ${result.skip}`) - if (result.todo > 0) P(`todo: ${result.todo}`) + P(`\ntotal: ${summary.total}`) + // if (result.bailout) P(_.realBad('BAILED!')) + if (summary.pass > 0) P(_.good(`passing: ${summary.pass}`)) + if (summary.fail > 0) P(_.bad(`failing: ${summary.fail}`)) + if (summary.skip > 0) P(_.dim(`skipped: ${summary.skip}`)) + if (summary.todo > 0) P(_.dim(`todo: ${summary.todo}`)) + + P(`${_.dim.italic(prettyMs(start))}\n`) // maybe output.end()? if (debug) { - P('tap-parser result:') - P(JSON.stringify(result, null, 2)) + P('tap-reader result:') + P(JSON.stringify({ summary, passing, failures, ok }, null, 2)) P('tap-arc internal counters:') P(JSON.stringify(counter, null, 2)) } - - output.end(`${_.dim(prettyMs(start))}\n`) }) if (verbose) { - parser.on('version', (version) => { + reader.on('version', ({ version }) => { P(`${_.strong('TAP version:')} ${version}`) }) - parser.on('plan', (plan) => { - const { start, end, comment } = plan - P(`${_.strong('Plan:')} start=${start} end=${end} ${comment ? `"${comment}"` : ''}`) + reader.on('plan', ({ plan, bad }) => { + const [ start, end ] = plan + P(`${_.strong('Plan:')} start=${start} end=${end} ${bad ? '(BAD)' : ''}`) }) } - if (debug) { - parser.on('line', (line) => { + if (tap) { + reader.on('line', ({ line }) => { P(line.trim()) }) } - return stream + return reader } diff --git a/test/exit-codes-test.js b/test/exit-codes-test.js index 47b9706..d3d3f88 100644 --- a/test/exit-codes-test.js +++ b/test/exit-codes-test.js @@ -1,6 +1,7 @@ import { exec } from 'child_process' import { join } from 'path' import test from 'tape' +import stripAnsi from 'strip-ansi' const mockPath = join('.', 'test', 'mock') @@ -30,7 +31,7 @@ test('streams and exit codes', (t) => { exec( `npx tape ${join(mockPath, filename)} | node src/index.js`, (error, stdout, stderr) => { - t.ok(error, `"${filename}" creates an error`) + t.notOk(error, `"${filename}" doesn't create an error`) t.ok(stderr, 'stderror should not be empty') t.ok(stdout.indexOf('total: 0') > 0, '"total: 0" should occur in output') } @@ -56,41 +57,43 @@ test('streams and exit codes', (t) => { }) } - const badCountPassing = 'missing-assertions-passing.txt' + const badCountPassing = 'missing-assertions-passing.tap' + const badCountFailing = 'missing-assertions-failing.tap' + t.test(`exit(0) "${badCountPassing}" | tap-arc`, (t) => { t.plan(3) exec( - `cat ${join(mockPath, badCountPassing)} | node src/index.js`, + `cat ${join(mockPath, 'tape', badCountPassing)} | node src/index.js`, (error, stdout, stderr) => { t.notOk(error, `"${badCountPassing}" exits without error`) t.notOk(stderr, 'stderror should be empty') t.ok( - stdout.indexOf('Expected 16 assertions, parsed 13') > 0, - '"Expected 16 assertions, parsed 13" should occur in output', + stripAnsi(stdout).indexOf('Expected 16 tests, parsed 13') > 0, + '"Expected 16 tests, parsed 13" should occur in output', ) } ) }) + t.test(`exit(1) "${badCountPassing}" | tap-arc --fail-bad-count`, (t) => { t.plan(3) exec( - `cat ${join(mockPath, badCountPassing)} | node src/index.js --fail-bad-count`, + `cat ${join(mockPath, 'tape', badCountPassing)} | node src/index.js --fail-bad-count`, (error, stdout, stderr) => { - t.ok(error, `"${badCountFailing}" creates an error`) + t.ok(error, `"${badCountPassing}" creates an error`) t.notOk(stderr, 'stderror should be empty') t.ok( - stdout.indexOf('Expected 16 assertions, parsed 13') > 0, - '"Expected 16 assertions, parsed 13" should occur in output', + stdout.indexOf('Expected 16 tests, parsed 13') > 0, + '"Expected 16 tests, parsed 13" should occur in output', ) } ) }) - const badCountFailing = 'missing-assertions-failing.txt' t.test(`exit(1) "${badCountFailing}" | tap-arc`, (t) => { t.plan(3) exec( - `cat ${join(mockPath, badCountFailing)} | node src/index.js`, + `cat ${join(mockPath, 'tape', badCountFailing)} | node src/index.js`, (error, stdout, stderr) => { t.ok(error, `"${badCountFailing}" creates an error`) t.notOk(stderr, 'stderror should be empty') diff --git a/test/formatting-test.js b/test/formatting-test.js index 367c08b..1960a49 100644 --- a/test/formatting-test.js +++ b/test/formatting-test.js @@ -1,57 +1,206 @@ import { Readable } from 'stream' +import stripAnsi from 'strip-ansi' import test from 'tape' import tapArc from '../src/tap-arc.js' const TAP = { - IN: { - comment: '# Comment', - ok: 'ok 1 should be truthy', - notOk: 'not ok 2 should be falsy', - plan: '1..2', - planTests: '# tests 2', - planPass: '# pass 1', - planFail: '# fail 1', - }, + IN: [ + 'TAP version 13', + '# Sample passing tests', + 'ok 1 Regex: match pass', + 'Arbitrary logs supported', + 'ok 2 Regex: doesNotMatch pass', + 'ok 3 A deeply equal array', + 'ok 4 A skipped test # SKIP', + 'ok 5 A deeply equal object', + '# TODO Some tests marked as "todo"', + 'ok 6 A passing TODO # TODO', + 'not ok 7 A failing TODO # TODO', + ' ---', + ' operator: fail', + ' at: Test. (/test/mock/create-simple-tap.cjs:19:7)', + ' ...', + '# Some failing tests', + 'not ok 8 should be strictly equal', + ' ---', + ' operator: equal', + ' expected: 666', + ' actual: 66', + ' at: Test. (/test/mock/create-simple-tap.cjs:27:5)', + ' stack: |-', + ' Error: should be strictly equal', + ' at Test.assert [as _assert] (/node_modules/tape/lib/test.js:479:48)', + ' at Test.strictEqual (/node_modules/tape/lib/test.js:643:7)', + ' at Test. (/test/mock/create-simple-tap.cjs:27:5)', + ' at Test.run (/node_modules/tape/lib/test.js:113:28)', + ' at Immediate.next [as _onImmediate] (/node_modules/tape/lib/results.js:157:7)', + ' at process.processImmediate (node:internal/timers:476:21)', + ' ...', + 'not ok 9 should be strictly equal', + ' ---', + ' operator: equal', + ' expected: \'Good dog\'', + ' actual: \'Bad dog\'', + ' at: Test. (/test/mock/create-simple-tap.cjs:28:5)', + ' stack: |-', + ' Error: should be strictly equal', + ' at Test.assert [as _assert] (/node_modules/tape/lib/test.js:479:48)', + ' at Test.strictEqual (/node_modules/tape/lib/test.js:643:7)', + ' at Test. (/test/mock/create-simple-tap.cjs:28:5)', + ' at Test.run (/node_modules/tape/lib/test.js:113:28)', + ' at Immediate.next [as _onImmediate] (/node_modules/tape/lib/results.js:157:7)', + ' at process.processImmediate (node:internal/timers:476:21)', + ' ...', + 'not ok 10 Regex: match fail', + ' ---', + ' operator: match', + ' expected: /^A/', + ' actual: \'atreides\'', + ' at: Test. (/test/mock/create-simple-tap.cjs:29:5)', + ' stack: |-', + ' Error: Regex: match fail', + ' at Test.assert [as _assert] (/node_modules/tape/lib/test.js:479:48)', + ' at Test.match (/node_modules/tape/lib/test.js:900:8)', + ' at Test. (/test/mock/create-simple-tap.cjs:29:5)', + ' at Test.run (/node_modules/tape/lib/test.js:113:28)', + ' at Immediate.next [as _onImmediate] (/node_modules/tape/lib/results.js:157:7)', + ' at process.processImmediate (node:internal/timers:476:21)', + ' ...', + '# Nested tests', + 'not ok 11 Sub-test partial array failure', + ' ---', + ' operator: deepEqual', + ' expected: [ \'foo\', \'bar\', \'foobar baz\' ]', + ' actual: [ \'foo\', \'bar\', \'baz\' ]', + ' at: Test. (/test/mock/create-simple-tap.cjs:32:8)', + ' stack: |-', + ' Error: Sub-test partial array failure', + ' at Test.assert [as _assert] (/node_modules/tape/lib/test.js:479:48)', + ' at Test.tapeDeepEqual (/node_modules/tape/lib/test.js:720:7)', + ' at Test. (/test/mock/create-simple-tap.cjs:32:8)', + ' at Test.run (/node_modules/tape/lib/test.js:113:28)', + ' at Test._end (/node_modules/tape/lib/test.js:385:5)', + ' at Immediate._onImmediate (/node_modules/tape/lib/test.js:154:9)', + ' at process.processImmediate (node:internal/timers:476:21)', + ' ...', + 'not ok 12 A small object deepEqual failure', + ' ---', + ' operator: deepEqual', + ' expected: |-', + ' { a: \'bar\', b: [ 420 ] }', + ' actual: |-', + ' { a: \'foo\', b: [ 42 ], c: \'baz\' }', + ' at: Test. (/test/mock/create-simple-tap.cjs:37:8)', + ' stack: |-', + ' Error: A small object deepEqual failure', + ' at Test.assert [as _assert] (/node_modules/tape/lib/test.js:479:48)', + ' at Test.tapeDeepEqual (/node_modules/tape/lib/test.js:720:7)', + ' at Test. (/test/mock/create-simple-tap.cjs:37:8)', + ' at Test.run (/node_modules/tape/lib/test.js:113:28)', + ' at Test._end (/node_modules/tape/lib/test.js:385:5)', + ' at Immediate._onImmediate (/node_modules/tape/lib/test.js:154:9)', + ' at process.processImmediate (node:internal/timers:476:21)', + ' ...', + '', + '1..12', + '# tests 12', + '# pass 7', + '# fail 5', + ], OUT: [ - '\x1B[1m\x1B[4mComment\x1B[24m\x1B[22m', - '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[32mโœ“\x1B[39m\x1B[22m \x1B[2mshould be truthy\x1B[22m', - '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[31mโœ—\x1B[39m\x1B[22m [2] \x1B[31mshould be falsy\x1B[39m', - '\x1B[31mFailed tests:\x1B[39m There was \x1B[31m1\x1B[39m failure', - '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[31mโœ—\x1B[39m\x1B[22m [2] \x1B[31mshould be falsy\x1B[39m', - 'total: 2', - '\x1B[32mpassing: 1\x1B[39m', - '\x1B[31mfailing: 1\x1B[39m' + '\x1B[1m\x1B[4mSample passing tests\x1B[24m\x1B[22m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[32mโœ“\x1B[39m\x1B[22m \x1B[2mRegex: match pass\x1B[22m', + '\x1B[3mArbitrary logs supported\x1B[23m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[32mโœ“\x1B[39m\x1B[22m \x1B[2mRegex: doesNotMatch pass\x1B[22m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[32mโœ“\x1B[39m\x1B[22m \x1B[2mA deeply equal array\x1B[22m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[36mโ‡ฅ\x1B[39m\x1B[22m \x1B[2mA skipped test\x1B[22m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[32mโœ“\x1B[39m\x1B[22m \x1B[2mA deeply equal object\x1B[22m', + '\x1B[1m\x1B[4mSome tests marked as "todo"\x1B[24m\x1B[22m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[36mโฃ\x1B[39m\x1B[22m \x1B[2mA passing TODO\x1B[22m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[36mโฃ\x1B[39m\x1B[22m \x1B[2mA failing TODO\x1B[22m', + '\x1B[1m\x1B[4mSome failing tests\x1B[24m\x1B[22m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[31mโœ—\x1B[39m\x1B[22m [8] \x1B[31mshould be strictly equal\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22mExpected \x1B[33m666\x1B[39m but got \x1B[34m66\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2mAt: Test. (/test/mock/create-simple-tap.cjs:27:5)\x1B[22m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[31mโœ—\x1B[39m\x1B[22m [9] \x1B[31mshould be strictly equal\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22mActual: \x1B[34mBad\x1B[39m dog', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22mExpected: \x1B[33mGood\x1B[39m dog', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2mAt: Test. (/test/mock/create-simple-tap.cjs:28:5)\x1B[22m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[31mโœ—\x1B[39m\x1B[22m [10] \x1B[31mRegex: match fail\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22mExpected "\x1B[34matreides\x1B[39m" to match \x1B[33m/^A/\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2mAt: Test. (/test/mock/create-simple-tap.cjs:29:5)\x1B[22m', + '\x1B[1m\x1B[4mNested tests\x1B[24m\x1B[22m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[31mโœ—\x1B[39m\x1B[22m [11] \x1B[31mSub-test partial array failure\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22mArray [', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m "foo",', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m "bar",', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m \x1B[34m"baz"\x1B[39m,', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m \x1B[33m"foobar baz"\x1B[39m,', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m]', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2mAt: Test. (/test/mock/create-simple-tap.cjs:32:8)\x1B[22m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[31mโœ—\x1B[39m\x1B[22m [12] \x1B[31mA small object deepEqual failure\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22mObject {', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[34m "a": "foo",\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[34m\x1B[39m\x1B[33m "a": "bar",\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[33m\x1B[39m "b": [', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[34m 42\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[34m\x1B[39m\x1B[33m 420\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[33m\x1B[39m ],', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[34m "c": "baz"\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[34m\x1B[39m}', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[2mAt: Test. (/test/mock/create-simple-tap.cjs:37:8)\x1B[22m', + '\x1B[31mFailed tests:\x1B[39m There were \x1B[31m5\x1B[39m failures', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[31mโœ—\x1B[39m\x1B[22m [8] \x1B[31mshould be strictly equal\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[31mโœ—\x1B[39m\x1B[22m [9] \x1B[31mshould be strictly equal\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[31mโœ—\x1B[39m\x1B[22m [10] \x1B[31mRegex: match fail\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[31mโœ—\x1B[39m\x1B[22m [11] \x1B[31mSub-test partial array failure\x1B[39m', + '\x1B[2m \x1B[22m\x1B[2m \x1B[22m\x1B[1m\x1B[31mโœ—\x1B[39m\x1B[22m [12] \x1B[31mA small object deepEqual failure\x1B[39m', + 'total: 12', + '\x1B[32mpassing: 7\x1B[39m', + '\x1B[31mfailing: 5\x1B[39m', + '\x1B[2mskipped: 1\x1B[22m', + '\x1B[2mtodo: 2\x1B[22m', ], } test('basic output formatting', (t) => { - const readable = new Readable({ read () { } }) - const parser = tapArc({ - color: true, - help: false, - pessimistic: false, - failBadCount: false, - verbose: false, - debug: false, - }) + const input = new Readable() let chunks = `` - parser.on('data', (chunk) => { - chunks += chunk.toString() - }) + const output = { + write (string) { chunks += string } + } + + const parser = tapArc( + input, + output, + { + color: true, + help: false, + showDiff: true, + pessimistic: false, + failBadCount: false, + verbose: false, + tap: false, + debug: false, + } + ) + + for (const line of TAP.IN) input.push(`${line}\n`) + input.push(null) parser.on('end', () => { + t.plan(2) + const actual = chunks.trim().split('\n').slice(0, -1).filter(l => l.length > 0) // remove timer - const expected = Object.keys(TAP.OUT).map((key) => TAP.OUT[key]) - t.deepEqual(actual, expected, 'should print expected output') - t.end() - }) - readable.pipe(parser) + t.deepEqual(actual, TAP.OUT, 'should print expected output') - const lines = Object.keys(TAP.IN).map((key) => TAP.IN[key]) - for (const line of lines) readable.push(`${line}\n`) + // this test helps visualize when output differs without the ANSI codes + const actualNoAnsi = actual.map(stripAnsi) + const expectedNoAnsi = TAP.OUT.map(stripAnsi) + // console.log('=========\n', actualNoAnsi.join('\n'), '\n=========') - readable.push(null) + t.deepEqual(actualNoAnsi, expectedNoAnsi, 'should print expected output without ANSI codes') + }) }) - diff --git a/test/mock/create-passing-tap.cjs b/test/mock/create-passing-tap.cjs index 137d15d..fbc8541 100644 --- a/test/mock/create-passing-tap.cjs +++ b/test/mock/create-passing-tap.cjs @@ -4,8 +4,8 @@ const test = require('tape') test('basic arithmetic', (t) => { - t.equal(2 + 3, 5) - t.equal(7 * 8 + 9, 65) + t.equal(5, 5) + t.equal(65, 65) t.end() }) @@ -13,8 +13,8 @@ test('basic arithmetic', (t) => { test('deep equality', (t) => { t.plan(2) - t.deepEqual([ 3, 4, 5 ], [ 3, 4, 2 + 3 ]) - t.deepEqual({ a: 7, b: [ 8, 9 ] }, { a: 3 + 4, b: [ 4 * 2 ].concat(3 * 3) }) + t.deepEqual([ 3, 4, 5 ], [ 3, 4, 5 ]) + t.deepEqual({ a: 7, b: [ 8, 9 ] }, { a: 7, b: [ 8 ].concat(9) }) }) test('comparing booleans', (t) => { @@ -25,7 +25,7 @@ test('comparing booleans', (t) => { test('negatives', (t) => { t.plan(3) - t.notEqual(1 + 2, 5) + t.notEqual(3, 5) t.notDeepEqual([ 1, 2 ], [ 12 ]) t.notOk(false) }) @@ -49,27 +49,27 @@ test('map with elements', (t) => { test('more info', (t) => { t.plan(2) - t.equal(1 + 2, 3, 'basic arithmetic still works') - t.ok(3 + 4 > 5, 'inequalities are as we might expect') + t.equal(3, 3, 'basic arithmetic still works') + t.ok(7 > 5, 'inequalities are as we might expect') }) test('asynchronous results', (t) => { t.plan(2) - t.equal(2 + 3, 5) + t.equal(5, 5) setTimeout(function () { - t.equal(5 + 5, 10) + t.equal(10, 10) }, 500) }) test('nested', (t) => { - t.test((st) => { + t.test('a nested test 1', (st) => { st.plan(1) - st.equal(1 + 2, 3) + st.equal(3, 3) }) - t.test((st) => { + t.test('a nested test 2', (st) => { st.plan(1) setTimeout(function () { st.pass() diff --git a/test/mock/missing-assertions-failing.txt b/test/mock/tape/missing-assertions-failing.tap similarity index 100% rename from test/mock/missing-assertions-failing.txt rename to test/mock/tape/missing-assertions-failing.tap diff --git a/test/mock/missing-assertions-passing.txt b/test/mock/tape/missing-assertions-passing.tap similarity index 100% rename from test/mock/missing-assertions-passing.txt rename to test/mock/tape/missing-assertions-passing.tap diff --git a/test/smoke.js b/test/smoke.js deleted file mode 100644 index 203d54d..0000000 --- a/test/smoke.js +++ /dev/null @@ -1,6 +0,0 @@ -// โ„น๏ธ Smoke test CLI program with bare minimum Parser - -// eslint-disable-next-line import/no-unresolved -import { Parser } from 'tap-parser' -const p = new Parser(console.log) -process.stdin.pipe(p)