From e69570acf316f1dbc3350d0e8d9e19c75812864f Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Sat, 11 Jan 2025 08:10:10 -0800 Subject: [PATCH 1/5] `npm audit fix` with npm@11.0.0 --- package-lock.json | 184 ++++++++++++++++++++-------------------------- 1 file changed, 81 insertions(+), 103 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4905611..203e63c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -558,10 +558,11 @@ } }, "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -904,10 +905,11 @@ "dev": true }, "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==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -918,12 +920,13 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -934,12 +937,6 @@ } } }, - "node_modules/debug/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/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -1813,32 +1810,32 @@ } }, "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" }, "bin": { "_mocha": "bin/_mocha", @@ -1846,17 +1843,24 @@ }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" } }, "node_modules/mocha/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -1874,37 +1878,26 @@ } }, "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "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" + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": "*" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/mocha/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -1915,10 +1908,11 @@ } }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -1926,15 +1920,6 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/minimatch/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": { - "balanced-match": "^1.0.0" - } - }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -1956,18 +1941,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", @@ -2416,6 +2389,7 @@ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -2518,7 +2492,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/sax": { "version": "1.3.0", @@ -2536,10 +2511,11 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -2951,10 +2927,11 @@ "dev": true }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "7.0.0", @@ -3079,10 +3056,11 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } From 52f8ff29573d5bb9b149153b05da8ff8697b8e73 Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Sat, 11 Jan 2025 08:13:59 -0800 Subject: [PATCH 2/5] Update to nyc@^17.1 --- package-lock.json | 484 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 243 insertions(+), 243 deletions(-) diff --git a/package-lock.json b/package-lock.json index 203e63c..c7d771d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,7 @@ "@types/xml2js": "^0.4.11", "chai": "^4.2.0", "mocha": "^10.2.0", - "nyc": "^15.0.1", + "nyc": "^17.1.0", "prettier": "^2.1.2", "ts-node": "^8.10.2", "tslint": "^5.20.1", @@ -39,56 +39,61 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", + "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", - "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.9", - "@babel/parser": "^7.23.9", - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -107,32 +112,36 @@ "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 + "dev": true, + "license": "MIT" }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", + "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@babel/parser": "^7.26.5", + "@babel/types": "^7.26.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -140,63 +149,30 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -205,90 +181,59 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "node_modules/@babel/parser": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz", + "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/types": "^7.26.5" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -297,33 +242,32 @@ } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.5.tgz", + "integrity": "sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.5", + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.5", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -332,14 +276,14 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", + "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -445,48 +389,53 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -686,9 +635,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", - "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, "funding": [ { @@ -704,11 +653,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001580", - "electron-to-chromium": "^1.4.648", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -757,9 +707,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001584", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001584.tgz", - "integrity": "sha512-LOz7CCQ9M1G7OjJOF9/mzmqmj3jE/7VOmrfw6Mgs0E8cjOsbRXQJHsPBfmBOXDskXKrHLyyW3n7kpDW/4BsfpQ==", + "version": "1.0.30001692", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz", + "integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==", "dev": true, "funding": [ { @@ -774,7 +724,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chai": { "version": "4.4.1", @@ -982,10 +933,11 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.656", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.656.tgz", - "integrity": "sha512-9AQB5eFTHyR3Gvt2t/NwR0le2jBSUNwCnMbUCejFWHD+so4tH40/dRLgoE+jxlPeWS43XJewyvCv+I8LPMl49Q==", - "dev": true + "version": "1.5.80", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.80.tgz", + "integrity": "sha512-LTrKpW0AqIuHwmlVNV+cjFYTnXtM9K37OGhpe0ZI10ScPSxqVSryZHIY3WnCS5NSYbBODRTZyhRMS2h5FAEqAw==", + "dev": true, + "license": "ISC" }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -1000,10 +952,11 @@ "dev": true }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1149,6 +1102,7 @@ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1216,6 +1170,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -1448,18 +1403,33 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=8" + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/istanbul-lib-processinfo": { @@ -1593,7 +1563,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", @@ -1608,15 +1579,16 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json5": { @@ -1624,6 +1596,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -1752,6 +1725,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } @@ -1954,10 +1928,11 @@ } }, "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 + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -1969,10 +1944,11 @@ } }, "node_modules/nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-17.1.0.tgz", + "integrity": "sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", @@ -1981,12 +1957,12 @@ "decamelize": "^1.2.0", "find-cache-dir": "^3.2.0", "find-up": "^4.1.0", - "foreground-child": "^2.0.0", + "foreground-child": "^3.3.0", "get-package-type": "^0.1.0", "glob": "^7.1.6", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-instrument": "^6.0.2", "istanbul-lib-processinfo": "^2.0.2", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", @@ -2006,7 +1982,7 @@ "nyc": "bin/nyc.js" }, "engines": { - "node": ">=8.9" + "node": ">=18" } }, "node_modules/nyc/node_modules/ansi-styles": { @@ -2066,6 +2042,36 @@ "node": ">=8" } }, + "node_modules/nyc/node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nyc/node_modules/foreground-child/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, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/nyc/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -2276,10 +2282,11 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -2679,15 +2686,6 @@ "node": ">=8" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2857,9 +2855,9 @@ "dev": true }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", "dev": true, "funding": [ { @@ -2875,9 +2873,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -3035,7 +3034,8 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "16.2.0", diff --git a/package.json b/package.json index 07fe0be..3b4fe4b 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@types/xml2js": "^0.4.11", "chai": "^4.2.0", "mocha": "^10.2.0", - "nyc": "^15.0.1", + "nyc": "^17.1.0", "prettier": "^2.1.2", "ts-node": "^8.10.2", "tslint": "^5.20.1", From 885a596e2bfcbf718e9a0e22d463f7a70a710ff1 Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Sat, 11 Jan 2025 11:52:52 -0800 Subject: [PATCH 3/5] Format codebase --- src/common/index.ts | 5 +- src/snapshot.ts | 5 +- src/unit.ts | 40 +- src/unit/reporter.ts | 645 ++++++++++++------------ test/unit/unit/reporter.test.ts | 849 +++++++++++++++++--------------- 5 files changed, 805 insertions(+), 739 deletions(-) diff --git a/src/common/index.ts b/src/common/index.ts index 95fb007..2ac1b36 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -104,7 +104,10 @@ export function loadConfiguration( {}, ...grammars.filter((x) => x.language).map((x) => ({ [x.language || '']: x.scopeName })) ) - let extToLang = Object.assign({}, ...ys.map((x: any) => (x.extensions || []).map((e: any) => ({ [e]: x.id }))).flat()) + let extToLang = Object.assign( + {}, + ...ys.map((x: any) => (x.extensions || []).map((e: any) => ({ [e]: x.id }))).flat() + ) extensionToScope = (ext) => scope || langToScope[extToLang[ext]] } return { grammars, extensionToScope } diff --git a/src/snapshot.ts b/src/snapshot.ts index a2fc8ba..509bf15 100644 --- a/src/snapshot.ts +++ b/src/snapshot.ts @@ -75,7 +75,7 @@ let { grammars, extensionToScope } = loadConfiguration(options.config, options.s const limiter = new Bottleneck({ maxConcurrent: 8, - minTime: 0 + minTime: 0 }) const registry = createRegistry(grammars) @@ -88,7 +88,8 @@ const testResults: Promise = Promise.all( console.log('No scope is associated with the file.') return TestFailed } - return limiter.schedule(() => getVSCodeTokens(registry, scope, src)) + return limiter + .schedule(() => getVSCodeTokens(registry, scope, src)) .then((tokens) => { if (fs.existsSync(filename + '.snap')) { if (options.updateSnapshot) { diff --git a/src/unit.ts b/src/unit.ts index 99a4a6d..a01f484 100644 --- a/src/unit.ts +++ b/src/unit.ts @@ -7,14 +7,16 @@ import glob from 'glob' import Bottleneck from 'bottleneck' import { runGrammarTestCase, parseGrammarTestCase, GrammarTestCase, TestFailure } from './unit/index' import { - Reporter, CompositeReporter, - ConsoleCompactReporter, ConsoleFullReporter, - XunitGenericReporter, XunitGitlabReporter + Reporter, + CompositeReporter, + ConsoleCompactReporter, + ConsoleFullReporter, + XunitGenericReporter, + XunitGitlabReporter } from './unit/reporter' import { createRegistry, loadConfiguration, IGrammarConfig } from './common/index' - let packageJson = require('../package.json') function collectGrammarOpts(value: String, previous: String[]): String[] { @@ -31,8 +33,14 @@ program ) .option('--config ', 'Path to the language configuration, package.json by default') .option('-c, --compact', 'Display output in the compact format, which is easier to use with VSCode problem matchers') - .option('--xunit-report ', 'Path to directory where test reports in the XUnit format will be emitted in addition to console output') - .option('--xunit-format ', 'Format of XML reports generated when --xunit-report is used. `gitlab` format is suitable for viewing the results in GitLab CI/CD web GUI') + .option( + '--xunit-report ', + 'Path to directory where test reports in the XUnit format will be emitted in addition to console output' + ) + .option( + '--xunit-format ', + 'Format of XML reports generated when --xunit-report is used. `gitlab` format is suitable for viewing the results in GitLab CI/CD web GUI' + ) .version(packageJson.version) .argument( '', @@ -42,7 +50,6 @@ program const options = program.opts() - const TestFailed = -1 const TestSuccessful = 0 @@ -57,16 +64,14 @@ if (options.validate) { } } - -const consoleReporter = options.compact - ? new ConsoleCompactReporter() - : new ConsoleFullReporter() +const consoleReporter = options.compact ? new ConsoleCompactReporter() : new ConsoleFullReporter() const reporter: Reporter = options.xunitReport ? new CompositeReporter( - consoleReporter, - options.xunitFormat === 'gitlab' - ? new XunitGitlabReporter(options.xunitReport) - : new XunitGenericReporter(options.xunitReport)) + consoleReporter, + options.xunitFormat === 'gitlab' + ? new XunitGitlabReporter(options.xunitReport) + : new XunitGenericReporter(options.xunitReport) + ) : consoleReporter const rawTestCases = program.args.map((x) => glob.sync(x)).flat() @@ -78,7 +83,7 @@ if (rawTestCases.length === 0) { const limiter = new Bottleneck({ maxConcurrent: 8, - minTime: 0 + minTime: 0 }) const testResults: Promise = Promise.all( @@ -93,7 +98,8 @@ const testResults: Promise = Promise.all( }) } let testCase = tc as GrammarTestCase - return limiter.schedule(() => runGrammarTestCase(registry, testCase)) + return limiter + .schedule(() => runGrammarTestCase(registry, testCase)) .then((failures) => { reporter.reportTestResult(filename, testCase, failures) return failures.length === 0 ? TestSuccessful : TestFailed diff --git a/src/unit/reporter.ts b/src/unit/reporter.ts index a4337b8..10f851b 100644 --- a/src/unit/reporter.ts +++ b/src/unit/reporter.ts @@ -4,143 +4,146 @@ import * as p from 'path' import * as tty from 'tty' import { EOL } from 'os' import { sep } from 'path' -import { GrammarTestCase, LineAssertion, TestFailure } from "./model" +import { GrammarTestCase, LineAssertion, TestFailure } from './model' export interface Reporter { - reportTestResult(filename: string, testCase: GrammarTestCase, failures: TestFailure[]): void - reportParseError(filename: string, error: any): void - reportGrammarTestError(filename: string, testCase: GrammarTestCase, reason: any): void - reportSuiteResult(): void + reportTestResult(filename: string, testCase: GrammarTestCase, failures: TestFailure[]): void + reportParseError(filename: string, error: any): void + reportGrammarTestError(filename: string, testCase: GrammarTestCase, reason: any): void + reportSuiteResult(): void } export class CompositeReporter implements Reporter { - - private reporters: Reporter[] - - constructor(...reporters: Reporter[]) { - this.reporters = reporters - } - - reportTestResult(filename: string, testCase: GrammarTestCase, failures: TestFailure[]): void { - this.reporters.forEach(r => r.reportTestResult(filename, testCase, failures)) - } - reportGrammarTestError(filename: string, testCase: GrammarTestCase, reason: any): void { - this.reporters.forEach(r => r.reportGrammarTestError(filename, testCase, reason)) - } - - reportParseError(filename: string, error: any): void { - this.reporters.forEach(r => r.reportParseError(filename, error)) - } - - reportSuiteResult(): void { - this.reporters.forEach(r => r.reportSuiteResult()) - } + private reporters: Reporter[] + + constructor(...reporters: Reporter[]) { + this.reporters = reporters + } + + reportTestResult(filename: string, testCase: GrammarTestCase, failures: TestFailure[]): void { + this.reporters.forEach((r) => r.reportTestResult(filename, testCase, failures)) + } + reportGrammarTestError(filename: string, testCase: GrammarTestCase, reason: any): void { + this.reporters.forEach((r) => r.reportGrammarTestError(filename, testCase, reason)) + } + + reportParseError(filename: string, error: any): void { + this.reporters.forEach((r) => r.reportParseError(filename, error)) + } + + reportSuiteResult(): void { + this.reporters.forEach((r) => r.reportSuiteResult()) + } } interface XunitSuite { - readonly file: string - readonly name: string - readonly cases: XunitCase[] + readonly file: string + readonly name: string + readonly cases: XunitCase[] } interface XunitCase { - readonly name: string - readonly classname?: string - readonly failures: XunitFailure[] + readonly name: string + readonly classname?: string + readonly failures: XunitFailure[] } interface XunitFailure { - readonly type: 'error' | 'failure' - readonly message: string - readonly body: string + readonly type: 'error' | 'failure' + readonly message: string + readonly body: string } abstract class XunitReportPerTestReporter implements Reporter, Colorizer { - // follows this schema https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd - // produces report in a way which looks nice when viewed in GitLab CI/CD web GUI, but is not neccesarily semantically correct - private suites: XunitSuite[] = [] - - constructor(private reportPath: string) { } - - abstract reportTestResult(filename: string, parsedFile: GrammarTestCase, failures: TestFailure[]): void + // follows this schema https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd + // produces report in a way which looks nice when viewed in GitLab CI/CD web GUI, but is not neccesarily semantically correct + private suites: XunitSuite[] = [] - protected abstract caseClassname(filename: string): string | undefined + constructor(private reportPath: string) {} - protected abstract suiteFailuresCount(suite: XunitSuite): number + abstract reportTestResult(filename: string, parsedFile: GrammarTestCase, failures: TestFailure[]): void - protected abstract suiteErrorsCount(suite: XunitSuite): number - - reportParseError(filename: string, error: any): void { - const suite = this.getSuite(filename) - suite.cases.push({ - name: "Parse test file", - classname: this.caseClassname(filename), - failures: [{ - type: 'error', - message: "Failed to parse test file", - body: `${error}` - }] - }) - } - - reportGrammarTestError(filename: string, parsedFile: GrammarTestCase, reason: any): void { - const suite = this.getSuite(filename, parsedFile) - suite.cases.push({ - name: "Run grammar tests", - classname: this.caseClassname(filename), - failures: [{ - type: 'error', - message: "Error when running grammar tests", - body: `${reason}` - }] - }) - } + protected abstract caseClassname(filename: string): string | undefined - red(text: string): string { - return text - } - gray(text: string): string { - return text - } - whiteBright(text: string): string { - return text - } + protected abstract suiteFailuresCount(suite: XunitSuite): number - protected getSuite(filename: string, parsedFile?: GrammarTestCase): XunitSuite { - const suite: XunitSuite = { - file: `TEST-${filename.replaceAll(sep, '.')}.xml`, - name: parsedFile?.metadata.description || filename, - cases: [] - } - this.suites.push(suite) - return suite - } + protected abstract suiteErrorsCount(suite: XunitSuite): number - protected getCase(suite: XunitSuite, filename: string, assertion: LineAssertion): XunitCase { - const name = `${filename}:${assertion.testCaseLineNumber + 1}` - for (const c of suite.cases) { - if (c.name === name) { - return c - } + reportParseError(filename: string, error: any): void { + const suite = this.getSuite(filename) + suite.cases.push({ + name: 'Parse test file', + classname: this.caseClassname(filename), + failures: [ + { + type: 'error', + message: 'Failed to parse test file', + body: `${error}` } - const c: XunitCase = { - name, - classname: this.caseClassname(filename), - failures: [] + ] + }) + } + + reportGrammarTestError(filename: string, parsedFile: GrammarTestCase, reason: any): void { + const suite = this.getSuite(filename, parsedFile) + suite.cases.push({ + name: 'Run grammar tests', + classname: this.caseClassname(filename), + failures: [ + { + type: 'error', + message: 'Error when running grammar tests', + body: `${reason}` } - suite.cases.push(c) + ] + }) + } + + red(text: string): string { + return text + } + gray(text: string): string { + return text + } + whiteBright(text: string): string { + return text + } + + protected getSuite(filename: string, parsedFile?: GrammarTestCase): XunitSuite { + const suite: XunitSuite = { + file: `TEST-${filename.replaceAll(sep, '.')}.xml`, + name: parsedFile?.metadata.description || filename, + cases: [] + } + this.suites.push(suite) + return suite + } + + protected getCase(suite: XunitSuite, filename: string, assertion: LineAssertion): XunitCase { + const name = `${filename}:${assertion.testCaseLineNumber + 1}` + for (const c of suite.cases) { + if (c.name === name) { return c + } } + const c: XunitCase = { + name, + classname: this.caseClassname(filename), + failures: [] + } + suite.cases.push(c) + return c + } - reportSuiteResult(): void { - fs.mkdirSync(this.reportPath, { recursive: true }) - for (const suite of this.suites.values()) { - fs.writeFileSync(p.resolve(this.reportPath, suite.file), this.renderSuite(suite)) - } + reportSuiteResult(): void { + fs.mkdirSync(this.reportPath, { recursive: true }) + for (const suite of this.suites.values()) { + fs.writeFileSync(p.resolve(this.reportPath, suite.file), this.renderSuite(suite)) } + } - private renderSuite(s: XunitSuite): string { - return ` + private renderSuite(s: XunitSuite): string { + return ` ${s.cases.reduce((a, c) => a + "\n" + this.renderCase(c), "")} +>${s.cases.reduce((a, c) => a + '\n' + this.renderCase(c), '')} ` - } - - private renderCase(c: XunitCase): string { - return ` ${c.failures.reduce((a, f) => a + "\n" + this.renderFailure(f), "")}${this.newlineIfHasItems(c.failures)}` - } - - private classnameAttr(c: XunitCase): string { - return c.classname ? `classname="${c.classname}" ` : "" - } - - private renderFailure(f: XunitFailure): string { - return ` <${f.type} message="${f.message}" type="${f.type === 'failure' ? 'TestFailure' : 'GrammarTestError'}">${this.escapedXml(f.body)}` - } - - private newlineIfHasItems(arr: any[]): string { - return arr.length === 0 ? "" : "\n" - } - - private escapedXml(raw: string): string { - return raw - .replace(/&/g, '&') - .replace(/"/g, '"') - .replace(/'/g, ''') - .replace(//g, '>') - } + } + + private renderCase(c: XunitCase): string { + return ` ${c.failures.reduce( + (a, f) => a + '\n' + this.renderFailure(f), + '' + )}${this.newlineIfHasItems(c.failures)}` + } + + private classnameAttr(c: XunitCase): string { + return c.classname ? `classname="${c.classname}" ` : '' + } + + private renderFailure(f: XunitFailure): string { + return ` <${f.type} message="${f.message}" type="${ + f.type === 'failure' ? 'TestFailure' : 'GrammarTestError' + }">${this.escapedXml(f.body)}` + } + + private newlineIfHasItems(arr: any[]): string { + return arr.length === 0 ? '' : '\n' + } + + private escapedXml(raw: string): string { + return raw + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>') + } } export class XunitGenericReporter extends XunitReportPerTestReporter { + // follows this schema https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd and produces one report file per test file + // if some CI requires single report file may also implement reporter for this format https://github.com/windyroad/JUnit-Schema/blob/master/JUnit.xsd - // follows this schema https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd and produces one report file per test file - // if some CI requires single report file may also implement reporter for this format https://github.com/windyroad/JUnit-Schema/blob/master/JUnit.xsd + constructor(reportPath: string) { + super(reportPath) + } - constructor(reportPath: string) { - super(reportPath) - } + reportTestResult(filename: string, parsedFile: GrammarTestCase, failures: TestFailure[]): void { + const suite = this.getSuite(filename, parsedFile) - reportTestResult(filename: string, parsedFile: GrammarTestCase, failures: TestFailure[]): void { - const suite = this.getSuite(filename, parsedFile) - - // source line in the test file is treated as testcase - // and every failed assertion associated with this source line is failure in that testcase - - for (const assertion of parsedFile.assertions) { - const c = this.getCase(suite, filename, assertion); - for (const failure of failures) { - if (failure.line !== assertion.testCaseLineNumber) { - continue - } - const { l, s, e } = getCorrectedOffsets(failure) - - const bodyLines: string[] = [] - printSourceLine(parsedFile, failure, '', 200, m => bodyLines.push(m), this) - printReason(parsedFile, failure, '', m => bodyLines.push(m), this) - c.failures.push({ - type: 'failure', - message: `Assertion failed at ${l}:${s}:${e}`, - body: bodyLines.join("\n") - }) - } - } - } + // source line in the test file is treated as testcase + // and every failed assertion associated with this source line is failure in that testcase - protected caseClassname(filename: string): undefined { - return undefined - } - protected suiteFailuresCount(s: XunitSuite): number { - return s.cases.reduce((accSuite, c) => accSuite + c.failures.reduce((accCase, f) => accCase + (f.type === 'failure' ? 1 : 0), 0), 0) - } - protected suiteErrorsCount(s: XunitSuite): number { - return s.cases.reduce((accSuite, c) => accSuite + c.failures.reduce((accCase, f) => accCase + (f.type === 'error' ? 1 : 0), 0), 0) - } + for (const assertion of parsedFile.assertions) { + const c = this.getCase(suite, filename, assertion) + for (const failure of failures) { + if (failure.line !== assertion.testCaseLineNumber) { + continue + } + const { l, s, e } = getCorrectedOffsets(failure) + + const bodyLines: string[] = [] + printSourceLine(parsedFile, failure, '', 200, (m) => bodyLines.push(m), this) + printReason(parsedFile, failure, '', (m) => bodyLines.push(m), this) + c.failures.push({ + type: 'failure', + message: `Assertion failed at ${l}:${s}:${e}`, + body: bodyLines.join('\n') + }) + } + } + } + + protected caseClassname(filename: string): undefined { + return undefined + } + protected suiteFailuresCount(s: XunitSuite): number { + return s.cases.reduce( + (accSuite, c) => accSuite + c.failures.reduce((accCase, f) => accCase + (f.type === 'failure' ? 1 : 0), 0), + 0 + ) + } + protected suiteErrorsCount(s: XunitSuite): number { + return s.cases.reduce( + (accSuite, c) => accSuite + c.failures.reduce((accCase, f) => accCase + (f.type === 'error' ? 1 : 0), 0), + 0 + ) + } } export class XunitGitlabReporter extends XunitReportPerTestReporter { - // follows this schema https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd - // produces report in a way which looks nice when viewed in GitLab CI/CD web GUI, but is not neccesarily semantically correct - - constructor(reportPath: string) { - super(reportPath) - } - - reportTestResult(filename: string, parsedFile: GrammarTestCase, failures: TestFailure[]): void { - const suite = this.getSuite(filename, parsedFile) - - for (const assertion of parsedFile.assertions) { - const c = this.getCase(suite, filename, assertion); - const bodyLines: string[] = [] - for (const failure of failures) { - if (failure.line !== assertion.testCaseLineNumber) { - continue - } - printAssertionLocation(filename, failure, '', m => bodyLines.push(m), this) - printSourceLine(parsedFile, failure, '', 200, m => bodyLines.push(m), this) - printReason(parsedFile, failure, '', m => bodyLines.push(m), this) - bodyLines.push("") - } - if (bodyLines.length > 0) { - c.failures.push({ - type: 'failure', - message: `Failed at soure line ${assertion.testCaseLineNumber + 1}`, - body: bodyLines.join("\n") - }) - } + // follows this schema https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd + // produces report in a way which looks nice when viewed in GitLab CI/CD web GUI, but is not neccesarily semantically correct + + constructor(reportPath: string) { + super(reportPath) + } + + reportTestResult(filename: string, parsedFile: GrammarTestCase, failures: TestFailure[]): void { + const suite = this.getSuite(filename, parsedFile) + + for (const assertion of parsedFile.assertions) { + const c = this.getCase(suite, filename, assertion) + const bodyLines: string[] = [] + for (const failure of failures) { + if (failure.line !== assertion.testCaseLineNumber) { + continue } - } - - protected caseClassname(filename: string): string { - return filename - } - protected suiteFailuresCount(s: XunitSuite): number { - return s.cases.reduce((accSuite, c) => accSuite + (c.failures.some(f => f.type === 'failure') ? 1 : 0), 0) - } - protected suiteErrorsCount(s: XunitSuite): number { - return s.cases.reduce((accSuite, c) => accSuite + (c.failures.some(f => f.type === 'error') ? 1 : 0), 0) - } + printAssertionLocation(filename, failure, '', (m) => bodyLines.push(m), this) + printSourceLine(parsedFile, failure, '', 200, (m) => bodyLines.push(m), this) + printReason(parsedFile, failure, '', (m) => bodyLines.push(m), this) + bodyLines.push('') + } + if (bodyLines.length > 0) { + c.failures.push({ + type: 'failure', + message: `Failed at soure line ${assertion.testCaseLineNumber + 1}`, + body: bodyLines.join('\n') + }) + } + } + } + + protected caseClassname(filename: string): string { + return filename + } + protected suiteFailuresCount(s: XunitSuite): number { + return s.cases.reduce((accSuite, c) => accSuite + (c.failures.some((f) => f.type === 'failure') ? 1 : 0), 0) + } + protected suiteErrorsCount(s: XunitSuite): number { + return s.cases.reduce((accSuite, c) => accSuite + (c.failures.some((f) => f.type === 'error') ? 1 : 0), 0) + } } const symbols = { - ok: '✓', - err: '✖', - dot: '․', - comma: ',', - bang: '!' + ok: '✓', + err: '✖', + dot: '․', + comma: ',', + bang: '!' } if (process.platform === 'win32') { - symbols.ok = '\u221A' - symbols.err = '\u00D7' - symbols.dot = '.' + symbols.ok = '\u221A' + symbols.err = '\u00D7' + symbols.dot = '.' } const Padding = ' ' @@ -290,142 +303,146 @@ let isatty = tty.isatty(1) && tty.isatty(2) let terminalWidth = 75 if (isatty) { - terminalWidth = (process.stdout as tty.WriteStream).getWindowSize()[0] + terminalWidth = (process.stdout as tty.WriteStream).getWindowSize()[0] } function handleGrammarTestError(filename: string, testCase: GrammarTestCase, reason: any): void { - console.log(chalk.red(symbols.err) + ' testcase ' + chalk.gray(filename) + ' aborted due to an error') - console.log(reason) + console.log(chalk.red(symbols.err) + ' testcase ' + chalk.gray(filename) + ' aborted due to an error') + console.log(reason) } function handleParseError(filename: string, error: any): void { - console.log(chalk.red('ERROR') + " can't parse testcase: " + chalk.whiteBright(filename) + '') - console.log(error) + console.log(chalk.red('ERROR') + " can't parse testcase: " + chalk.whiteBright(filename) + '') + console.log(error) } export class ConsoleCompactReporter implements Reporter { - - reportTestResult(filename: string, testCase: GrammarTestCase, failures: TestFailure[]): void { - if (failures.length === 0) { - console.log(chalk.green(symbols.ok) + ' ' + chalk.whiteBright(filename) + ` run successfuly.`) - } else { - failures.forEach((failure) => { - console.log( - `ERROR ${filename}:${failure.line + 1}:${failure.start + 1}:${failure.end + 1} ${this.renderCompactErrorMsg( - testCase, - failure - )}` - ) - }) - } + reportTestResult(filename: string, testCase: GrammarTestCase, failures: TestFailure[]): void { + if (failures.length === 0) { + console.log(chalk.green(symbols.ok) + ' ' + chalk.whiteBright(filename) + ` run successfuly.`) + } else { + failures.forEach((failure) => { + console.log( + `ERROR ${filename}:${failure.line + 1}:${failure.start + 1}:${failure.end + 1} ${this.renderCompactErrorMsg( + testCase, + failure + )}` + ) + }) + } + } + + private renderCompactErrorMsg(testCase: GrammarTestCase, failure: TestFailure): string { + let res = '' + if (failure.missing && failure.missing.length > 0) { + res += `Missing required scopes: [ ${failure.missing.join(' ')} ] ` } - - private renderCompactErrorMsg(testCase: GrammarTestCase, failure: TestFailure): string { - let res = '' - if (failure.missing && failure.missing.length > 0) { - res += `Missing required scopes: [ ${failure.missing.join(' ')} ] ` - } - if (failure.unexpected && failure.unexpected.length > 0) { - res += `Prohibited scopes: [ ${failure.unexpected.join(' ')} ] ` - } - if (failure.actual !== undefined) { - res += `actual scopes: [${failure.actual.join(' ')}]` - } - return res + if (failure.unexpected && failure.unexpected.length > 0) { + res += `Prohibited scopes: [ ${failure.unexpected.join(' ')} ] ` + } + if (failure.actual !== undefined) { + res += `actual scopes: [${failure.actual.join(' ')}]` } + return res + } - reportParseError = handleParseError + reportParseError = handleParseError - reportGrammarTestError = handleGrammarTestError + reportGrammarTestError = handleGrammarTestError - reportSuiteResult(): void { } + reportSuiteResult(): void {} } - export class ConsoleFullReporter implements Reporter { + reportTestResult(filename: string, testCase: GrammarTestCase, failures: TestFailure[]): void { + if (failures.length === 0) { + console.log(chalk.green(symbols.ok) + ' ' + chalk.whiteBright(filename) + ` run successfuly.`) + } else { + console.log(chalk.red(symbols.err + ' ' + filename + ' failed')) + failures.forEach((failure) => { + printAssertionLocation(filename, failure, Padding, console.log, chalk) + printSourceLine(testCase, failure, Padding, terminalWidth, console.log, chalk) + printReason(testCase, failure, Padding, console.log, chalk) - reportTestResult(filename: string, testCase: GrammarTestCase, failures: TestFailure[]): void { - if (failures.length === 0) { - console.log(chalk.green(symbols.ok) + ' ' + chalk.whiteBright(filename) + ` run successfuly.`) - } else { - console.log(chalk.red(symbols.err + ' ' + filename + ' failed')) - failures.forEach((failure) => { - printAssertionLocation(filename, failure, Padding, console.log, chalk) - printSourceLine(testCase, failure, Padding, terminalWidth, console.log, chalk) - printReason(testCase, failure, Padding, console.log, chalk) - - console.log(EOL) - }) - console.log('') - } + console.log(EOL) + }) + console.log('') } + } - reportParseError = handleParseError + reportParseError = handleParseError - reportGrammarTestError = handleGrammarTestError + reportGrammarTestError = handleGrammarTestError - reportSuiteResult(): void { } + reportSuiteResult(): void {} } function printAssertionLocation( - filename: string, failure: TestFailure, - padding: string, - sink: (message: string) => void, colorizer: Colorizer + filename: string, + failure: TestFailure, + padding: string, + sink: (message: string) => void, + colorizer: Colorizer ) { - const { l, s, e } = getCorrectedOffsets(failure) - sink(padding + 'at [' + colorizer.whiteBright(`${filename}:${l}:${s}:${e}`) + ']:') + const { l, s, e } = getCorrectedOffsets(failure) + sink(padding + 'at [' + colorizer.whiteBright(`${filename}:${l}:${s}:${e}`) + ']:') } function getCorrectedOffsets(failure: TestFailure): { - l: number - s: number - e: number + l: number + s: number + e: number } { - return { - l: failure.line + 1, - s: failure.start + 1, - e: failure.end + 1 - } + return { + l: failure.line + 1, + s: failure.start + 1, + e: failure.end + 1 + } } function printSourceLine( - testCase: GrammarTestCase, failure: TestFailure, - padding: string, terminalWidth: number, - sink: (message: string) => void, colorizer: Colorizer + testCase: GrammarTestCase, + failure: TestFailure, + padding: string, + terminalWidth: number, + sink: (message: string) => void, + colorizer: Colorizer ) { - const line = testCase.source[failure.srcLine] - const pos = failure.line + 1 + ': ' - const accents = ' '.repeat(failure.start) + '^'.repeat(failure.end - failure.start) + const line = testCase.source[failure.srcLine] + const pos = failure.line + 1 + ': ' + const accents = ' '.repeat(failure.start) + '^'.repeat(failure.end - failure.start) - const termWidth = terminalWidth - pos.length - Padding.length - 5 + const termWidth = terminalWidth - pos.length - Padding.length - 5 - const trimLeft = failure.end > termWidth ? Math.max(0, failure.start - 8) : 0 + const trimLeft = failure.end > termWidth ? Math.max(0, failure.start - 8) : 0 - const line1 = line.substr(trimLeft) - const accents1 = accents.substr(trimLeft) + const line1 = line.substr(trimLeft) + const accents1 = accents.substr(trimLeft) - sink(padding + colorizer.gray(pos) + line1.substr(0, termWidth)) - sink(padding + ' '.repeat(pos.length) + accents1.substr(0, termWidth)) + sink(padding + colorizer.gray(pos) + line1.substr(0, termWidth)) + sink(padding + ' '.repeat(pos.length) + accents1.substr(0, termWidth)) } function printReason( - testCase: GrammarTestCase, failure: TestFailure, - padding: string, - sink: (message: string) => void, colorizer: Colorizer + testCase: GrammarTestCase, + failure: TestFailure, + padding: string, + sink: (message: string) => void, + colorizer: Colorizer ) { - if (failure.missing && failure.missing.length > 0) { - sink(colorizer.red(padding + 'missing required scopes: ') + colorizer.gray(failure.missing.join(' '))) - } - if (failure.unexpected && failure.unexpected.length > 0) { - sink(colorizer.red(padding + 'prohibited scopes: ') + colorizer.gray(failure.unexpected.join(' '))) - } - if (failure.actual !== undefined) { - sink(colorizer.red(padding + 'actual: ') + colorizer.gray(failure.actual.join(' '))) - } + if (failure.missing && failure.missing.length > 0) { + sink(colorizer.red(padding + 'missing required scopes: ') + colorizer.gray(failure.missing.join(' '))) + } + if (failure.unexpected && failure.unexpected.length > 0) { + sink(colorizer.red(padding + 'prohibited scopes: ') + colorizer.gray(failure.unexpected.join(' '))) + } + if (failure.actual !== undefined) { + sink(colorizer.red(padding + 'actual: ') + colorizer.gray(failure.actual.join(' '))) + } } interface Colorizer { - red(text: string): string; - gray(text: string): string - whiteBright(text: string): string + red(text: string): string + gray(text: string): string + whiteBright(text: string): string } diff --git a/test/unit/unit/reporter.test.ts b/test/unit/unit/reporter.test.ts index d6dff2a..c1416ad 100644 --- a/test/unit/unit/reporter.test.ts +++ b/test/unit/unit/reporter.test.ts @@ -11,431 +11,470 @@ import { LineAssertion, TestCaseMetadata, TestFailure } from '../../../src/unit/ const sep = p.sep describe('XUnit reporters', () => { + let reportsDir: string - let reportsDir: string + beforeEach(() => { + reportsDir = fs.mkdtempSync(`${os.tmpdir}${sep}reports_`) + }) + + afterEach(() => { + fs.rmSync(reportsDir, { recursive: true }) + }) + + describe('Generic XUnit reporter', () => { + let reporter: Reporter beforeEach(() => { - reportsDir = fs.mkdtempSync(`${os.tmpdir}${sep}reports_`) + reporter = new XunitGenericReporter(reportsDir) + }) + + it('should emit one report file per test file', async () => { + reporter.reportTestResult( + 'file1', + { + source: ['source1'], + metadata: metadata('case 1 description'), + assertions: [lineAssertion(0, 1), lineAssertion(0, 2)] + }, + [] + ) + reporter.reportTestResult( + 'file2', + { + source: ['source2'], + metadata: metadata(), + assertions: [lineAssertion(0, 3)] + }, + [] + ) + reporter.reportSuiteResult() + + assertReportFiles('TEST-file1.xml', 'TEST-file2.xml') + + const xml1 = await readReport('TEST-file1.xml') + expect(xml1.testsuite.$.name).eq('case 1 description') + expect(xml1.testsuite.$.tests).eq('2') + expect(xml1.testsuite.$.failures).eq('0') + expect(xml1.testsuite.testcase).length(2) + expect(xml1.testsuite.testcase[0].$.name).eq('file1:1') + expect(xml1.testsuite.testcase[1].$.name).eq('file1:2') + + const xml2 = await readReport('TEST-file2.xml') + expect(xml2.testsuite.$.name).eq('file2') + expect(xml2.testsuite.$.tests).eq('1') + expect(xml2.testsuite.$.failures).eq('0') + expect(xml2.testsuite.testcase).length(1) + expect(xml2.testsuite.testcase[0].$.name).eq('file2:3') + }) + + it('should place reports for test files in nested directories directly into reports directory with mangled names', async () => { + reporter.reportTestResult( + 'file1', + { + source: ['source1'], + metadata: metadata(), + assertions: [lineAssertion(0, 1)] + }, + [] + ) + reporter.reportTestResult( + `dir1${sep}file2`, + { + source: ['source2'], + metadata: metadata('case 2 description'), + assertions: [lineAssertion(0, 2)] + }, + [] + ) + reporter.reportTestResult( + `dir1${sep}dir2${sep}file3`, + { + source: ['source3'], + metadata: metadata(), + assertions: [lineAssertion(0, 3)] + }, + [] + ) + reporter.reportSuiteResult() + + assertReportFiles('TEST-file1.xml', 'TEST-dir1.file2.xml', 'TEST-dir1.dir2.file3.xml') + + const xml1 = await readReport('TEST-file1.xml') + expect(xml1.testsuite.$.name).eq('file1') + expect(xml1.testsuite.testcase[0].$.name).eq('file1:1') + + const xml2 = await readReport('TEST-dir1.file2.xml') + expect(xml2.testsuite.$.name).eq('case 2 description') + expect(xml2.testsuite.testcase[0].$.name).eq(`dir1${sep}file2:2`) + + const xml3 = await readReport('TEST-dir1.dir2.file3.xml') + expect(xml3.testsuite.$.name).eq(`dir1${sep}dir2${sep}file3`) + expect(xml3.testsuite.testcase[0].$.name).eq(`dir1${sep}dir2${sep}file3:3`) + }) + + it('should escape reserved characters in failure description', async () => { + reporter.reportTestResult( + 'file', + { + source: [ + 'xml hell " \' < > &' + // 'assertion', + ], + metadata: metadata(), + assertions: [lineAssertion(0, 1)] + }, + [assertionFailure(0, 1, 0, 1, [], ['m1'], [])] + ) + reporter.reportSuiteResult() + + const xml = await readReport('TEST-file.xml') + expect(xml.testsuite.testcase[0].failure[0]._).eq( + [ + '1: xml hell " \' < > &', // the escapes were converted back to regular chars by the xml lib when parsing + ' ^', + 'missing required scopes: m1', + 'actual: ' + ].join('\n') + ) }) - afterEach(() => { - fs.rmSync(reportsDir, { recursive: true }) + it('should associate assertion failures with source lines', async () => { + reporter.reportTestResult( + 'file', + { + source: [ + /*0*/ '1 source1', + // '2 assertion1', + // '3 assertion2', + /*1*/ '4 source2', + // '5 assertion3', + /*2*/ '6 source3', + // '7 assertion4', + // '8 assertion5', + /*3*/ '9 source4' + // '10 assertion6', + ], + metadata: metadata(), + assertions: [lineAssertion(0, 1), lineAssertion(1, 4), lineAssertion(2, 6), lineAssertion(3, 9)] + }, + [ + assertionFailure(0, 1, 0, 1, ['a1', 'a2', 'a3'], ['m1', 'm2'], ['u1']), + assertionFailure(2, 6, 0, 3, ['a1', 'a2'], ['m1'], []), + assertionFailure(2, 6, 3, 5, ['a1'], [], ['u1']) + ] + ) + reporter.reportSuiteResult() + + assertReportFiles('TEST-file.xml') + + const xml = await readReport('TEST-file.xml') + expect(xml.testsuite.$.tests).eq('4') + expect(xml.testsuite.$.failures).eq('3') + expect(xml.testsuite.testcase).length(4) + + const [xmlCase1, xmlCase2, xmlCase3, xmlCase4] = xml.testsuite.testcase + + expect(xmlCase1.$.name).eq('file:1') + expect(xmlCase1.failure).length(1) + const [xmlFailure11] = xmlCase1.failure + expect(xmlFailure11.$.message).eq('Assertion failed at 1:1:2') + expect(xmlFailure11._).eq( + ['1: 1 source1', ' ^', 'missing required scopes: m1 m2', 'prohibited scopes: u1', 'actual: a1 a2 a3'].join( + '\n' + ) + ) + + expect(xmlCase2.$.name).eq('file:4') + expect(xmlCase2.failure).is.undefined + + expect(xmlCase3.$.name).eq('file:6') + expect(xmlCase3.failure).length(2) + const [xmlFailure31, xmlFailure32] = xmlCase3.failure + expect(xmlFailure31.$.message).eq('Assertion failed at 6:1:4') + expect(xmlFailure31._).eq(['6: 6 source3', ' ^^^', 'missing required scopes: m1', 'actual: a1 a2'].join('\n')) + expect(xmlFailure32.$.message).eq('Assertion failed at 6:4:6') + expect(xmlFailure32._).eq(['6: 6 source3', ' ^^', 'prohibited scopes: u1', 'actual: a1'].join('\n')) + + expect(xmlCase4.$.name).eq('file:9') + expect(xmlCase4.failure).is.undefined + }) + + it('should create report for test file which fails to parse', async () => { + reporter.reportTestResult( + 'file1', + { + source: ['source1'], + metadata: metadata(), + assertions: [lineAssertion(0, 1)] + }, + [] + ) + reporter.reportParseError( + 'file2', + new Error( + 'Expecting the first line in the syntax test file to be in the following format:\n' + + ' SYNTAX TEST "" ("description")?\n' + ) + ) + reporter.reportTestResult( + 'file3', + { + source: ['source3'], + metadata: metadata(), + assertions: [lineAssertion(0, 3)] + }, + [] + ) + reporter.reportSuiteResult() + + assertReportFiles('TEST-file1.xml', 'TEST-file2.xml', 'TEST-file3.xml') + + const xml = await readReport('TEST-file2.xml') + expect(xml.testsuite.$.tests).eq('1') + expect(xml.testsuite.$.failures).eq('0') + expect(xml.testsuite.$.errors).eq('1') + expect(xml.testsuite.testcase).length(1) + + const xmlCase = xml.testsuite.testcase[0] + expect(xmlCase.$.name).eq('Parse test file') + expect(xmlCase.failure).is.undefined + expect(xmlCase.error).length(1) + expect(xmlCase.error[0].$.message).eq('Failed to parse test file') + expect(xmlCase.error[0]._).satisfy((m: string) => + m.startsWith( + [ + 'Error: Expecting the first line in the syntax test file to be in the following format:', + ' SYNTAX TEST "" ("description")?' + ].join('\n') + ) + ) + }) + + it('should create report for test file which errors when running grammar test', async () => { + reporter.reportTestResult( + 'file1', + { + source: ['source1'], + metadata: metadata(), + assertions: [lineAssertion(0, 1)] + }, + [] + ) + reporter.reportGrammarTestError( + 'file2', + { + source: ['source1'], + metadata: metadata(), + assertions: [lineAssertion(0, 2)] + }, + new Error('No grammar provided for ') + ) + reporter.reportTestResult( + 'file3', + { + source: ['source3'], + metadata: metadata(), + assertions: [lineAssertion(0, 3)] + }, + [] + ) + reporter.reportSuiteResult() + + assertReportFiles('TEST-file1.xml', 'TEST-file2.xml', 'TEST-file3.xml') + + const xml = await readReport('TEST-file2.xml') + expect(xml.testsuite.$.tests).eq('1') + expect(xml.testsuite.$.failures).eq('0') + expect(xml.testsuite.$.errors).eq('1') + expect(xml.testsuite.testcase).length(1) + + const xmlCase = xml.testsuite.testcase[0] + expect(xmlCase.$.name).eq('Run grammar tests') + expect(xmlCase.failure).is.undefined + expect(xmlCase.error).length(1) + expect(xmlCase.error[0].$.message).eq('Error when running grammar tests') + expect(xmlCase.error[0]._).satisfy((m: string) => + m.startsWith(['Error: No grammar provided for '].join('\n')) + ) + }) + }) + + describe('GitLab-flavored XUnit reporter', () => { + let reporter: Reporter + + beforeEach(() => { + reporter = new XunitGitlabReporter(reportsDir) }) - describe('Generic XUnit reporter', () => { - - let reporter: Reporter - - beforeEach(() => { - reporter = new XunitGenericReporter(reportsDir) - }) - - it('should emit one report file per test file', async () => { - reporter.reportTestResult('file1', { - source: ['source1'], - metadata: metadata('case 1 description'), - assertions: [ - lineAssertion(0, 1), - lineAssertion(0, 2), - ] - }, []) - reporter.reportTestResult('file2', { - source: ['source2'], - metadata: metadata(), - assertions: [ - lineAssertion(0, 3), - ] - }, []) - reporter.reportSuiteResult() - - assertReportFiles( - 'TEST-file1.xml', - 'TEST-file2.xml' - ) - - const xml1 = await readReport('TEST-file1.xml') - expect(xml1.testsuite.$.name).eq('case 1 description') - expect(xml1.testsuite.$.tests).eq('2') - expect(xml1.testsuite.$.failures).eq('0') - expect(xml1.testsuite.testcase).length(2) - expect(xml1.testsuite.testcase[0].$.name).eq('file1:1') - expect(xml1.testsuite.testcase[1].$.name).eq('file1:2') - - const xml2 = await readReport('TEST-file2.xml') - expect(xml2.testsuite.$.name).eq('file2') - expect(xml2.testsuite.$.tests).eq('1') - expect(xml2.testsuite.$.failures).eq('0') - expect(xml2.testsuite.testcase).length(1) - expect(xml2.testsuite.testcase[0].$.name).eq('file2:3') - }) - - it('should place reports for test files in nested directories directly into reports directory with mangled names', async () => { - reporter.reportTestResult('file1', { - source: ['source1'], - metadata: metadata(), - assertions: [lineAssertion(0, 1)] - }, []) - reporter.reportTestResult(`dir1${sep}file2`, { - source: ['source2'], - metadata: metadata("case 2 description"), - assertions: [lineAssertion(0, 2)] - }, []) - reporter.reportTestResult(`dir1${sep}dir2${sep}file3`, { - source: ['source3'], - metadata: metadata(), - assertions: [lineAssertion(0, 3)] - }, []) - reporter.reportSuiteResult() - - assertReportFiles( - 'TEST-file1.xml', - 'TEST-dir1.file2.xml', - 'TEST-dir1.dir2.file3.xml', - ) - - const xml1 = await readReport('TEST-file1.xml') - expect(xml1.testsuite.$.name).eq('file1') - expect(xml1.testsuite.testcase[0].$.name).eq('file1:1') - - const xml2 = await readReport('TEST-dir1.file2.xml') - expect(xml2.testsuite.$.name).eq('case 2 description') - expect(xml2.testsuite.testcase[0].$.name).eq(`dir1${sep}file2:2`) - - const xml3 = await readReport('TEST-dir1.dir2.file3.xml') - expect(xml3.testsuite.$.name).eq(`dir1${sep}dir2${sep}file3`) - expect(xml3.testsuite.testcase[0].$.name).eq(`dir1${sep}dir2${sep}file3:3`) - }) - - it('should escape reserved characters in failure description', async () => { - reporter.reportTestResult('file', { - source: [ - 'xml hell " \' < > &', - // 'assertion', - ], - metadata: metadata(), - assertions: [ - lineAssertion(0, 1) - ] - }, [ - assertionFailure(0, 1, 0, 1, [], ['m1'], []), - ]) - reporter.reportSuiteResult() - - const xml = await readReport('TEST-file.xml') - expect(xml.testsuite.testcase[0].failure[0]._).eq([ - '1: xml hell " \' < > &', // the escapes were converted back to regular chars by the xml lib when parsing - ' ^', - 'missing required scopes: m1', - 'actual: ', - ].join("\n")) - }) - - it('should associate assertion failures with source lines', async () => { - reporter.reportTestResult('file', { - source: [ - /*0*/'1 source1', - // '2 assertion1', - // '3 assertion2', - /*1*/'4 source2', - // '5 assertion3', - /*2*/'6 source3', - // '7 assertion4', - // '8 assertion5', - /*3*/'9 source4', - // '10 assertion6', - ], - metadata: metadata(), - assertions: [ - lineAssertion(0, 1), - lineAssertion(1, 4), - lineAssertion(2, 6), - lineAssertion(3, 9), - ] - }, [ - assertionFailure(0, 1, 0, 1, ['a1', 'a2', 'a3'], ['m1', 'm2'], ['u1']), - assertionFailure(2, 6, 0, 3, ['a1', 'a2'], ['m1'], []), - assertionFailure(2, 6, 3, 5, ['a1'], [], ['u1']), - ]) - reporter.reportSuiteResult() - - assertReportFiles('TEST-file.xml') - - const xml = await readReport('TEST-file.xml') - expect(xml.testsuite.$.tests).eq('4') - expect(xml.testsuite.$.failures).eq('3') - expect(xml.testsuite.testcase).length(4) - - const [xmlCase1, xmlCase2, xmlCase3, xmlCase4] = xml.testsuite.testcase - - expect(xmlCase1.$.name).eq('file:1') - expect(xmlCase1.failure).length(1) - const [xmlFailure11] = xmlCase1.failure - expect(xmlFailure11.$.message).eq("Assertion failed at 1:1:2") - expect(xmlFailure11._).eq([ - '1: 1 source1', - ' ^', - 'missing required scopes: m1 m2', - 'prohibited scopes: u1', - 'actual: a1 a2 a3', - ].join("\n")) - - expect(xmlCase2.$.name).eq('file:4') - expect(xmlCase2.failure).is.undefined - - expect(xmlCase3.$.name).eq('file:6') - expect(xmlCase3.failure).length(2) - const [xmlFailure31, xmlFailure32] = xmlCase3.failure - expect(xmlFailure31.$.message).eq("Assertion failed at 6:1:4") - expect(xmlFailure31._).eq([ - '6: 6 source3', - ' ^^^', - 'missing required scopes: m1', - 'actual: a1 a2', - ].join("\n")) - expect(xmlFailure32.$.message).eq("Assertion failed at 6:4:6") - expect(xmlFailure32._).eq([ - '6: 6 source3', - ' ^^', - 'prohibited scopes: u1', - 'actual: a1', - ].join("\n")) - - expect(xmlCase4.$.name).eq('file:9') - expect(xmlCase4.failure).is.undefined - }) - - it('should create report for test file which fails to parse', async () => { - reporter.reportTestResult('file1', { - source: ['source1'], - metadata: metadata(), - assertions: [lineAssertion(0, 1)] - }, []) - reporter.reportParseError('file2', new Error( - 'Expecting the first line in the syntax test file to be in the following format:\n' + - ' SYNTAX TEST "" ("description")?\n')) - reporter.reportTestResult('file3', { - source: ['source3'], - metadata: metadata(), - assertions: [lineAssertion(0, 3)] - }, []) - reporter.reportSuiteResult() - - assertReportFiles( - 'TEST-file1.xml', - 'TEST-file2.xml', - 'TEST-file3.xml', - ) - - const xml = await readReport('TEST-file2.xml') - expect(xml.testsuite.$.tests).eq('1') - expect(xml.testsuite.$.failures).eq('0') - expect(xml.testsuite.$.errors).eq('1') - expect(xml.testsuite.testcase).length(1) - - const xmlCase = xml.testsuite.testcase[0] - expect(xmlCase.$.name).eq('Parse test file') - expect(xmlCase.failure).is.undefined - expect(xmlCase.error).length(1) - expect(xmlCase.error[0].$.message).eq("Failed to parse test file") - expect(xmlCase.error[0]._).satisfy((m: string) => m.startsWith([ - 'Error: Expecting the first line in the syntax test file to be in the following format:', - ' SYNTAX TEST "" ("description")?', - ].join("\n"))) - }) - - it('should create report for test file which errors when running grammar test', async () => { - reporter.reportTestResult('file1', { - source: ['source1'], - metadata: metadata(), - assertions: [lineAssertion(0, 1)] - }, []) - reporter.reportGrammarTestError('file2', { - source: ['source1'], - metadata: metadata(), - assertions: [lineAssertion(0, 2)] - }, new Error('No grammar provided for ')) - reporter.reportTestResult('file3', { - source: ['source3'], - metadata: metadata(), - assertions: [lineAssertion(0, 3)] - }, []) - reporter.reportSuiteResult() - - assertReportFiles( - 'TEST-file1.xml', - 'TEST-file2.xml', - 'TEST-file3.xml', - ) - - const xml = await readReport('TEST-file2.xml') - expect(xml.testsuite.$.tests).eq('1') - expect(xml.testsuite.$.failures).eq('0') - expect(xml.testsuite.$.errors).eq('1') - expect(xml.testsuite.testcase).length(1) - - const xmlCase = xml.testsuite.testcase[0] - expect(xmlCase.$.name).eq('Run grammar tests') - expect(xmlCase.failure).is.undefined - expect(xmlCase.error).length(1) - expect(xmlCase.error[0].$.message).eq("Error when running grammar tests") - expect(xmlCase.error[0]._).satisfy((m: string) => m.startsWith([ - 'Error: No grammar provided for ', - ].join("\n"))) - }) + it('should always put filename into classname', async () => { + reporter.reportTestResult( + 'file1', + { + source: ['source1'], + metadata: metadata(), + assertions: [lineAssertion(0, 1)] + }, + [] + ) + reporter.reportGrammarTestError( + 'file2', + { + source: ['source1'], + metadata: metadata(), + assertions: [lineAssertion(0, 2)] + }, + new Error('No grammar provided for ') + ) + reporter.reportParseError( + 'file3', + new Error( + 'Expecting the first line in the syntax test file to be in the following format:\n' + + ' SYNTAX TEST "" ("description")?\n' + ) + ) + reporter.reportSuiteResult() + + const xml1 = await readReport('TEST-file1.xml') + expect(xml1.testsuite.testcase[0].$.classname).eq('file1') + + const xml2 = await readReport('TEST-file2.xml') + expect(xml2.testsuite.testcase[0].$.classname).eq('file2') + + const xml3 = await readReport('TEST-file3.xml') + expect(xml3.testsuite.testcase[0].$.classname).eq('file3') }) - describe('GitLab-flavored XUnit reporter', () => { - - let reporter: Reporter - - beforeEach(() => { - reporter = new XunitGitlabReporter(reportsDir) - }) - - it('should always put filename into classname', async () => { - reporter.reportTestResult('file1', { - source: ['source1'], - metadata: metadata(), - assertions: [lineAssertion(0, 1)] - }, []) - reporter.reportGrammarTestError('file2', { - source: ['source1'], - metadata: metadata(), - assertions: [lineAssertion(0, 2)] - }, new Error('No grammar provided for ')) - reporter.reportParseError('file3', new Error( - 'Expecting the first line in the syntax test file to be in the following format:\n' + - ' SYNTAX TEST "" ("description")?\n')) - reporter.reportSuiteResult() - - const xml1 = await readReport('TEST-file1.xml') - expect(xml1.testsuite.testcase[0].$.classname).eq('file1') - - const xml2 = await readReport('TEST-file2.xml') - expect(xml2.testsuite.testcase[0].$.classname).eq('file2') - - const xml3 = await readReport('TEST-file3.xml') - expect(xml3.testsuite.testcase[0].$.classname).eq('file3') - }) - - it('should put all failed assertions for one source line into single failure', async () => { - reporter.reportTestResult('file', { - source: [ - /*0*/'1 source1', - // '2 assertion1', - // '3 assertion2', - /*1*/'4 source2', - // '5 assertion3', - /*2*/'6 source3', - // '7 assertion4', - // '8 assertion5', - /*3*/'9 source4', - // '10 assertion6', - ], - metadata: metadata(), - assertions: [ - lineAssertion(0, 1), - lineAssertion(1, 4), - lineAssertion(2, 6), - lineAssertion(3, 9), - ] - }, [ - assertionFailure(0, 1, 0, 1, ['a1', 'a2', 'a3'], ['m1', 'm2'], ['u1']), - assertionFailure(2, 6, 0, 3, ['a1', 'a2'], ['m1'], []), - assertionFailure(2, 6, 3, 5, ['a1'], [], ['u1']), - ]) - reporter.reportSuiteResult() - - assertReportFiles('TEST-file.xml') - - const xml = await readReport('TEST-file.xml') - expect(xml.testsuite.$.tests).eq('4') - expect(xml.testsuite.$.failures).eq('2') - expect(xml.testsuite.testcase).length(4) - - const [xmlCase1, xmlCase2, xmlCase3, xmlCase4] = xml.testsuite.testcase - - expect(xmlCase1.$.name).eq('file:1') - expect(xmlCase1.failure).length(1) - const [xmlFailure1] = xmlCase1.failure - expect(xmlFailure1.$.message).eq("Failed at soure line 1") - expect(xmlFailure1._).eq([ - 'at [file:1:1:2]:', - '1: 1 source1', - ' ^', - 'missing required scopes: m1 m2', - 'prohibited scopes: u1', - 'actual: a1 a2 a3', - '' - ].join("\n")) - - expect(xmlCase2.$.name).eq('file:4') - expect(xmlCase2.failure).is.undefined - - expect(xmlCase3.$.name).eq('file:6') - expect(xmlCase3.failure).length(1) - const [xmlFailure3] = xmlCase3.failure - expect(xmlFailure3.$.message).eq("Failed at soure line 6") - expect(xmlFailure3._).eq([ - 'at [file:6:1:4]:', - '6: 6 source3', - ' ^^^', - 'missing required scopes: m1', - 'actual: a1 a2', - '', - 'at [file:6:4:6]:', - '6: 6 source3', - ' ^^', - 'prohibited scopes: u1', - 'actual: a1', - '' - ].join("\n")) - - expect(xmlCase4.$.name).eq('file:9') - expect(xmlCase4.failure).is.undefined - }) + it('should put all failed assertions for one source line into single failure', async () => { + reporter.reportTestResult( + 'file', + { + source: [ + /*0*/ '1 source1', + // '2 assertion1', + // '3 assertion2', + /*1*/ '4 source2', + // '5 assertion3', + /*2*/ '6 source3', + // '7 assertion4', + // '8 assertion5', + /*3*/ '9 source4' + // '10 assertion6', + ], + metadata: metadata(), + assertions: [lineAssertion(0, 1), lineAssertion(1, 4), lineAssertion(2, 6), lineAssertion(3, 9)] + }, + [ + assertionFailure(0, 1, 0, 1, ['a1', 'a2', 'a3'], ['m1', 'm2'], ['u1']), + assertionFailure(2, 6, 0, 3, ['a1', 'a2'], ['m1'], []), + assertionFailure(2, 6, 3, 5, ['a1'], [], ['u1']) + ] + ) + reporter.reportSuiteResult() + + assertReportFiles('TEST-file.xml') + + const xml = await readReport('TEST-file.xml') + expect(xml.testsuite.$.tests).eq('4') + expect(xml.testsuite.$.failures).eq('2') + expect(xml.testsuite.testcase).length(4) + + const [xmlCase1, xmlCase2, xmlCase3, xmlCase4] = xml.testsuite.testcase + + expect(xmlCase1.$.name).eq('file:1') + expect(xmlCase1.failure).length(1) + const [xmlFailure1] = xmlCase1.failure + expect(xmlFailure1.$.message).eq('Failed at soure line 1') + expect(xmlFailure1._).eq( + [ + 'at [file:1:1:2]:', + '1: 1 source1', + ' ^', + 'missing required scopes: m1 m2', + 'prohibited scopes: u1', + 'actual: a1 a2 a3', + '' + ].join('\n') + ) + + expect(xmlCase2.$.name).eq('file:4') + expect(xmlCase2.failure).is.undefined + + expect(xmlCase3.$.name).eq('file:6') + expect(xmlCase3.failure).length(1) + const [xmlFailure3] = xmlCase3.failure + expect(xmlFailure3.$.message).eq('Failed at soure line 6') + expect(xmlFailure3._).eq( + [ + 'at [file:6:1:4]:', + '6: 6 source3', + ' ^^^', + 'missing required scopes: m1', + 'actual: a1 a2', + '', + 'at [file:6:4:6]:', + '6: 6 source3', + ' ^^', + 'prohibited scopes: u1', + 'actual: a1', + '' + ].join('\n') + ) + + expect(xmlCase4.$.name).eq('file:9') + expect(xmlCase4.failure).is.undefined }) + }) - const assertReportFiles: (...expected: string[]) => void = (...expected: string[]) => { - const reportFiles = fs.readdirSync(reportsDir) - expect(reportFiles) - .members(expected) - .length(expected.length) - } + const assertReportFiles: (...expected: string[]) => void = (...expected: string[]) => { + const reportFiles = fs.readdirSync(reportsDir) + expect(reportFiles).members(expected).length(expected.length) + } - const readReport: (filename: string) => any = async (filename: string) => { - return await parseStringPromise(fs.readFileSync(p.resolve(reportsDir, filename))) - } + const readReport: (filename: string) => any = async (filename: string) => { + return await parseStringPromise(fs.readFileSync(p.resolve(reportsDir, filename))) + } }) function metadata(description?: string): TestCaseMetadata { - return { - scope: 'main.scope', - commentToken: '//', - description: description || "", - allowMiddleLineAssertions: true - } + return { + scope: 'main.scope', + commentToken: '//', + description: description || '', + allowMiddleLineAssertions: true + } } function lineAssertion(sourceLineNumber: number, testCaseLineNumber: number): LineAssertion { - return { - sourceLineNumber, - testCaseLineNumber: testCaseLineNumber - 1, - scopeAssertions: [{ - from: -1, to: -2, scopes: ['scope1'], exclude: [] - }] - } + return { + sourceLineNumber, + testCaseLineNumber: testCaseLineNumber - 1, + scopeAssertions: [ + { + from: -1, + to: -2, + scopes: ['scope1'], + exclude: [] + } + ] + } } function assertionFailure( - sourceLineNumber: number, testCaseLineNumber: number, - start: number, end: number, - actual: string[], missing: string[], unexpected: string[], + sourceLineNumber: number, + testCaseLineNumber: number, + start: number, + end: number, + actual: string[], + missing: string[], + unexpected: string[] ): TestFailure { - return { - actual, missing, unexpected, - srcLine: sourceLineNumber, - line: testCaseLineNumber - 1, - start, end - } + return { + actual, + missing, + unexpected, + srcLine: sourceLineNumber, + line: testCaseLineNumber - 1, + start, + end + } } From 2c9d3bb20314edc4da1bb076573f4b59b5b1b1ae Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Sat, 11 Jan 2025 11:53:33 -0800 Subject: [PATCH 4/5] Update quotes to be Windows-compatible single quotes don't quite work in Windows, double quotes work in both Windows and Linux --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 3b4fe4b..33d9903 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,10 @@ }, "scripts": { "build": "npx tsc", - "coverage": "npx nyc --reporter=html mocha -r ts-node/register 'test/**/*.test.ts'", - "format": "prettier --config .prettierrc 'src/**/*.ts' 'test/**/*.ts' --write", - "lint": "tslint -c tslint.json 'src/**/*.ts'", - "test": "mocha -r ts-node/register 'test/**/*.test.ts'" + "coverage": "npx nyc --reporter=html mocha -r ts-node/register \"test/**/*.test.ts\"", + "format": "prettier --config .prettierrc \"src/**/*.ts\" \"test/**/*.ts\" --write", + "lint": "tslint -c tslint.json \"src/**/*.ts\"", + "test": "mocha -r ts-node/register \"test/**/*.test.ts\"" }, "bin": { "vscode-tmgrammar-test": "./dist/unit.js", From 83f0b2a14dd14fdf4133819ada3361a7259d053d Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Sat, 11 Jan 2025 11:53:48 -0800 Subject: [PATCH 5/5] Update Mocha to 11.1 --- package-lock.json | 387 ++++++++++++++++++++++++++++++++++++++++++---- package.json | 2 +- 2 files changed, 354 insertions(+), 35 deletions(-) diff --git a/package-lock.json b/package-lock.json index c7d771d..29632bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,7 @@ "@types/node": "^18.11.9", "@types/xml2js": "^0.4.11", "chai": "^4.2.0", - "mocha": "^10.2.0", + "mocha": "^11.1.0", "nyc": "^17.1.0", "prettier": "^2.1.2", "ts-node": "^8.10.2", @@ -289,6 +289,109 @@ "node": ">=6.9.0" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/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, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/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, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/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, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "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", @@ -441,6 +544,17 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@types/chai": { "version": "4.3.11", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.11.tgz", @@ -807,14 +921,18 @@ } }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "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, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/color-convert": { @@ -932,6 +1050,13 @@ "node": ">=0.3.1" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, "node_modules/electron-to-chromium": { "version": "1.5.80", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.80.tgz", @@ -1559,6 +1684,22 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -1771,6 +1912,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -1784,9 +1935,9 @@ } }, "node_modules/mocha": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", - "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", + "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", "dev": true, "license": "MIT", "dependencies": { @@ -1797,7 +1948,7 @@ "diff": "^5.2.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", - "glob": "^8.1.0", + "glob": "^10.4.5", "he": "^1.2.0", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", @@ -1807,8 +1958,8 @@ "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "bin": { @@ -1816,7 +1967,7 @@ "mocha": "bin/mocha.js" }, "engines": { - "node": ">= 14.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/mocha/node_modules/brace-expansion": { @@ -1851,22 +2002,55 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mocha/node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/mocha/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -1894,6 +2078,19 @@ "node": ">=10" } }, + "node_modules/mocha/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, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -2240,6 +2437,13 @@ "node": ">=8" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2272,6 +2476,30 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -2616,6 +2844,22 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -2628,6 +2872,20 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -2937,6 +3195,26 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -2949,11 +3227,48 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/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, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/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, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/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, + "license": "MIT" + }, "node_modules/wrap-ansi/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, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -2969,6 +3284,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -2980,7 +3296,8 @@ "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 + "dev": true, + "license": "MIT" }, "node_modules/wrappy": { "version": "1.0.2", @@ -3026,6 +3343,7 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -3038,31 +3356,32 @@ "license": "ISC" }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-unparser": { diff --git a/package.json b/package.json index 33d9903..0035cf8 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@types/node": "^18.11.9", "@types/xml2js": "^0.4.11", "chai": "^4.2.0", - "mocha": "^10.2.0", + "mocha": "^11.1.0", "nyc": "^17.1.0", "prettier": "^2.1.2", "ts-node": "^8.10.2",