From 6b907536193301bbe2106b902ac8dcc287d2cc29 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Tue, 18 Mar 2025 17:53:36 -0700 Subject: [PATCH 01/70] Add jest package --- package-lock.json | 4323 +++++++++++++++++++++++++++++++++++++++------ package.json | 8 +- 2 files changed, 3774 insertions(+), 557 deletions(-) diff --git a/package-lock.json b/package-lock.json index d71ad929..d801a52c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,824 +16,3284 @@ "eask": "eask" }, "devDependencies": { - "@yao-pkg/pkg": "^6.0.0" + "@yao-pkg/pkg": "^6.0.0", + "jest": "^29.7.0" } }, - "node_modules/@babel/helper-string-parser": { - "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==", + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "node_modules/@babel/code-frame": { + "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", - "engines": { - "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" + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/compat-data": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/core": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "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==", + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } }, - "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==", + "node_modules/@babel/generator": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", + "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", "dev": true, "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "@babel/parser": "^7.26.10", + "@babel/types": "^7.26.10", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/helper-compilation-targets": { + "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": { - "ansi-regex": "^6.0.1" + "@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" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "license": "MIT", + "license": "ISC", "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" + "yallist": "^3.0.2" } }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@babel/helper-module-imports": { + "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": { - "minipass": "^7.0.4" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/@babel/helper-module-transforms": { + "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": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@babel/helper-string-parser": { + "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.0.0" + "node": ">=6.9.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 - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/@babel/helper-validator-identifier": { + "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, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "license": "MIT", + "engines": { + "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/helper-validator-option": { + "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", - "optional": true, "engines": { - "node": ">=14" + "node": ">=6.9.0" } }, - "node_modules/@yao-pkg/pkg": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@yao-pkg/pkg/-/pkg-6.2.0.tgz", - "integrity": "sha512-kq1aDs9aa+fEtKQQ2AsxcL4Z82LsYw9ZQIwD3Q/wDq8ZPN69wCf2+OQp271lnqMybYInXwwBJ3swIb/nvaXS/g==", + "node_modules/@babel/helpers": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", + "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/generator": "^7.23.0", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "@yao-pkg/pkg-fetch": "3.5.18", - "into-stream": "^6.0.0", - "minimist": "^1.2.6", - "multistream": "^4.1.0", - "picocolors": "^1.1.0", - "picomatch": "^4.0.2", - "prebuild-install": "^7.1.1", - "resolve": "^1.22.0", - "stream-meter": "^1.0.4", - "tar": "^7.4.3", - "tinyglobby": "^0.2.9", - "unzipper": "^0.12.3" - }, - "bin": { - "pkg": "lib-es5/bin.js" + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@yao-pkg/pkg-fetch": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@yao-pkg/pkg-fetch/-/pkg-fetch-3.5.18.tgz", - "integrity": "sha512-tdUT7zS2lyXeJwkA8lDI4aVxHwauAc5lKj6Xui3/BtDe6vDsQ8KP+f66u07AI28DuTzKxjRJKNNXVdyGv2Ndsg==", + "node_modules/@babel/parser": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", + "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", "dev": true, "license": "MIT", "dependencies": { - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.6", - "picocolors": "^1.1.0", - "progress": "^2.0.3", - "semver": "^7.3.5", - "tar-fs": "^2.1.1", - "yargs": "^16.2.0" + "@babel/types": "^7.26.10" }, "bin": { - "pkg-fetch": "lib-es5/bin.js" + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@yao-pkg/pkg-fetch/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@yao-pkg/pkg-fetch/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==", + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@yao-pkg/pkg/node_modules/@babel/generator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", - "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.3", - "@babel/types": "^7.26.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" + "@babel/helper-plugin-utils": "^7.12.13" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@yao-pkg/pkg/node_modules/@babel/parser": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", - "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.26.3" - }, - "bin": { - "parser": "bin/babel-parser.js" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@yao-pkg/pkg/node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@yao-pkg/pkg/node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" }, - "engines": { - "node": ">=6" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@yao-pkg/pkg/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "dev": true, "license": "MIT", "dependencies": { - "debug": "4" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { - "node": ">= 6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "@babel/helper-plugin-utils": "^7.8.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, + "license": "MIT", "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, + "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">= 6" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "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==", + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "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==", + "node_modules/@babel/template": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", + "dev": true, + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@babel/traverse": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz", + "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==", + "dev": true, + "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10", + "debug": "^4.3.1", + "globals": "^11.1.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=6.9.0" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/@babel/types": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", + "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" } }, - "node_modules/cross-spawn/node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "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": { - "isexe": "^2.0.0" + "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" }, - "bin": { - "node-which": "bin/node-which" + "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/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "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", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "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.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "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, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "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, + "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 + }, + "node_modules/@jridgewell/trace-mapping": { + "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, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@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/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/node": { + "version": "22.13.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", + "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@yao-pkg/pkg": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@yao-pkg/pkg/-/pkg-6.2.0.tgz", + "integrity": "sha512-kq1aDs9aa+fEtKQQ2AsxcL4Z82LsYw9ZQIwD3Q/wDq8ZPN69wCf2+OQp271lnqMybYInXwwBJ3swIb/nvaXS/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "@yao-pkg/pkg-fetch": "3.5.18", + "into-stream": "^6.0.0", + "minimist": "^1.2.6", + "multistream": "^4.1.0", + "picocolors": "^1.1.0", + "picomatch": "^4.0.2", + "prebuild-install": "^7.1.1", + "resolve": "^1.22.0", + "stream-meter": "^1.0.4", + "tar": "^7.4.3", + "tinyglobby": "^0.2.9", + "unzipper": "^0.12.3" + }, + "bin": { + "pkg": "lib-es5/bin.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@yao-pkg/pkg-fetch": { + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@yao-pkg/pkg-fetch/-/pkg-fetch-3.5.18.tgz", + "integrity": "sha512-tdUT7zS2lyXeJwkA8lDI4aVxHwauAc5lKj6Xui3/BtDe6vDsQ8KP+f66u07AI28DuTzKxjRJKNNXVdyGv2Ndsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.6", + "picocolors": "^1.1.0", + "progress": "^2.0.3", + "semver": "^7.3.5", + "tar-fs": "^2.1.1", + "yargs": "^16.2.0" + }, + "bin": { + "pkg-fetch": "lib-es5/bin.js" + } + }, + "node_modules/@yao-pkg/pkg-fetch/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@yao-pkg/pkg-fetch/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==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/@yao-pkg/pkg/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "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==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, + "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/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "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" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001706", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz", + "integrity": "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "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==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, + "license": "MIT" + }, + "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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.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", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "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.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "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.120", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.120.tgz", + "integrity": "sha512-oTUp3gfX1gZI+xfD2djr2rzQdHCwHzPQrrK0CD7WpTdF0nPdQ/INcRVjWgLdCT4a9W3jFObR9DAfsuyFQnI8CQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, + "node_modules/glob": { + "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": { + "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/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/into-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz", + "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==", + "dev": true, + "dependencies": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "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.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "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/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, - "engines": { - "node": ">= 8" + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" }, "peerDependenciesMeta": { - "supports-color": { + "@types/node": { + "optional": true + }, + "ts-node": { "optional": true } } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { - "mimic-response": "^3.1.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "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.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=10" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "node_modules/jest-config/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=4.0.0" + "node": "*" } }, - "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "node_modules/jest-config/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "readable-stream": "^2.0.2" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, + "license": "MIT", "dependencies": { - "once": "^1.4.0" + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">=14" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, + "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=14.14" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "dev": true + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "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" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "6", - "debug": "4" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "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.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">= 6" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "node_modules/jest-runtime/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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/into-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz", - "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==", + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, + "license": "MIT", "dependencies": { - "from2": "^2.3.0", - "p-is-promise": "^3.0.0" + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -841,42 +3301,110 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, "engines": { - "node": ">=16" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "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": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "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" + }, + "engines": { + "node": ">=6" } }, "node_modules/jsonfile": { @@ -892,6 +3420,46 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", @@ -899,6 +3467,63 @@ "dev": true, "license": "ISC" }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", @@ -1033,6 +3658,13 @@ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "dev": true }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, "node_modules/node-abi": { "version": "3.63.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.63.0.tgz", @@ -1073,6 +3705,36 @@ "dev": true, "license": "MIT" }, + "node_modules/node-releases": { + "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", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1082,6 +3744,22 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-is-promise": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", @@ -1091,6 +3769,61 @@ "node": ">=8" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "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", @@ -1098,6 +3831,45 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -1138,6 +3910,42 @@ "dev": true, "license": "ISC" }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/prebuild-install": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", @@ -1164,6 +3972,34 @@ "node": ">=10" } }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -1180,6 +4016,20 @@ "node": ">=0.4.0" } }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -1190,6 +4040,23 @@ "once": "^1.3.1" } }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -1205,6 +4072,13 @@ "rc": "cli.js" } }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -1245,6 +4119,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/resolve/node_modules/is-core-module": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", @@ -1372,6 +4279,64 @@ "simple-concat": "^1.0.0" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/stream-meter": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/stream-meter/-/stream-meter-1.0.4.tgz", @@ -1390,6 +4355,20 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -1444,6 +4423,26 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -1453,6 +4452,19 @@ "node": ">=0.10.0" } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -1535,6 +4547,67 @@ "node": ">=18" } }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "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.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/tinyglobby": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", @@ -1577,6 +4650,26 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -1596,6 +4689,36 @@ "node": "*" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true, + "license": "MIT" + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -1620,12 +4743,68 @@ "node-int64": "^0.4.0" } }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -1699,6 +4878,27 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -1741,6 +4941,19 @@ "engines": { "node": ">=12" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 746a528c..569b7b80 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "A set of command-line tools to build Emacs packages", "main": "eask", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "test": "jest", "pkg-all": "pkg package.json", "pkg-linux-arm64": "pkg package.json -t node*-linuxstatic-arm64 --output dist/eask --public", "pkg-linux-x64": "pkg package.json -t node*-linuxstatic-x64 --output dist/eask --public", @@ -33,7 +33,11 @@ "yargs": "^17.0.0" }, "devDependencies": { - "@yao-pkg/pkg": "^6.0.0" + "@yao-pkg/pkg": "^6.0.0", + "jest": "^29.7.0" + }, + "jest": { + "rootDir": "./test-js" }, "files": [ "cmds", From 274ee3cfd7f8ee1412a33f4bbd2b0d8f1ba8361a Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Tue, 18 Mar 2025 17:53:54 -0700 Subject: [PATCH 02/70] Port analyze tests --- test-js/analyze.test.js | 53 ++++++++++++++++++++++++++++++ test-js/dsl/.gitignore | 14 ++++++++ test-js/dsl/Eask | 44 +++++++++++++++++++++++++ test-js/dsl/check-dsl.el | 37 +++++++++++++++++++++ test-js/empty/.gitkeep | 0 test-js/metadata/.gitignore | 14 ++++++++ test-js/metadata/Eask | 16 +++++++++ test-js/metadata/check-metadata.el | 37 +++++++++++++++++++++ 8 files changed, 215 insertions(+) create mode 100644 test-js/analyze.test.js create mode 100644 test-js/dsl/.gitignore create mode 100644 test-js/dsl/Eask create mode 100644 test-js/dsl/check-dsl.el create mode 100644 test-js/empty/.gitkeep create mode 100644 test-js/metadata/.gitignore create mode 100644 test-js/metadata/Eask create mode 100644 test-js/metadata/check-metadata.el diff --git a/test-js/analyze.test.js b/test-js/analyze.test.js new file mode 100644 index 00000000..14d85e44 --- /dev/null +++ b/test-js/analyze.test.js @@ -0,0 +1,53 @@ +const util = require("node:util"); +const exec = util.promisify(require("node:child_process").exec); + +describe("analyze", () => { + describe("dsl", () => { + const cwd = "./test-js/dsl"; + it("handles plain text", async () => { + const res = await exec("eask analyze", { cwd }); + expect(res).toBeTruthy(); + + const res1 = await exec("eask analyze Eask", { cwd }); + expect(res1).toBeTruthy(); + }); + + it("handles json", async () => { + const res = await exec("eask analyze --json", { cwd }); + expect(res).toBeTruthy(); + + const res1 = await exec("eask analyze Eask --json", { + cwd, + }); + expect(res1).toBeTruthy(); + }); + }); + + describe("error", () => { + const cwd = "./test-js/empty"; + it("errors in an empty dir", async () => { + await expect(exec("eask scrog", { cwd })).rejects.toThrow(); + }); + }); + + describe("metadata", () => { + const cwd = "./test-js/metadata"; + it("handles plain text", async () => { + const res = await exec("eask analyze", { cwd }); + expect(res).toBeTruthy(); + + const res1 = await exec("eask analyze Eask", { cwd }); + expect(res1).toBeTruthy(); + }); + + it("handles json", async () => { + const res = await exec("eask analyze --json", { cwd }); + expect(res).toBeTruthy(); + + const res1 = await exec("eask analyze Eask --json", { + cwd, + }); + expect(res1).toBeTruthy(); + }); + }); +}); diff --git a/test-js/dsl/.gitignore b/test-js/dsl/.gitignore new file mode 100644 index 00000000..a50232f7 --- /dev/null +++ b/test-js/dsl/.gitignore @@ -0,0 +1,14 @@ +# ignore these directories +/.git +/recipes + +# ignore generated files +*.elc + +# eask packages +.eask/ +dist/ + +# packaging +*-autoloads.el +*-pkg.el diff --git a/test-js/dsl/Eask b/test-js/dsl/Eask new file mode 100644 index 00000000..a7dd0905 --- /dev/null +++ b/test-js/dsl/Eask @@ -0,0 +1,44 @@ +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 + +;; +;;; Below are errors/warnings to lint + +(package "check-dsl" "0.0.1" "Test for DSL") ; duplicate `package` directive +(package "" "" "") + +(website-url "https://github.com/emacs-eask/check-dsl") ; duplicate url +(website-url "https://github.com/emacs-eask/check-dsl") +(keywords "dsl") ; duplicate keywords +(keywords "dsl") + +(author "name") ; duplicate `author` +(author "name") + +(license "GPLv3") ; duplicate `license` +(license "GPLv3") + +(package-file "check-dsl.el") ; duplicate `package-file` directive +(package-file "check-dsl.el") + +(package-descriptor "check-pkg.el") ; duplicate `package-descriptor` directive +(package-descriptor "check-pkg.el") + +;; duplicate scripts +(script "test" "echo \"Error: no test specified\" && exit 1") +(script "test" "echo \"Error: no test specified\" && exit 1") + +(source 'gnu) ; duplicate archives +(source 'gnu) + +(source "magic-archive") ; Unkown archive + +(depends-on "emacs" "26.1") ; duplicate `emacs` dependency +(depends-on "emacs") + +(depends-on "dash") ; duplicate dependency +(depends-on "dash") + +(development + (depends-on "f") ; duplicate dependency + (depends-on "f") + ) diff --git a/test-js/dsl/check-dsl.el b/test-js/dsl/check-dsl.el new file mode 100644 index 00000000..e6407257 --- /dev/null +++ b/test-js/dsl/check-dsl.el @@ -0,0 +1,37 @@ +;;; check-dsl.el --- Test for DSL -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2025 the Eask authors. +;; Created date 2022-04-19 15:16:50 + +;; Author: Shen, Jen-Chieh +;; URL: https://github.com/emacs-eask/check-dsl +;; Version: 0.0.1 +;; Package-Requires: ((emacs "24.3") (dash "0.1")) +;; Keywords: dsl + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; Test for DSL. +;; + +;;; Code: + + + +(provide 'check-dsl) +;;; check-dsl.el ends here diff --git a/test-js/empty/.gitkeep b/test-js/empty/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test-js/metadata/.gitignore b/test-js/metadata/.gitignore new file mode 100644 index 00000000..a50232f7 --- /dev/null +++ b/test-js/metadata/.gitignore @@ -0,0 +1,14 @@ +# ignore these directories +/.git +/recipes + +# ignore generated files +*.elc + +# eask packages +.eask/ +dist/ + +# packaging +*-autoloads.el +*-pkg.el diff --git a/test-js/metadata/Eask b/test-js/metadata/Eask new file mode 100644 index 00000000..25b9ca66 --- /dev/null +++ b/test-js/metadata/Eask @@ -0,0 +1,16 @@ +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 + +;; +;;; Below are errors/warnings to lint + +(package "check-metadata?" ; unmatched + "0.0.1?" ; unmatched and invalid version syntax + "Test for unmatch metadata?" ; unmatched + ) + +(website-url "https://github.com/emacs-eask/check-metadata?") ; unmatched +(keywords "metadata?") ; missing + +(package-file "check-metadata.el") + +(depends-on "s") ; unmatch dependency diff --git a/test-js/metadata/check-metadata.el b/test-js/metadata/check-metadata.el new file mode 100644 index 00000000..301968d8 --- /dev/null +++ b/test-js/metadata/check-metadata.el @@ -0,0 +1,37 @@ +;;; check-metadata.el --- Test for unmatch metadata -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2025 the Eask authors. +;; Created date 2022-04-19 15:16:50 + +;; Author: Shen, Jen-Chieh +;; URL: https://github.com/emacs-eask/check-metadata +;; Version: 0.0.1 +;; Package-Requires: ((emacs "24.3") (dash "0.1")) +;; Keywords: metadata + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; Test for unmatch metadata. +;; + +;;; Code: + + + +(provide 'check-metadata) +;;; check-metadata.el ends here From 1f9902fa4ee9dc844ac1c92385558aae90c0af09 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 14:38:25 -0700 Subject: [PATCH 03/70] Add testUnsafe helper and config.test.js --- package.json | 1 + test-js/config.test.js | 32 ++++++++++++++++++++++++++++++++ test-js/helpers.js | 15 +++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 test-js/config.test.js create mode 100644 test-js/helpers.js diff --git a/package.json b/package.json index 569b7b80..3802dcf5 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "A set of command-line tools to build Emacs packages", "main": "eask", "scripts": { + "test-docker": "env ALLOW_UNSAFE=1 jest", "test": "jest", "pkg-all": "pkg package.json", "pkg-linux-arm64": "pkg package.json -t node*-linuxstatic-arm64 --output dist/eask --public", diff --git a/test-js/config.test.js b/test-js/config.test.js new file mode 100644 index 00000000..a6f4bbb0 --- /dev/null +++ b/test-js/config.test.js @@ -0,0 +1,32 @@ +const util = require("node:util"); +const exec = util.promisify(require("node:child_process").exec); +const { testUnsafe } = require("./helpers"); + +describe("config param", () => { + test("eask archives -c", async () => { + const res = await exec("eask archives -c"); + expect(res).toBeTruthy(); + }); + + // TODO perhaps teardown the following two? + // TODO check in docker + testUnsafe("eask install -c", async () => { + const res = await exec("eask install -cp spinner ivy beacon company fuzzy"); + expect(res).toBeTruthy(); + }); + + testUnsafe("eask uninstall -c", async () => { + const res = await exec("eask uninstall -c ivy fuzzy"); + expect(res).toBeTruthy(); + }); + + test("eask list -c", async () => { + const res = await exec("eask list -c --depth=0"); + expect(res).toBeTruthy(); + }); + + test("eask outdated -c", async () => { + const res = await exec("eask outdated -c"); + expect(res).toBeTruthy(); + }); +}); diff --git a/test-js/helpers.js b/test-js/helpers.js new file mode 100644 index 00000000..9f7f2091 --- /dev/null +++ b/test-js/helpers.js @@ -0,0 +1,15 @@ +/** + * As for jest.test but skips running if the ALLOW_UNSAFE env var is set. + * @param {string} name + * @param {any} fn + * @param {number} timeout + */ +function testUnsafe(name, fn, timeout) { + if (process.env.ALLOW_UNSAFE) { + return test(name, fn, timeout); + } else { + return test.skip(name, fn, timeout); + } +} + +module.exports = { testUnsafe }; From d63f6b4639fba54cd3b5afd6aa90df99c31a23ae Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 15:30:57 -0700 Subject: [PATCH 04/70] Add mini.pkg.1 to test-js/ --- test-js/mini.pkg.1/Eask | 37 ++++++++++++++++++++++ test-js/mini.pkg.1/RADME.md | 1 + test-js/mini.pkg.1/files/mini.pkg.1-1.el | 32 +++++++++++++++++++ test-js/mini.pkg.1/files/mini.pkg.1-2.el | 31 +++++++++++++++++++ test-js/mini.pkg.1/mini.pkg.1.el | 39 ++++++++++++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 test-js/mini.pkg.1/Eask create mode 100644 test-js/mini.pkg.1/RADME.md create mode 100644 test-js/mini.pkg.1/files/mini.pkg.1-1.el create mode 100644 test-js/mini.pkg.1/files/mini.pkg.1-2.el create mode 100644 test-js/mini.pkg.1/mini.pkg.1.el diff --git a/test-js/mini.pkg.1/Eask b/test-js/mini.pkg.1/Eask new file mode 100644 index 00000000..480eef12 --- /dev/null +++ b/test-js/mini.pkg.1/Eask @@ -0,0 +1,37 @@ +(package "mini.pkg.1" + "0.0.1" + "Minimal test package") + +(website-url "https://github.com/emacs-eask/cli/tree/master/test/fixtures/mini.pkg.1") +(keywords "test" "local") + +(package-file "mini.pkg.1.el") + +(files "files/*.el") + +(script "test" "echo \"Have a nice day!~ ;)\"") +(script "extra" "echo :") +(script "info" "eask info") + +(eask-defcommand mini-test-1 "Test command 1." (message "Test 1")) +(eask-defcommand mini-test-2 "Test command 2." (message "Test 2")) +(eask-defcommand mini-test-3 + "Test command 3." + (message "Test 3: %s" eask-rest)) + +(source 'gnu) +(source 'melpa) +(source 'jcs-elpa) + +(depends-on "emacs" "26.1") +(depends-on "f") +(depends-on "s") +(depends-on "fringe-helper") +(depends-on "watch-cursor" + :repo "jcs-elpa/watch-cursor" :fetcher 'github) +(depends-on "organize-imports-java" + :repo "jcs-elpa/organize-imports-java" + :fetcher 'github + :files '(:defaults "sdk" "default")) + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test-js/mini.pkg.1/RADME.md b/test-js/mini.pkg.1/RADME.md new file mode 100644 index 00000000..441cfd06 --- /dev/null +++ b/test-js/mini.pkg.1/RADME.md @@ -0,0 +1 @@ +Minimal Emacs package to simulate development environment; only for testing purposes! diff --git a/test-js/mini.pkg.1/files/mini.pkg.1-1.el b/test-js/mini.pkg.1/files/mini.pkg.1-1.el new file mode 100644 index 00000000..1c7e7c73 --- /dev/null +++ b/test-js/mini.pkg.1/files/mini.pkg.1-1.el @@ -0,0 +1,32 @@ +;;; mini.pkg.1-1.el --- Extern file 1 -*- lexical-binding: t; -*- + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; files/mini.pkg.1-1.el +;; + +;;; Code: + + +(defun mini.pkg.1-1 () + "Test function 1." + (interactive) + ) + +(provide 'mini.pkg.1-1) +;;; mini.pkg.1-1.el ends here diff --git a/test-js/mini.pkg.1/files/mini.pkg.1-2.el b/test-js/mini.pkg.1/files/mini.pkg.1-2.el new file mode 100644 index 00000000..09d7eb8c --- /dev/null +++ b/test-js/mini.pkg.1/files/mini.pkg.1-2.el @@ -0,0 +1,31 @@ +;;; mini.pkg.1-2.el --- Extern file 2 -*- lexical-binding: t; -*- + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; files/mini.pkg.1-2.el +;; + +;;; Code: + +(defun mini.pkg.1-2 () + "Test function 2." + (interactive) + ) + +(provide 'mini.pkg.1-2) +;;; mini.pkg.1-2.el ends here diff --git a/test-js/mini.pkg.1/mini.pkg.1.el b/test-js/mini.pkg.1/mini.pkg.1.el new file mode 100644 index 00000000..1db1a166 --- /dev/null +++ b/test-js/mini.pkg.1/mini.pkg.1.el @@ -0,0 +1,39 @@ +;;; mini.pkg.1.el --- Minimal test package -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2025 the Eask authors. +;; Created date 2022-03-29 01:52:58 + +;; Author: Shen, Jen-Chieh +;; URL: https://github.com/emacs-eask/cli/tree/master/test/fixtures/mini.pkg.1 +;; Version: 0.0.1 +;; Package-Requires: ((emacs "24.3") (s "1.12.0") (fringe-helper "1.0.1")) +;; Keywords: test local + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; Minimal Emacs package to simulate development environment; only for testing +;; purposes! +;; + +;;; Code: + +(require 's) +(require 'fringe-helper) + +(provide 'mini.pkg.1) +;;; mini.pkg.1.el ends here From 405a983d4b2be8806148c0252c186d4831ec208a Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 15:43:08 -0700 Subject: [PATCH 05/70] Add exec.test.js --- test-js/exec.test.js | 40 ++++++++++++++++++++++++++++++++ test-js/exec/.gitignore | 14 +++++++++++ test-js/exec/Eask | 20 ++++++++++++++++ test-js/exec/bin/github-elpa.bat | 2 ++ test-js/exec/exec.el | 37 +++++++++++++++++++++++++++++ test-js/exec/test/test-dummy.el | 36 ++++++++++++++++++++++++++++ 6 files changed, 149 insertions(+) create mode 100644 test-js/exec.test.js create mode 100644 test-js/exec/.gitignore create mode 100644 test-js/exec/Eask create mode 100644 test-js/exec/bin/github-elpa.bat create mode 100644 test-js/exec/exec.el create mode 100644 test-js/exec/test/test-dummy.el diff --git a/test-js/exec.test.js b/test-js/exec.test.js new file mode 100644 index 00000000..a321808c --- /dev/null +++ b/test-js/exec.test.js @@ -0,0 +1,40 @@ +const util = require("node:util"); +const exec = util.promisify(require("node:child_process").exec); +const execSync = require("node:child_process").execSync; + +describe("exec", () => { + const cwd = "./test-js/exec"; + + beforeAll(() => execSync("eask install-deps", { cwd })); + + test("eask exec ert-runner", async () => { + const res = await exec("eask exec ert-runner -h", { cwd }); + expect(res).toBeTruthy(); + }); + + test("eask exec github-elpa", async () => { + const res = await exec("eask exec github-elpa -h", { cwd }); + expect(res).toBeTruthy(); + }); + + test("eask exec echo", async () => { + const res = await exec("eask exec echo hello world", { cwd }); + expect(res).toBeTruthy(); + }); + + test("eask exec buttercup -L .", async () => { + const res = await exec("eask exec buttercup -L .", { cwd }); + expect(res).toBeTruthy(); + }); + + test("eask exec buttercup -L . --pattern 'pattern 1'", async () => { + const res = await exec("eask exec buttercup -L . --pattern 'pattern 1'", { + cwd, + }); + expect(res).toBeTruthy(); + }); + + test("should error with no args", async () => { + await expect(exec("./bin/eask exec", { cwd })).rejects.toThrow(); + }); +}); diff --git a/test-js/exec/.gitignore b/test-js/exec/.gitignore new file mode 100644 index 00000000..a50232f7 --- /dev/null +++ b/test-js/exec/.gitignore @@ -0,0 +1,14 @@ +# ignore these directories +/.git +/recipes + +# ignore generated files +*.elc + +# eask packages +.eask/ +dist/ + +# packaging +*-autoloads.el +*-pkg.el diff --git a/test-js/exec/Eask b/test-js/exec/Eask new file mode 100644 index 00000000..3a9b9b2b --- /dev/null +++ b/test-js/exec/Eask @@ -0,0 +1,20 @@ +(package "exec" + "0.0.1" + "Test project for command exec") + +(website-url "https://github.com/emacs-eask/exec") +(keywords "exec") + +(package-file "exec.el") + +(exec-paths "./bin/") + +(source 'gnu) +(source 'melpa) + +(depends-on "emacs" "26.1") +(depends-on "ert-runner") +(depends-on "github-elpa") +(depends-on "buttercup") + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test-js/exec/bin/github-elpa.bat b/test-js/exec/bin/github-elpa.bat new file mode 100644 index 00000000..b444158f --- /dev/null +++ b/test-js/exec/bin/github-elpa.bat @@ -0,0 +1,2 @@ +@echo off +echo Test from github-elpa.bat diff --git a/test-js/exec/exec.el b/test-js/exec/exec.el new file mode 100644 index 00000000..c9d67827 --- /dev/null +++ b/test-js/exec/exec.el @@ -0,0 +1,37 @@ +;;; exec.el --- Test project for command exec -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2025 the Eask authors. +;; Created date 2022-03-29 14:10:40 + +;; Author: Shen, Jen-Chieh +;; URL: https://github.com/emacs-eask/exec +;; Version: 0.0.1 +;; Package-Requires: ((emacs "26.1")) +;; Keywords: exec + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; Test project for command exec. +;; + +;;; Code: + +(require 'cl-lib) + +(provide 'exec) +;;; exec.el ends here diff --git a/test-js/exec/test/test-dummy.el b/test-js/exec/test/test-dummy.el new file mode 100644 index 00000000..bae38926 --- /dev/null +++ b/test-js/exec/test/test-dummy.el @@ -0,0 +1,36 @@ +;;; test-dummy.el --- Dummy buttercup test -*- lexical-binding: t; -*- + +;; Copyright (C) 2023 the Eask authors. + +;; This file is not part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; Dummy buttercup test. +;; + +;;; Code: + +(describe "Dumm Test" + (it "pattern 1" + (let ((dummy-var-1 t)) + (expect dummy-var-1 :to-be t))) + (it "pattern 2" + (let ((dummy-var-2 nil)) + (expect dummy-var-2 :to-be nil)))) + +(provide 'test-dummy) +;;; test-dummy.el ends here From 1a1c302cef620a4274980cd02a9fd86509078cb0 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 18:43:02 -0700 Subject: [PATCH 06/70] Add emacsVersion helper Fix return type of emacsVersion() --- test-js/helpers.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/test-js/helpers.js b/test-js/helpers.js index 9f7f2091..ff134b06 100644 --- a/test-js/helpers.js +++ b/test-js/helpers.js @@ -1,3 +1,6 @@ +const util = require("node:util"); +const exec = util.promisify(require("node:child_process").exec); + /** * As for jest.test but skips running if the ALLOW_UNSAFE env var is set. * @param {string} name @@ -12,4 +15,18 @@ function testUnsafe(name, fn, timeout) { } } -module.exports = { testUnsafe }; +/** + * The version string for system emacs, e.g. "30.0.50". + * You can compare lexicographically, e.g. if ((await emacsVersion()) > "27") { ... } + * @returns {Promise.} emacs version string. + */ +async function emacsVersion() { + const text = await exec("emacs --version"); + const version = text.stdout.match("Emacs ([^ ]+)")?.[1]; + if (!version) { + throw Error("Couldn't extract Emacs version. Text was:\n" + text); + } + return version; +} + +module.exports = { testUnsafe, emacsVersion }; From 7310c972f08ea98e64480f6609c3fc5622f789a6 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 19:08:16 -0700 Subject: [PATCH 07/70] NPM script to reset test environments --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 3802dcf5..75a24263 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "test-docker": "env ALLOW_UNSAFE=1 jest", "test": "jest", + "test-reset": "rm -rf ./test-js/.eask ./test-js/*/.eask; git restore ./test-js/*/", "pkg-all": "pkg package.json", "pkg-linux-arm64": "pkg package.json -t node*-linuxstatic-arm64 --output dist/eask --public", "pkg-linux-x64": "pkg package.json -t node*-linuxstatic-x64 --output dist/eask --public", From ed38d21ae3a18f456dcea8a8741ecf251fd1ee04 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 23:25:12 -0700 Subject: [PATCH 08/70] Add TestContext class and simplify exec.test.js --- test-js/exec.test.js | 29 +++++++++++------------------ test-js/helpers.js | 29 ++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/test-js/exec.test.js b/test-js/exec.test.js index a321808c..0dc4ff4b 100644 --- a/test-js/exec.test.js +++ b/test-js/exec.test.js @@ -1,40 +1,33 @@ -const util = require("node:util"); -const exec = util.promisify(require("node:child_process").exec); -const execSync = require("node:child_process").execSync; +const { TestContext } = require("./helpers"); describe("exec", () => { - const cwd = "./test-js/exec"; + const ctx = new TestContext("./test-js/exec"); - beforeAll(() => execSync("eask install-deps", { cwd })); + beforeAll(async () => await ctx.runEask("install-deps"), 10000); + + afterAll(() => ctx.cleanUp()); test("eask exec ert-runner", async () => { - const res = await exec("eask exec ert-runner -h", { cwd }); - expect(res).toBeTruthy(); + await ctx.runEask("exec ert-runner -h"); }); test("eask exec github-elpa", async () => { - const res = await exec("eask exec github-elpa -h", { cwd }); - expect(res).toBeTruthy(); + await ctx.runEask("exec github-elpa -h"); }); test("eask exec echo", async () => { - const res = await exec("eask exec echo hello world", { cwd }); - expect(res).toBeTruthy(); + await ctx.runEask("exec echo hello world"); }); test("eask exec buttercup -L .", async () => { - const res = await exec("eask exec buttercup -L .", { cwd }); - expect(res).toBeTruthy(); + await ctx.runEask("exec buttercup -L ."); }); test("eask exec buttercup -L . --pattern 'pattern 1'", async () => { - const res = await exec("eask exec buttercup -L . --pattern 'pattern 1'", { - cwd, - }); - expect(res).toBeTruthy(); + await ctx.runEask("exec buttercup -L . --pattern 'pattern 1'"); }); test("should error with no args", async () => { - await expect(exec("./bin/eask exec", { cwd })).rejects.toThrow(); + await expect(ctx.runEask("exec")).rejects.toThrow(); }); }); diff --git a/test-js/helpers.js b/test-js/helpers.js index ff134b06..11abe12a 100644 --- a/test-js/helpers.js +++ b/test-js/helpers.js @@ -29,4 +29,31 @@ async function emacsVersion() { return version; } -module.exports = { testUnsafe, emacsVersion }; +class TestContext { + /** + * @param {string} cwd Current Working Directory, used for all commands. + */ + constructor(cwd) { + this.cwd = cwd; + this.easkCommand = process.env.EASK_COMMAND || "eask"; + this.controller = new AbortController(); + } + + runEask(command, config) { + return this.run(this.easkCommand + " " + command, config); + } + + run(command, config) { + return exec(command, { + cwd: this.cwd, + signal: this.controller.signal, + ...config, + }); + } + + cleanUp() { + this.controller.abort(); + } +} + +module.exports = { testUnsafe, emacsVersion, TestContext }; From a6727552821136afa39eadd08efab6d079a72cba Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 16:01:32 -0700 Subject: [PATCH 09/70] Add options.test.js --- test-js/options.test.js | 94 ++++++++++++++++++++++++++++++++++++++ test-js/options/.gitignore | 14 ++++++ test-js/options/Eask | 12 +++++ 3 files changed, 120 insertions(+) create mode 100644 test-js/options.test.js create mode 100644 test-js/options/.gitignore create mode 100644 test-js/options/Eask diff --git a/test-js/options.test.js b/test-js/options.test.js new file mode 100644 index 00000000..7e85643f --- /dev/null +++ b/test-js/options.test.js @@ -0,0 +1,94 @@ +const { TestContext } = require("./helpers"); + +describe("options", () => { + const ctx = new TestContext("./test-js/options"); + + test("eask info -g should error", async () => { + await expect(ctx.runEask("info -g")).rejects.toThrow(); + await expect(ctx.runEask("info -global")).rejects.toThrow(); + }); + + test("eask info -a", async () => { + await ctx.runEask("info -a"); + }); + + test("eask info --all", async () => { + await ctx.runEask("info --all"); + }); + + test("eask info -q", async () => { + await ctx.runEask("info -q"); + }); + + test("eask info --quick", async () => { + await ctx.runEask("info --quick"); + }); + + test("eask info -f", async () => { + await ctx.runEask("info -f"); + }); + + test("eask info --force", async () => { + await ctx.runEask("info --force"); + }); + + test("eask info --debug", async () => { + await ctx.runEask("info --debug"); + }); + + test("eask info --strict", async () => { + await ctx.runEask("info --strict"); + }); + + test("eask info --allow-error", async () => { + await ctx.runEask("info --allow-error"); + }); + + test("eask info --insecure", async () => { + await ctx.runEask("info --insecure"); + }); + + test("eask info --timestamps", async () => { + await ctx.runEask("info --timestamps"); + }); + + test("eask info --log-level", async () => { + await ctx.runEask("info --log-level"); + }); + + test("eask info --elapsed-time", async () => { + await ctx.runEask("info --elapsed-time"); + }); + + test("eask info --et", async () => { + await ctx.runEask("info --et"); + }); + + test("eask info --no-color", async () => { + await ctx.runEask("info --no-color"); + }); + + test("eask info --proxy localhost:8080", async () => { + await ctx.runEask("info --proxy localhost:8080"); + }); + + test("eask info --http-proxy localhost:8080", async () => { + await ctx.runEask("info --http-proxy localhost:8080"); + }); + + test("eask info --https-proxy localhost:8080", async () => { + await ctx.runEask("info --https-proxy localhost:8080"); + }); + + test("eask info --no-proxy localhost:8080", async () => { + await ctx.runEask("info --no-proxy localhost:8080"); + }); + + test("eask info -v 4", async () => { + await ctx.runEask("info -v 4"); + }); + + test("eask info --verbose 4", async () => { + await ctx.runEask("info --verbose 4"); + }); +}); diff --git a/test-js/options/.gitignore b/test-js/options/.gitignore new file mode 100644 index 00000000..a50232f7 --- /dev/null +++ b/test-js/options/.gitignore @@ -0,0 +1,14 @@ +# ignore these directories +/.git +/recipes + +# ignore generated files +*.elc + +# eask packages +.eask/ +dist/ + +# packaging +*-autoloads.el +*-pkg.el diff --git a/test-js/options/Eask b/test-js/options/Eask new file mode 100644 index 00000000..ee70be40 --- /dev/null +++ b/test-js/options/Eask @@ -0,0 +1,12 @@ +(package "options" + "0.0.0" + "Test all options flag") + +(website-url "https://github.com/emacs-eask/options") +(keywords "test") + +(package-file "options.el") + +(source 'gnu) + +(depends-on "emacs" "26.1") From 613a145f934a66b187728f007690e8a6b354995b Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 19:27:23 -0700 Subject: [PATCH 10/70] Add buttercup.test.js --- test-js/buttercup.test.js | 35 +++++++++++++++++++ test-js/buttercup/.gitignore | 14 ++++++++ test-js/buttercup/Eask | 13 +++++++ test-js/buttercup/test-fail/buttercup-test.el | 31 ++++++++++++++++ test-js/buttercup/test-ok/buttercup-test.el | 31 ++++++++++++++++ 5 files changed, 124 insertions(+) create mode 100644 test-js/buttercup.test.js create mode 100644 test-js/buttercup/.gitignore create mode 100644 test-js/buttercup/Eask create mode 100644 test-js/buttercup/test-fail/buttercup-test.el create mode 100644 test-js/buttercup/test-ok/buttercup-test.el diff --git a/test-js/buttercup.test.js b/test-js/buttercup.test.js new file mode 100644 index 00000000..a6f47c05 --- /dev/null +++ b/test-js/buttercup.test.js @@ -0,0 +1,35 @@ +const { TestContext } = require("./helpers"); + +jest.setTimeout(10000); + +describe("buttercup", () => { + const ctx = new TestContext("./test-js/buttercup"); + + beforeAll(async () => await ctx.runEask("install-deps --dev")); + + test("run all tests", async () => { + // this runs all tests, so should error + await expect(ctx.runEask("test buttercup")).rejects.toThrow(); + }); + + // buttercup takes directories as arguments + test("run succeeding tests", async () => { + await ctx.runEask("test buttercup ./test-ok"); + }); + + test("run all tests explicitly", async () => { + await expect( + ctx.runEask("test buttercup ./test-ok ./test-fail"), + ).rejects.toThrow(); + }); + + test("does not take options", async () => { + await ctx.runEask("test buttercup --no-color ./test-ok"); + }); + + // Because load-path is manually set, cannot refer to parent directories. + // Note this does work if you do ../buttercup/test-ok/, but not for any other directory. + test("running paths in parent dir", async () => { + await expect(ctx.runEask("test buttercup ../bin")).rejects.toThrow(); + }); +}); diff --git a/test-js/buttercup/.gitignore b/test-js/buttercup/.gitignore new file mode 100644 index 00000000..a50232f7 --- /dev/null +++ b/test-js/buttercup/.gitignore @@ -0,0 +1,14 @@ +# ignore these directories +/.git +/recipes + +# ignore generated files +*.elc + +# eask packages +.eask/ +dist/ + +# packaging +*-autoloads.el +*-pkg.el diff --git a/test-js/buttercup/Eask b/test-js/buttercup/Eask new file mode 100644 index 00000000..d026ebbc --- /dev/null +++ b/test-js/buttercup/Eask @@ -0,0 +1,13 @@ +(package "buttercup" + "0.0.1" + "Test project for command `buttercup'") + +(package-file "buttercup.el") + +(source 'gnu) +(source 'melpa) + +(development + (depends-on "buttercup")) + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test-js/buttercup/test-fail/buttercup-test.el b/test-js/buttercup/test-fail/buttercup-test.el new file mode 100644 index 00000000..6f61aad4 --- /dev/null +++ b/test-js/buttercup/test-fail/buttercup-test.el @@ -0,0 +1,31 @@ +;;; buttercup-test.el --- Test the command buttercup -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2025 the Eask authors. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Tests for the command buttercup + +;;; Code: + +(require 'buttercup) +(require 'debug) + +(describe "A failing suite" + (it "contains a spec with a false expectation" + (expect t :to-be nil))) + +;;; buttercup-test.el ends here diff --git a/test-js/buttercup/test-ok/buttercup-test.el b/test-js/buttercup/test-ok/buttercup-test.el new file mode 100644 index 00000000..ed52b235 --- /dev/null +++ b/test-js/buttercup/test-ok/buttercup-test.el @@ -0,0 +1,31 @@ +;;; buttercup-test.el --- Test the command buttercup -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2025 the Eask authors. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Tests for the command buttercup + +;;; Code: + +(require 'buttercup) +(require 'debug) + +(describe "A suite" + (it "contains a spec with an expectation" + (expect t :to-be t))) + +;;; buttercup-test.el ends here From a6e54b307f89554b8f2e70d99353b34f6faa9453 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 17:06:46 -0700 Subject: [PATCH 11/70] Add outdated.test.js --- test-js/outdated.test.js | 23 +++++++++ test-js/outdated_upgrade/.gitignore | 14 ++++++ test-js/outdated_upgrade/Eask | 13 ++++++ test-js/outdated_upgrade/make-outdate.el | 59 ++++++++++++++++++++++++ 4 files changed, 109 insertions(+) create mode 100644 test-js/outdated.test.js create mode 100644 test-js/outdated_upgrade/.gitignore create mode 100644 test-js/outdated_upgrade/Eask create mode 100644 test-js/outdated_upgrade/make-outdate.el diff --git a/test-js/outdated.test.js b/test-js/outdated.test.js new file mode 100644 index 00000000..aae52ab5 --- /dev/null +++ b/test-js/outdated.test.js @@ -0,0 +1,23 @@ +const { TestContext } = require("./helpers"); + +describe("outdated and upgrade", () => { + const ctx = new TestContext("./test-js/outdated_upgrade"); + + beforeAll(async () => { + await ctx.runEask("install-deps"); + await ctx.runEask("load make-outdate.el"); + }, 15000); + + // these will run in sequence + afterAll(async () => await ctx.runEask("clean all")); + afterAll(() => ctx.cleanUp()); + + test("list outdated", async () => { + await ctx.runEask("outdated"); + await ctx.runEask("outdated --depth 0"); + }); + + test("upgrade", async () => { + await ctx.runEask("upgrade"); + }); +}); diff --git a/test-js/outdated_upgrade/.gitignore b/test-js/outdated_upgrade/.gitignore new file mode 100644 index 00000000..a50232f7 --- /dev/null +++ b/test-js/outdated_upgrade/.gitignore @@ -0,0 +1,14 @@ +# ignore these directories +/.git +/recipes + +# ignore generated files +*.elc + +# eask packages +.eask/ +dist/ + +# packaging +*-autoloads.el +*-pkg.el diff --git a/test-js/outdated_upgrade/Eask b/test-js/outdated_upgrade/Eask new file mode 100644 index 00000000..00283012 --- /dev/null +++ b/test-js/outdated_upgrade/Eask @@ -0,0 +1,13 @@ +(package "outdated-upgrade" + "0.0.1" + "Test project for command outdated and upgrade") + +(package-file "outdated-upgrade.el") + +(source 'gnu) +(source 'melpa) + +(depends-on "f") +(depends-on "s") + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test-js/outdated_upgrade/make-outdate.el b/test-js/outdated_upgrade/make-outdate.el new file mode 100644 index 00000000..63d6c5d7 --- /dev/null +++ b/test-js/outdated_upgrade/make-outdate.el @@ -0,0 +1,59 @@ +;;; make-outdate.el --- Make some packages outdate -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2025 the Eask authors. + +;; This file is not part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; Make some packages outdate +;; + +;;; Code: + +(eask-pkg-init) + +(require 'f) + +(defconst make-outdate-version "20001122.1234" + "Outdate version.") + +(defun make-outdate-package (name) + "Make package (NAME) outdate." + (let* ((dir (file-name-directory (locate-library name))) + (pkg (concat dir name "-pkg.el"))) + (with-current-buffer (find-file pkg) + (goto-char (point-min)) + (when (re-search-forward "\"[0-9.]*\"" nil t) + (save-excursion + (let ((end (point))) + (backward-sexp) + (delete-region (point) end) + (insert (format "\"%s\"" make-outdate-version))))) + (save-buffer) + (kill-this-buffer)) + (let ((dest (expand-file-name (concat name "-" make-outdate-version "/") package-user-dir))) + (eask-info "Moving %s" dir) + (eask-info " to %s" dest) + (ignore-errors (make-directory dest t)) + (f-copy-contents dir dest) + (ignore-errors (delete-directory dir t))))) + +(make-outdate-package "dash") +(make-outdate-package "f") + +(provide 'make-outdate) +;;; make-outdate.el ends here From 7cf92e1b5c3b05f845ef78dc90a4273983835c79 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 18:56:09 -0700 Subject: [PATCH 12/70] Add emacs.test.js --- test-js/emacs.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 test-js/emacs.test.js diff --git a/test-js/emacs.test.js b/test-js/emacs.test.js new file mode 100644 index 00000000..63f328bc --- /dev/null +++ b/test-js/emacs.test.js @@ -0,0 +1,18 @@ +const { TestContext } = require("./helpers"); + +describe("emacs", () => { + const cwd = "./test-js/empty"; + const ctx = new TestContext(cwd); + + beforeAll(async () => await ctx.runEask("clean all")); + + test("eask emacs --version", async () => { + await ctx.runEask("emacs --version"); + }); + + test("eask emacs --batch --eval", async () => { + await ctx.runEask( + 'emacs --batch --eval "(require (quote ert))" --eval "(ert-deftest mytest () (should-not (display-graphic-p)))" -f ert-run-tests-batch', + ); + }); +}); From 9822b1e5a47a6918155e90907b3d592fe5314f81 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 16:52:50 -0700 Subject: [PATCH 13/70] Add search.test.js --- test-js/search.test.js | 22 ++++++++++++++++++++++ test-js/search/.gitignore | 14 ++++++++++++++ test-js/search/Eask | 10 ++++++++++ 3 files changed, 46 insertions(+) create mode 100644 test-js/search.test.js create mode 100644 test-js/search/.gitignore create mode 100644 test-js/search/Eask diff --git a/test-js/search.test.js b/test-js/search.test.js new file mode 100644 index 00000000..2c1d64f1 --- /dev/null +++ b/test-js/search.test.js @@ -0,0 +1,22 @@ +const { TestContext } = require("./helpers"); + +describe("search", () => { + const cwd = "./test-js/search"; + const ctx = new TestContext(cwd); + + test("eask search company", async () => { + await ctx.runEask("search company"); + }); + + test("eask search company dash --depth 0", async () => { + await ctx.runEask("search company dash --depth 0"); + }); + + test("eask search company dash f s --depth 0 -g", async () => { + await ctx.runEask("search company dash f s --depth 0 -g"); + }); + + test("eask search should error", async () => { + await expect(ctx.runEask("search")).rejects.toThrow(); + }); +}); diff --git a/test-js/search/.gitignore b/test-js/search/.gitignore new file mode 100644 index 00000000..a50232f7 --- /dev/null +++ b/test-js/search/.gitignore @@ -0,0 +1,14 @@ +# ignore these directories +/.git +/recipes + +# ignore generated files +*.elc + +# eask packages +.eask/ +dist/ + +# packaging +*-autoloads.el +*-pkg.el diff --git a/test-js/search/Eask b/test-js/search/Eask new file mode 100644 index 00000000..51558d01 --- /dev/null +++ b/test-js/search/Eask @@ -0,0 +1,10 @@ +(package "search" + "0.0.1" + "Test project for command `search'") + +(package-file "search.el") + +(source 'gnu) +(source 'melpa) + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 From a97b28bf65bf8c2612e26e5ee22a3c7edb74f66a Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 15:31:25 -0700 Subject: [PATCH 14/70] Add link.test.js --- test-js/link.test.js | 35 +++++++++++++++++++++++++++++++++++ test-js/link/.gitkeep | 0 test-js/link/Eask | 14 ++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 test-js/link.test.js create mode 100644 test-js/link/.gitkeep create mode 100644 test-js/link/Eask diff --git a/test-js/link.test.js b/test-js/link.test.js new file mode 100644 index 00000000..a645bef8 --- /dev/null +++ b/test-js/link.test.js @@ -0,0 +1,35 @@ +const { TestContext } = require("./helpers"); + +describe("link", () => { + describe("normally", () => { + const cwd = "./test-js/link"; + const ctx = new TestContext(cwd); + it("adds a link", async () => { + await ctx.runEask('link add "mini.pkg.1" "./test/mini.pkg.1/"'); + }); + + it("lists links", async () => { + await ctx.runEask("link list"); + }); + + it("deletes links", async () => { + await ctx.runEask("link delete mini.pkg.1-0.0.1"); + }); + }); + + describe("in an empty directory", () => { + const ctx = new TestContext("./test-js/empty"); + + it("eask link add should error", async () => { + await expect(ctx.runEask("link add")).rejects.toThrow(); + }); + + it("adding an unknown package should error", async () => { + await expect(ctx.runEask("link add foo .")).rejects.toThrow(); + }); + + it("deleting an unknown package should error", async () => { + await expect(ctx.runEask("link delete")).rejects.toThrow(); + }); + }); +}); diff --git a/test-js/link/.gitkeep b/test-js/link/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test-js/link/Eask b/test-js/link/Eask new file mode 100644 index 00000000..29876c88 --- /dev/null +++ b/test-js/link/Eask @@ -0,0 +1,14 @@ +(package "link" + "1.0.0" + "") + +(website-url "") +(keywords ) + +(package-file "link.el") + +(script "test" "echo \"Error: no test specified\" && exit 1") + +(source "gnu") + +(depends-on "emacs" "26.1") From 81ac7c86dc32f4ebdc0eaf007ff4fe2418c0f1ca Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 23:54:34 -0700 Subject: [PATCH 15/70] Log cmd output when DEBUG is set --- package.json | 1 + test-js/helpers.js | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/package.json b/package.json index 75a24263..c96e7c22 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "eask", "scripts": { "test-docker": "env ALLOW_UNSAFE=1 jest", + "test-debug": "env DEBUG=1 jest", "test": "jest", "test-reset": "rm -rf ./test-js/.eask ./test-js/*/.eask; git restore ./test-js/*/", "pkg-all": "pkg package.json", diff --git a/test-js/helpers.js b/test-js/helpers.js index 11abe12a..44aba73a 100644 --- a/test-js/helpers.js +++ b/test-js/helpers.js @@ -48,6 +48,13 @@ class TestContext { cwd: this.cwd, signal: this.controller.signal, ...config, + }).then((obj) => { + if (process.env.DEBUG) { + console.log(command); + console.log(obj.stdout); + console.log(obj.stderr); + } + return obj; }); } From 54e3a9cd17693fa0fa19e6f6e24e2988acea9293 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 19 Mar 2025 23:54:49 -0700 Subject: [PATCH 16/70] Fix config.test.js --- test-js/config.test.js | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/test-js/config.test.js b/test-js/config.test.js index a6f4bbb0..82888a7c 100644 --- a/test-js/config.test.js +++ b/test-js/config.test.js @@ -1,32 +1,33 @@ -const util = require("node:util"); -const exec = util.promisify(require("node:child_process").exec); -const { testUnsafe } = require("./helpers"); +const { testUnsafe, TestContext } = require("./helpers"); describe("config param", () => { + const ctx = new TestContext(); + + afterAll(() => ctx.cleanUp()); + + // TODO timeout test("eask archives -c", async () => { - const res = await exec("eask archives -c"); - expect(res).toBeTruthy(); + await ctx.runEask("archives -c"); }); // TODO perhaps teardown the following two? // TODO check in docker testUnsafe("eask install -c", async () => { - const res = await exec("eask install -cp spinner ivy beacon company fuzzy"); - expect(res).toBeTruthy(); + await ctx.runEask("install -c spinner ivy beacon company-fuzzy"); }); + // TODO should test uninstalling multiple testUnsafe("eask uninstall -c", async () => { - const res = await exec("eask uninstall -c ivy fuzzy"); - expect(res).toBeTruthy(); + await ctx.runEask("uninstall -c ivy company-fuzzy"); }); + // TODO timeout test("eask list -c", async () => { - const res = await exec("eask list -c --depth=0"); - expect(res).toBeTruthy(); + await ctx.runEask("list -c --depth=0"); }); + // TODO timeout test("eask outdated -c", async () => { - const res = await exec("eask outdated -c"); - expect(res).toBeTruthy(); + await ctx.runEask("outdated -c"); }); }); From 5f89df7ca0198be8a5021edb21d8a07e2e09fe1f Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Fri, 21 Mar 2025 14:41:44 -0700 Subject: [PATCH 17/70] Add test-ecukes.test.js --- test-js/ecukes/Eask | 13 +++++++++++++ test-js/ecukes/features/foo.feature | 0 .../features/step-definitions/ecukes-steps.el | 0 test-js/ecukes/features/support/env.el | 0 test-js/test-ecukes.test.js | 16 ++++++++++++++++ 5 files changed, 29 insertions(+) create mode 100644 test-js/ecukes/Eask create mode 100644 test-js/ecukes/features/foo.feature create mode 100644 test-js/ecukes/features/step-definitions/ecukes-steps.el create mode 100644 test-js/ecukes/features/support/env.el create mode 100644 test-js/test-ecukes.test.js diff --git a/test-js/ecukes/Eask b/test-js/ecukes/Eask new file mode 100644 index 00000000..cc5ec20f --- /dev/null +++ b/test-js/ecukes/Eask @@ -0,0 +1,13 @@ +(package "ecukes" + "0.0.1" + "Test project for command `ecukes'") + +(package-file "ecukes.el") + +(source 'gnu) +(source 'melpa) + +(development + (depends-on "ecukes")) + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test-js/ecukes/features/foo.feature b/test-js/ecukes/features/foo.feature new file mode 100644 index 00000000..e69de29b diff --git a/test-js/ecukes/features/step-definitions/ecukes-steps.el b/test-js/ecukes/features/step-definitions/ecukes-steps.el new file mode 100644 index 00000000..e69de29b diff --git a/test-js/ecukes/features/support/env.el b/test-js/ecukes/features/support/env.el new file mode 100644 index 00000000..e69de29b diff --git a/test-js/test-ecukes.test.js b/test-js/test-ecukes.test.js new file mode 100644 index 00000000..7d38aac1 --- /dev/null +++ b/test-js/test-ecukes.test.js @@ -0,0 +1,16 @@ +const { TestContext } = require("./helpers"); + +describe("test_ecukes", () => { + const ctx = new TestContext("./test-js/ecukes"); + + beforeAll(async () => await ctx.runEask("install-deps --dev"), 10000); + afterAll(() => ctx.cleanUp()); + + test("eask test ecukes", async () => { + await ctx.runEask("test ecukes"); + }); + + test("eask test ecukes ./features/foo.feature", async () => { + await ctx.runEask("test ecukes ./features/foo.feature"); + }); +}); From 1e80a68c8e6be44f0da29e899a8dfc3303b368a4 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Fri, 21 Mar 2025 14:53:37 -0700 Subject: [PATCH 18/70] Add test-ert.test.js --- test-js/ert/.gitignore | 14 +++++++++++ test-js/ert/Eask | 10 ++++++++ test-js/ert/test-nil-message/ert-test.el | 30 ++++++++++++++++++++++++ test-js/ert/test/ert-test.el | 30 ++++++++++++++++++++++++ test-js/test-ert.test.js | 19 +++++++++++++++ 5 files changed, 103 insertions(+) create mode 100644 test-js/ert/.gitignore create mode 100644 test-js/ert/Eask create mode 100644 test-js/ert/test-nil-message/ert-test.el create mode 100644 test-js/ert/test/ert-test.el create mode 100644 test-js/test-ert.test.js diff --git a/test-js/ert/.gitignore b/test-js/ert/.gitignore new file mode 100644 index 00000000..a50232f7 --- /dev/null +++ b/test-js/ert/.gitignore @@ -0,0 +1,14 @@ +# ignore these directories +/.git +/recipes + +# ignore generated files +*.elc + +# eask packages +.eask/ +dist/ + +# packaging +*-autoloads.el +*-pkg.el diff --git a/test-js/ert/Eask b/test-js/ert/Eask new file mode 100644 index 00000000..0d433c3d --- /dev/null +++ b/test-js/ert/Eask @@ -0,0 +1,10 @@ +(package "ert" + "0.0.1" + "Test project for command `ert'") + +(package-file "ert.el") + +(source 'gnu) +(source 'melpa) + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test-js/ert/test-nil-message/ert-test.el b/test-js/ert/test-nil-message/ert-test.el new file mode 100644 index 00000000..64d20a16 --- /dev/null +++ b/test-js/ert/test-nil-message/ert-test.el @@ -0,0 +1,30 @@ +;;; ert-test.el --- Test the command ert -*- lexical-binding: t; -*- + +;; Copyright (C) 2024-2025 the Eask authors. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Tests for the command ert + +;;; Code: + +(require 'ert) +(require 'debug) + +(ert-deftest ert-test-1 () + (should-not (message nil))) + +;;; ert-test.el ends here diff --git a/test-js/ert/test/ert-test.el b/test-js/ert/test/ert-test.el new file mode 100644 index 00000000..fa5e835a --- /dev/null +++ b/test-js/ert/test/ert-test.el @@ -0,0 +1,30 @@ +;;; ert-test.el --- Test the command ert -*- lexical-binding: t; -*- + +;; Copyright (C) 2024-2025 the Eask authors. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Tests for the command ert + +;;; Code: + +(require 'ert) +(require 'debug) + +(ert-deftest ert-test-1 () + (should (= 1 1))) + +;;; ert-test.el ends here diff --git a/test-js/test-ert.test.js b/test-js/test-ert.test.js new file mode 100644 index 00000000..c811301a --- /dev/null +++ b/test-js/test-ert.test.js @@ -0,0 +1,19 @@ +const { TestContext } = require("./helpers"); + +describe("test-ert", () => { + const ctx = new TestContext("./test-js/ert"); + + afterAll(() => ctx.cleanUp()); + + test("eask test ert ./test/*.el", async () => { + await ctx.runEask("test ert ./test/*.el"); + }); + + test("nil message", async () => { + await ctx.runEask("test ert ./test-nil-message/*.el"); + }); + + test("no files", async () => { + await expect(ctx.runEask("test ert")).rejects.toThrow(); + }); +}); From 453692efc9f13a1ef30342095c7567c380957e97 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Fri, 21 Mar 2025 15:51:10 -0700 Subject: [PATCH 19/70] Add test-ert-runner.test.js --- test-js/ert-runner/.gitignore | 14 ++++++++++ test-js/ert-runner/Eask | 13 +++++++++ test-js/ert-runner/test/ert-runner-test.el | 31 ++++++++++++++++++++++ test-js/test-ert-runner.test.js | 13 +++++++++ 4 files changed, 71 insertions(+) create mode 100644 test-js/ert-runner/.gitignore create mode 100644 test-js/ert-runner/Eask create mode 100644 test-js/ert-runner/test/ert-runner-test.el create mode 100644 test-js/test-ert-runner.test.js diff --git a/test-js/ert-runner/.gitignore b/test-js/ert-runner/.gitignore new file mode 100644 index 00000000..a50232f7 --- /dev/null +++ b/test-js/ert-runner/.gitignore @@ -0,0 +1,14 @@ +# ignore these directories +/.git +/recipes + +# ignore generated files +*.elc + +# eask packages +.eask/ +dist/ + +# packaging +*-autoloads.el +*-pkg.el diff --git a/test-js/ert-runner/Eask b/test-js/ert-runner/Eask new file mode 100644 index 00000000..3050d52e --- /dev/null +++ b/test-js/ert-runner/Eask @@ -0,0 +1,13 @@ +(package "ert-runner" + "0.0.1" + "Test project for command `ert-runner'") + +(package-file "ert-runner.el") + +(source 'gnu) +(source 'melpa) + +(development + (depends-on "ert-runner")) + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test-js/ert-runner/test/ert-runner-test.el b/test-js/ert-runner/test/ert-runner-test.el new file mode 100644 index 00000000..9255e819 --- /dev/null +++ b/test-js/ert-runner/test/ert-runner-test.el @@ -0,0 +1,31 @@ +;;; ert-runner-test.el --- Test the command ert-runner -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2025 the Eask authors. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Tests for the command ert-runner + +;;; Code: + +(require 'ert) +(require 'debug) + +(ert-deftest ert-runner-test-1 () + (should (= 1 1))) + +(provide 'ert-runner-test) +;;; ert-runner-test.el ends here diff --git a/test-js/test-ert-runner.test.js b/test-js/test-ert-runner.test.js new file mode 100644 index 00000000..ed8cfbea --- /dev/null +++ b/test-js/test-ert-runner.test.js @@ -0,0 +1,13 @@ +const { TestContext } = require("./helpers"); + +describe("test ert-runner", () => { + const ctx = new TestContext("./test-js/ert-runner"); + + beforeAll(async () => await ctx.runEask("install-deps --dev"), 10000); + + afterAll(() => ctx.cleanUp()); + + test("eask test ert-runner ./test/*.el", async () => { + await ctx.runEask("test ert-runner ./test/*.el"); + }); +}); From cfda301cd8427acc8af7d8eab16581d9b300b590 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Sun, 23 Mar 2025 14:09:26 -0700 Subject: [PATCH 20/70] Add exit-status tests --- test-js/exit-status.test.js | 146 ++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 test-js/exit-status.test.js diff --git a/test-js/exit-status.test.js b/test-js/exit-status.test.js new file mode 100644 index 00000000..926c83f8 --- /dev/null +++ b/test-js/exit-status.test.js @@ -0,0 +1,146 @@ +const { TestContext } = require("./helpers"); + +describe("exit-status", () => { + const ctx = new TestContext("./test-js/empty"); + + // beforeAll(async () => await ctx.runEask("install-deps"), 10000); + + afterAll(() => ctx.cleanUp()); + + describe("bump", () => { + it("should error with no files", async () => { + await expect(ctx.runEask("bump")).rejects.toThrow(); + }); + }); + + describe("concat", () => { + it("should error with no files", async () => { + await expect(ctx.runEask("concat")).rejects.toThrow(); + }); + }); + + describe("docs", () => { + it("should error with no files", async () => { + await expect(ctx.runEask("docs")).rejects.toThrow(); + }); + }); + + describe("eval", () => { + it("should error with no files", async () => { + await expect(ctx.runEask("eval")).rejects.toThrow(); + }); + }); + + describe("format", () => { + it("elfmt should error with no files", async () => { + await expect(ctx.runEask("format elfmt")).rejects.toThrow(); + }); + + it("elisp-autofmt should error with no files", async () => { + await expect(ctx.runEask("format elisp-autofmt")).rejects.toThrow(); + }); + }); + + describe("info", () => { + it("should error with no files", async () => { + // When run in the current directory this sees the eask file from the main project + await expect(ctx.runEask("info -g")).rejects.toThrow(); + }); + }); + + describe("init", () => { + it("should error with no files", async () => { + await expect(ctx.runEask("concat")).rejects.toThrow(); + }); + }); + describe("concat", () => { + it("--from cask should error with no files", async () => { + await expect(ctx.runEask("init --from cask")).rejects.toThrow(); + }); + + it("--from keg should error with no files", async () => { + await expect(ctx.runEask("init --from keg")).rejects.toThrow(); + }); + + it("--from eldev should error with no files", async () => { + await expect(ctx.runEask("init --from eldev")).rejects.toThrow(); + }); + + it("--from source should error with no files", async () => { + await expect(ctx.runEask("init --from source")).rejects.toThrow(); + }); + }); + + describe("lint", () => { + it("checkdoc should error with no files", async () => { + await expect(ctx.runEask("lint checkdoc")).rejects.toThrow(); + }); + + it("declare should error with no files", async () => { + await expect(ctx.runEask("lint declare")).rejects.toThrow(); + }); + + it("elint should error with no files", async () => { + await expect(ctx.runEask("lint elint")).rejects.toThrow(); + }); + + it("elisp-lint should error with no files", async () => { + await expect(ctx.runEask("lint elisp-lint")).rejects.toThrow(); + }); + + // takes a while to install elsa + it("elsa should error with no files", async () => { + await expect(ctx.runEask("lint elsa")).rejects.toThrow(); + }, 10000); + + it("indent should error with no files", async () => { + await expect(ctx.runEask("lint indent")).rejects.toThrow(); + }); + + it("keywords should error with no files", async () => { + await expect(ctx.runEask("lint keywords")).rejects.toThrow(); + }); + + it("regexps should error with no files", async () => { + await expect(ctx.runEask("lint regexps")).rejects.toThrow(); + }); + }); + + describe("recipe", () => { + it("should error with no files", async () => { + await expect(ctx.runEask("recipe")).rejects.toThrow(); + }); + }); + + describe("run", () => { + it("run command should error with no files", async () => { + await expect(ctx.runEask("run command")).rejects.toThrow(); + }); + + it("run script should error with no files", async () => { + await expect(ctx.runEask("run script -g")).rejects.toThrow(); + }); + }); + + describe("source", () => { + it("should error with no files", async () => { + await expect(ctx.runEask("source")).rejects.toThrow(); + }); + + it("add should error with no files", async () => { + await expect(ctx.runEask("source add")).rejects.toThrow(); + }); + + it("add should error with unknown package", async () => { + await expect(ctx.runEask("source add foo")).rejects.toThrow(); + }); + + it("delete should error with no files", async () => { + await expect(ctx.runEask("source delete")).rejects.toThrow(); + }); + + it("delete should error with unknown package", async () => { + await expect(ctx.runEask("source delete foo")).rejects.toThrow(); + }); + }); +}); From 86c8245441f11c9cde15e909b3cd8a4b34f1bc1f Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Sun, 23 Mar 2025 18:45:26 -0700 Subject: [PATCH 21/70] Add local.test.js --- test-js/local.test.js | 273 ++++++++++++++++++++++++++++ test-js/local/Eask | 37 ++++ test-js/local/RADME.md | 1 + test-js/local/files/mini.pkg.1-1.el | 32 ++++ test-js/local/files/mini.pkg.1-2.el | 31 ++++ test-js/local/mini.pkg.1.el | 39 ++++ 6 files changed, 413 insertions(+) create mode 100644 test-js/local.test.js create mode 100644 test-js/local/Eask create mode 100644 test-js/local/RADME.md create mode 100644 test-js/local/files/mini.pkg.1-1.el create mode 100644 test-js/local/files/mini.pkg.1-2.el create mode 100644 test-js/local/mini.pkg.1.el diff --git a/test-js/local.test.js b/test-js/local.test.js new file mode 100644 index 00000000..76aab5dc --- /dev/null +++ b/test-js/local.test.js @@ -0,0 +1,273 @@ +// Here we test all local (workspace) commands by simulating a Emacs +// pacakge development environment! + +// Notice, below we clone a random package (repo) that uses Eask as the +// dependencies management tool. + +const { emacsVersion, TestContext } = require("./helpers"); + +const fs = require("node:fs/promises"); +const path = require("node:path"); + +jest.setTimeout(15000); + +describe("local", () => { + const cwd = "./test-js/local"; + const ctx = new TestContext(cwd); + + afterAll(() => ctx.cleanUp()); + + describe("info commands", () => { + it("info", async () => { + await ctx.runEask("info"); + }); + it("status", async () => { + await ctx.runEask("status"); + }); + it("archives", async () => { + await ctx.runEask("archives"); + }); + it("archives --all", async () => { + await ctx.runEask("archives --all"); + }); + it("list --depth=0", async () => { + await ctx.runEask("list --depth=0"); + }); + // this alters the eask file + it("bump", async () => { + await ctx.runEask("bump major minor patch"); + }); + it("cat", async () => { + await ctx.runEask("cat package.json --insecure"); + await ctx.runEask("cat package.json --number --insecure"); + }); + it("concat", async () => { + await ctx.runEask("concat"); + }); + it("loc", async () => { + if ((await emacsVersion()) > "27.1") { + await ctx.runEask("loc"); + await ctx.runEask("loc Eask"); + } + }); + }); + + describe("PATH environment", () => { + it("path", async () => { + await ctx.runEask("path"); + await ctx.runEask("path bin"); + }); + it("load-path", async () => { + await ctx.runEask("load-path"); + await ctx.runEask("load-path bin"); + }); + }); + + describe("Preparation", () => { + afterAll(async () => await ctx.runEask("clean all")); + + // install-deps + // TODO this times out + it("prepare --dev", async () => { + await ctx.runEask("prepare --dev"); + }, 20000); + + it("package", async () => { + await ctx.runEask("package"); + }); + }); + + describe("Development", () => { + // TODO takes a long time, organize-imports-java? + // works when installed + beforeAll(async () => await ctx.runEask("install-deps"), 15000); + // this requires install-deps + it("compile", async () => { + await ctx.runEask("compile"); + await ctx.runEask("compile --clean"); + await ctx.runEask("recompile"); + await ctx.runEask("recompile --clean"); + }); + + it("recipe", async () => { + await ctx.runEask("recipe"); + }); + + it("keywords", async () => { + await ctx.runEask("keywords"); + }); + + it("run script", async () => { + await ctx.runEask("run script"); + await ctx.runEask("run script test"); + await ctx.runEask("run script extra -- Extra arguments!"); + await ctx.runEask("run script --all"); + }); + + it("run command", async () => { + await ctx.runEask("run command"); + await ctx.runEask("run command test"); + await ctx.runEask("run command mini-test-3 -- Extra arguments!"); + await ctx.runEask("run command --all"); + }); + }); + + // TODO requires install-deps + describe("Execution", () => { + test("eval", async () => { + await ctx.runEask('eval "(progn (require \'mini.pkg.1))"'); + }); + }); + + describe("Generating", () => { + it("generate autoloads", async () => { + await ctx.runEask("generate autoloads"); + }); + it("generate pkg-file", async () => { + await ctx.runEask("generate pkg-file"); + }); + it("generate recipe -y", async () => { + await ctx.runEask("generate recipe -y"); + }); + // await ctx.runEask("generate license gpl-3.0"); # XXX: Avoid API rate limit exceeded error + it("generate ignore elisp", async () => { + await ctx.runEask("generate ignore elisp"); + }); + }); + + describe("Generating tests", () => { + it("generate test ert", async () => { + await ctx.runEask("generate test ert"); + await fs.rm(path.join(cwd, "/test"), { recursive: true, retries: 1 }); + }); + it("generate test ert-runner", async () => { + await ctx.runEask("generate test ert-runner"); + }); + it("generate test buttercup", async () => { + await ctx.runEask("generate test buttercup"); + }); + it("generate test ecukes", async () => { + await ctx.runEask("generate test ecukes"); + }); + }); + + describe("Generating workflow", () => { + it("generate workflow circle-ci", async () => { + await ctx.runEask("generate workflow circle-ci"); + }); + it("generate workflow github", async () => { + await ctx.runEask("generate workflow github"); + }); + it("generate workflow gitlab", async () => { + await ctx.runEask("generate workflow gitlab"); + }); + it("generate workflow travis-ci", async () => { + await ctx.runEask("generate workflow travis-ci"); + }); + }); + + describe("Linting", () => { + it("lint checkdoc", async () => { + await ctx.runEask("lint checkdoc"); + }); + it("lint declare", async () => { + await ctx.runEask("lint declare"); + }); + it("lint elint", async () => { + await ctx.runEask("lint elint"); + }); + it("lint elisp-lint", async () => { + await ctx.runEask("lint elisp-lint"); + }); + // XXX: Elsa is not stable, ignore it for now + test.skip("lint elsa", async () => { + await ctx.runEask("lint elsa"); + }); + it("lint indent", async () => { + await ctx.runEask("lint indent"); + }); + it("lint keywords", async () => { + await ctx.runEask("lint keywords"); + }); + it("lint license", async () => { + await ctx.runEask("lint license"); + }); + it("lint package", async () => { + await ctx.runEask("lint package"); + }); + it("lint regexps", async () => { + if ((await emacsVersion()) > "27.1") { + await ctx.runEask("lint regexps"); + } + }); + }); + + describe("Testing", () => { + it("test activate", async () => { + await ctx.runEask("test activate"); + }); + }); + + describe("Formatting", () => { + // installs elisp-autofmt + it("format elisp-autofmt", async () => { + if ((await emacsVersion()) > "29.1") { + await ctx.runEask("format elisp-autofmt"); + } + }); + + it("format elfmt", async () => { + await ctx.runEask("format elfmt"); + }); + }); + + describe("Cleaning", () => { + it("clean .eask", async () => { + await ctx.runEask("clean .eask"); + }); + it("clean elc", async () => { + await ctx.runEask("clean elc"); + }); + it("clean dist", async () => { + await ctx.runEask("clean dist"); + }); + it("clean autoloads", async () => { + await ctx.runEask("clean autoloads"); + }); + it("clean pkg-file", async () => { + await ctx.runEask("clean pkg-file"); + }); + it("clean log-file", async () => { + await ctx.runEask("clean log-file"); + }); + it("clean all", async () => { + await ctx.runEask("clean all"); + }); + }); + + describe("Control DSL", () => { + it("source add", async () => { + await ctx.runEask('source add test "https://test.elpa.com"'); + }); + it("source delete test", async () => { + await ctx.runEask("source delete test"); + }); + it("source list", async () => { + await ctx.runEask("source list"); + }); + }); + + describe("Util", () => { + it("locate", async () => { + await ctx.runEask("locate"); + }); + // TODO hmm, this might cause weird effects + test.skip("upgrade-eask", async () => { + await ctx.runEask("upgrade-eask"); + }); + + it("refresh", async () => { + await ctx.runEask("refresh"); + }); + }); +}); diff --git a/test-js/local/Eask b/test-js/local/Eask new file mode 100644 index 00000000..480eef12 --- /dev/null +++ b/test-js/local/Eask @@ -0,0 +1,37 @@ +(package "mini.pkg.1" + "0.0.1" + "Minimal test package") + +(website-url "https://github.com/emacs-eask/cli/tree/master/test/fixtures/mini.pkg.1") +(keywords "test" "local") + +(package-file "mini.pkg.1.el") + +(files "files/*.el") + +(script "test" "echo \"Have a nice day!~ ;)\"") +(script "extra" "echo :") +(script "info" "eask info") + +(eask-defcommand mini-test-1 "Test command 1." (message "Test 1")) +(eask-defcommand mini-test-2 "Test command 2." (message "Test 2")) +(eask-defcommand mini-test-3 + "Test command 3." + (message "Test 3: %s" eask-rest)) + +(source 'gnu) +(source 'melpa) +(source 'jcs-elpa) + +(depends-on "emacs" "26.1") +(depends-on "f") +(depends-on "s") +(depends-on "fringe-helper") +(depends-on "watch-cursor" + :repo "jcs-elpa/watch-cursor" :fetcher 'github) +(depends-on "organize-imports-java" + :repo "jcs-elpa/organize-imports-java" + :fetcher 'github + :files '(:defaults "sdk" "default")) + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test-js/local/RADME.md b/test-js/local/RADME.md new file mode 100644 index 00000000..441cfd06 --- /dev/null +++ b/test-js/local/RADME.md @@ -0,0 +1 @@ +Minimal Emacs package to simulate development environment; only for testing purposes! diff --git a/test-js/local/files/mini.pkg.1-1.el b/test-js/local/files/mini.pkg.1-1.el new file mode 100644 index 00000000..1c7e7c73 --- /dev/null +++ b/test-js/local/files/mini.pkg.1-1.el @@ -0,0 +1,32 @@ +;;; mini.pkg.1-1.el --- Extern file 1 -*- lexical-binding: t; -*- + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; files/mini.pkg.1-1.el +;; + +;;; Code: + + +(defun mini.pkg.1-1 () + "Test function 1." + (interactive) + ) + +(provide 'mini.pkg.1-1) +;;; mini.pkg.1-1.el ends here diff --git a/test-js/local/files/mini.pkg.1-2.el b/test-js/local/files/mini.pkg.1-2.el new file mode 100644 index 00000000..09d7eb8c --- /dev/null +++ b/test-js/local/files/mini.pkg.1-2.el @@ -0,0 +1,31 @@ +;;; mini.pkg.1-2.el --- Extern file 2 -*- lexical-binding: t; -*- + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; files/mini.pkg.1-2.el +;; + +;;; Code: + +(defun mini.pkg.1-2 () + "Test function 2." + (interactive) + ) + +(provide 'mini.pkg.1-2) +;;; mini.pkg.1-2.el ends here diff --git a/test-js/local/mini.pkg.1.el b/test-js/local/mini.pkg.1.el new file mode 100644 index 00000000..1db1a166 --- /dev/null +++ b/test-js/local/mini.pkg.1.el @@ -0,0 +1,39 @@ +;;; mini.pkg.1.el --- Minimal test package -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2025 the Eask authors. +;; Created date 2022-03-29 01:52:58 + +;; Author: Shen, Jen-Chieh +;; URL: https://github.com/emacs-eask/cli/tree/master/test/fixtures/mini.pkg.1 +;; Version: 0.0.1 +;; Package-Requires: ((emacs "24.3") (s "1.12.0") (fringe-helper "1.0.1")) +;; Keywords: test local + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; Minimal Emacs package to simulate development environment; only for testing +;; purposes! +;; + +;;; Code: + +(require 's) +(require 'fringe-helper) + +(provide 'mini.pkg.1) +;;; mini.pkg.1.el ends here From dcaa90325eb7a9d62c342a7eb9e8e20a11c82cda Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Sun, 23 Mar 2025 19:10:29 -0700 Subject: [PATCH 22/70] Add docker.test.js --- test-js/docker.test.js | 11 ++++++++ test-js/docker/Eask | 37 ++++++++++++++++++++++++++ test-js/docker/RADME.md | 1 + test-js/docker/files/mini.pkg.1-1.el | 32 +++++++++++++++++++++++ test-js/docker/files/mini.pkg.1-2.el | 31 ++++++++++++++++++++++ test-js/docker/mini.pkg.1.el | 39 ++++++++++++++++++++++++++++ 6 files changed, 151 insertions(+) create mode 100644 test-js/docker.test.js create mode 100644 test-js/docker/Eask create mode 100644 test-js/docker/RADME.md create mode 100644 test-js/docker/files/mini.pkg.1-1.el create mode 100644 test-js/docker/files/mini.pkg.1-2.el create mode 100644 test-js/docker/mini.pkg.1.el diff --git a/test-js/docker.test.js b/test-js/docker.test.js new file mode 100644 index 00000000..273a19ef --- /dev/null +++ b/test-js/docker.test.js @@ -0,0 +1,11 @@ +const { TestContext } = require("./helpers"); + +describe("docker", () => { + const ctx = new TestContext("./test-js/docker"); + + afterAll(() => ctx.cleanUp()); + + test("eask docker 27.1 info", async () => { + await ctx.runEask("docker 27.1 info"); + }); +}); diff --git a/test-js/docker/Eask b/test-js/docker/Eask new file mode 100644 index 00000000..480eef12 --- /dev/null +++ b/test-js/docker/Eask @@ -0,0 +1,37 @@ +(package "mini.pkg.1" + "0.0.1" + "Minimal test package") + +(website-url "https://github.com/emacs-eask/cli/tree/master/test/fixtures/mini.pkg.1") +(keywords "test" "local") + +(package-file "mini.pkg.1.el") + +(files "files/*.el") + +(script "test" "echo \"Have a nice day!~ ;)\"") +(script "extra" "echo :") +(script "info" "eask info") + +(eask-defcommand mini-test-1 "Test command 1." (message "Test 1")) +(eask-defcommand mini-test-2 "Test command 2." (message "Test 2")) +(eask-defcommand mini-test-3 + "Test command 3." + (message "Test 3: %s" eask-rest)) + +(source 'gnu) +(source 'melpa) +(source 'jcs-elpa) + +(depends-on "emacs" "26.1") +(depends-on "f") +(depends-on "s") +(depends-on "fringe-helper") +(depends-on "watch-cursor" + :repo "jcs-elpa/watch-cursor" :fetcher 'github) +(depends-on "organize-imports-java" + :repo "jcs-elpa/organize-imports-java" + :fetcher 'github + :files '(:defaults "sdk" "default")) + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test-js/docker/RADME.md b/test-js/docker/RADME.md new file mode 100644 index 00000000..441cfd06 --- /dev/null +++ b/test-js/docker/RADME.md @@ -0,0 +1 @@ +Minimal Emacs package to simulate development environment; only for testing purposes! diff --git a/test-js/docker/files/mini.pkg.1-1.el b/test-js/docker/files/mini.pkg.1-1.el new file mode 100644 index 00000000..1c7e7c73 --- /dev/null +++ b/test-js/docker/files/mini.pkg.1-1.el @@ -0,0 +1,32 @@ +;;; mini.pkg.1-1.el --- Extern file 1 -*- lexical-binding: t; -*- + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; files/mini.pkg.1-1.el +;; + +;;; Code: + + +(defun mini.pkg.1-1 () + "Test function 1." + (interactive) + ) + +(provide 'mini.pkg.1-1) +;;; mini.pkg.1-1.el ends here diff --git a/test-js/docker/files/mini.pkg.1-2.el b/test-js/docker/files/mini.pkg.1-2.el new file mode 100644 index 00000000..09d7eb8c --- /dev/null +++ b/test-js/docker/files/mini.pkg.1-2.el @@ -0,0 +1,31 @@ +;;; mini.pkg.1-2.el --- Extern file 2 -*- lexical-binding: t; -*- + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; files/mini.pkg.1-2.el +;; + +;;; Code: + +(defun mini.pkg.1-2 () + "Test function 2." + (interactive) + ) + +(provide 'mini.pkg.1-2) +;;; mini.pkg.1-2.el ends here diff --git a/test-js/docker/mini.pkg.1.el b/test-js/docker/mini.pkg.1.el new file mode 100644 index 00000000..1db1a166 --- /dev/null +++ b/test-js/docker/mini.pkg.1.el @@ -0,0 +1,39 @@ +;;; mini.pkg.1.el --- Minimal test package -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2025 the Eask authors. +;; Created date 2022-03-29 01:52:58 + +;; Author: Shen, Jen-Chieh +;; URL: https://github.com/emacs-eask/cli/tree/master/test/fixtures/mini.pkg.1 +;; Version: 0.0.1 +;; Package-Requires: ((emacs "24.3") (s "1.12.0") (fringe-helper "1.0.1")) +;; Keywords: test local + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; Minimal Emacs package to simulate development environment; only for testing +;; purposes! +;; + +;;; Code: + +(require 's) +(require 'fringe-helper) + +(provide 'mini.pkg.1) +;;; mini.pkg.1.el ends here From f45327612897317f12f89b9f74280607280faa61 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Sun, 23 Mar 2025 19:18:31 -0700 Subject: [PATCH 23/70] Add install.test.js --- test-js/install.test.js | 54 +++++++++++++++++++++++++++ test-js/install/Eask | 37 ++++++++++++++++++ test-js/install/RADME.md | 1 + test-js/install/files/mini.pkg.1-1.el | 32 ++++++++++++++++ test-js/install/files/mini.pkg.1-2.el | 31 +++++++++++++++ test-js/install/mini.pkg.1.el | 39 +++++++++++++++++++ 6 files changed, 194 insertions(+) create mode 100644 test-js/install.test.js create mode 100644 test-js/install/Eask create mode 100644 test-js/install/RADME.md create mode 100644 test-js/install/files/mini.pkg.1-1.el create mode 100644 test-js/install/files/mini.pkg.1-2.el create mode 100644 test-js/install/mini.pkg.1.el diff --git a/test-js/install.test.js b/test-js/install.test.js new file mode 100644 index 00000000..2314ce13 --- /dev/null +++ b/test-js/install.test.js @@ -0,0 +1,54 @@ +const { TestContext } = require("./helpers"); + +jest.setTimeout(15000); + +describe("install and uninstall", () => { + describe("in mini.pkg.1", () => { + const ctx = new TestContext("./test-js/install/"); + afterAll(() => ctx.cleanUp()); + // beforeAll(async () => await exec("eask clean all", { cwd })); + + // TODO also teardown? + + // TODO this can take a really really long time! + it("installs dependencies", async () => { + await ctx.runEask("install-deps"); + }, 20000); + + it("installs project package", async () => { + await ctx.runEask("package"); + await ctx.runEask("install"); + }); + + it("installs specific packages", async () => { + await ctx.runEask("install beacon company-fuzzy transwin"); + }); + + // TODO stateful + it("uninstalls specific packages", async () => { + await ctx.runEask("uninstall beacon transwin"); + }); + + it("uninstalls project package", async () => { + await ctx.runEask("uninstall"); + }); + }); + + describe("in an empty project", () => { + const ctx = new TestContext("./test-js/empty"); + beforeAll(async () => await ctx.runEask("clean all")); + afterAll(() => ctx.cleanUp()); + + it("errors on install", async () => { + await expect(ctx.runEask("install")).rejects.toThrow(); + }); + + it("errors on uninstall", async () => { + await expect(ctx.runEask("uninstall")).rejects.toThrow(); + }); + + it("errors on reinstall", async () => { + await expect(ctx.runEask("reinstall")).rejects.toThrow(); + }); + }); +}); diff --git a/test-js/install/Eask b/test-js/install/Eask new file mode 100644 index 00000000..480eef12 --- /dev/null +++ b/test-js/install/Eask @@ -0,0 +1,37 @@ +(package "mini.pkg.1" + "0.0.1" + "Minimal test package") + +(website-url "https://github.com/emacs-eask/cli/tree/master/test/fixtures/mini.pkg.1") +(keywords "test" "local") + +(package-file "mini.pkg.1.el") + +(files "files/*.el") + +(script "test" "echo \"Have a nice day!~ ;)\"") +(script "extra" "echo :") +(script "info" "eask info") + +(eask-defcommand mini-test-1 "Test command 1." (message "Test 1")) +(eask-defcommand mini-test-2 "Test command 2." (message "Test 2")) +(eask-defcommand mini-test-3 + "Test command 3." + (message "Test 3: %s" eask-rest)) + +(source 'gnu) +(source 'melpa) +(source 'jcs-elpa) + +(depends-on "emacs" "26.1") +(depends-on "f") +(depends-on "s") +(depends-on "fringe-helper") +(depends-on "watch-cursor" + :repo "jcs-elpa/watch-cursor" :fetcher 'github) +(depends-on "organize-imports-java" + :repo "jcs-elpa/organize-imports-java" + :fetcher 'github + :files '(:defaults "sdk" "default")) + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test-js/install/RADME.md b/test-js/install/RADME.md new file mode 100644 index 00000000..441cfd06 --- /dev/null +++ b/test-js/install/RADME.md @@ -0,0 +1 @@ +Minimal Emacs package to simulate development environment; only for testing purposes! diff --git a/test-js/install/files/mini.pkg.1-1.el b/test-js/install/files/mini.pkg.1-1.el new file mode 100644 index 00000000..1c7e7c73 --- /dev/null +++ b/test-js/install/files/mini.pkg.1-1.el @@ -0,0 +1,32 @@ +;;; mini.pkg.1-1.el --- Extern file 1 -*- lexical-binding: t; -*- + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; files/mini.pkg.1-1.el +;; + +;;; Code: + + +(defun mini.pkg.1-1 () + "Test function 1." + (interactive) + ) + +(provide 'mini.pkg.1-1) +;;; mini.pkg.1-1.el ends here diff --git a/test-js/install/files/mini.pkg.1-2.el b/test-js/install/files/mini.pkg.1-2.el new file mode 100644 index 00000000..09d7eb8c --- /dev/null +++ b/test-js/install/files/mini.pkg.1-2.el @@ -0,0 +1,31 @@ +;;; mini.pkg.1-2.el --- Extern file 2 -*- lexical-binding: t; -*- + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; files/mini.pkg.1-2.el +;; + +;;; Code: + +(defun mini.pkg.1-2 () + "Test function 2." + (interactive) + ) + +(provide 'mini.pkg.1-2) +;;; mini.pkg.1-2.el ends here diff --git a/test-js/install/mini.pkg.1.el b/test-js/install/mini.pkg.1.el new file mode 100644 index 00000000..1db1a166 --- /dev/null +++ b/test-js/install/mini.pkg.1.el @@ -0,0 +1,39 @@ +;;; mini.pkg.1.el --- Minimal test package -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2025 the Eask authors. +;; Created date 2022-03-29 01:52:58 + +;; Author: Shen, Jen-Chieh +;; URL: https://github.com/emacs-eask/cli/tree/master/test/fixtures/mini.pkg.1 +;; Version: 0.0.1 +;; Package-Requires: ((emacs "24.3") (s "1.12.0") (fringe-helper "1.0.1")) +;; Keywords: test local + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; Minimal Emacs package to simulate development environment; only for testing +;; purposes! +;; + +;;; Code: + +(require 's) +(require 'fringe-helper) + +(provide 'mini.pkg.1) +;;; mini.pkg.1.el ends here From ee96a399faf8a1b03fb9388b9cb058c931727c15 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Sun, 23 Mar 2025 19:20:45 -0700 Subject: [PATCH 24/70] Add global.test.js --- test-js/global.test.js | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 test-js/global.test.js diff --git a/test-js/global.test.js b/test-js/global.test.js new file mode 100644 index 00000000..c77d4a41 --- /dev/null +++ b/test-js/global.test.js @@ -0,0 +1,37 @@ +const { testUnsafe, TestContext } = require("./helpers"); + +describe("global", () => { + // global => install to ~/.eask + // TODO may need to copy a global eask file? + // or perhaps need --insecure option? + // cp -R ./test/fixtures/home/Eask ~/Eask + + const ctx = new TestContext(); + + describe("informational", () => { + test("eask archives -g", async () => { + await ctx.runEask("archives -g"); + }); + + test("eask list -g --depth=0", async () => { + await ctx.runEask("list -g --depth=0"); + }); + + test("eask outdated -g", async () => { + await ctx.runEask("outdated -g"); + }); + }); + + describe("install", () => { + /* + * This test modifies ~/.eask + */ + testUnsafe("eask install -g", async () => { + await ctx.runEask("install -g spinner ivy beacon company fuzzy"); + }); + + testUnsafe("eask uninstall -g", async () => { + await ctx.runEask("uninstall -g ivy fuzzy"); + }); + }); +}); From ca22326dcd026acc872fa853237953abf1de3ea3 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Mon, 24 Mar 2025 16:03:41 -0700 Subject: [PATCH 25/70] Tidy up log formatting --- test-js/helpers.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test-js/helpers.js b/test-js/helpers.js index 44aba73a..92cbd1cb 100644 --- a/test-js/helpers.js +++ b/test-js/helpers.js @@ -50,9 +50,11 @@ class TestContext { ...config, }).then((obj) => { if (process.env.DEBUG) { - console.log(command); - console.log(obj.stdout); - console.log(obj.stderr); + console.log( + `--> ${command}\n` + + (obj.stdout ? obj.stdout : "") + + (obj.stderr ? obj.stderr : ""), + ); } return obj; }); From ec5b154d3fe5ddaca2a8303f6290ef85942a14dd Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Mon, 24 Mar 2025 16:29:01 -0700 Subject: [PATCH 26/70] config.test.js should create ~/.emacs.d/init.el --- test-js/config.test.js | 61 +++++++++++++++++++++++++++++------------- test-js/config/init.el | 27 +++++++++++++++++++ 2 files changed, 69 insertions(+), 19 deletions(-) create mode 100644 test-js/config/init.el diff --git a/test-js/config.test.js b/test-js/config.test.js index 82888a7c..65aa5d54 100644 --- a/test-js/config.test.js +++ b/test-js/config.test.js @@ -1,33 +1,56 @@ const { testUnsafe, TestContext } = require("./helpers"); +const fs = require("node:fs/promises"); +const path = require("node:path"); +const process = require("node:process"); describe("config param", () => { const ctx = new TestContext(); afterAll(() => ctx.cleanUp()); - // TODO timeout - test("eask archives -c", async () => { - await ctx.runEask("archives -c"); - }); + describe("informational", () => { + /* + * Note that these tests will run against your ~/.emacs.d if run locally. + * If you have a complicated set up, they may timeout. + */ - // TODO perhaps teardown the following two? - // TODO check in docker - testUnsafe("eask install -c", async () => { - await ctx.runEask("install -c spinner ivy beacon company-fuzzy"); - }); + test("eask archives -c", async () => { + await ctx.runEask("archives -c"); + }); - // TODO should test uninstalling multiple - testUnsafe("eask uninstall -c", async () => { - await ctx.runEask("uninstall -c ivy company-fuzzy"); - }); + test("eask list -c", async () => { + await ctx.runEask("list -c --depth=0"); + }); - // TODO timeout - test("eask list -c", async () => { - await ctx.runEask("list -c --depth=0"); + test("eask outdated -c", async () => { + await ctx.runEask("outdated -c"); + }); }); - // TODO timeout - test("eask outdated -c", async () => { - await ctx.runEask("outdated -c"); + describe("install", () => { + /* + * This test modifies ~/.emacs.d/init.el and installs packages there when run with ALLOW_UNSAFE + */ + testUnsafe( + "eask install -c", + async () => { + // create ~/.emacs.d + await fs.mkdir(path.join(process.env.HOME, "/.emacs.d/"), { + recursive: true, + }); + // copy init.el from fixtures + // it must enable sources for the installed packages + await fs.copyFile( + "./test-js/config/init.el", + path.join(process.env.HOME, "/.emacs.d/init.el"), + ); + await ctx.runEask("install -c spinner ivy beacon company-fuzzy"); + }, + 15000, + ); + + testUnsafe("eask uninstall -c", async () => { + await ctx.runEask("uninstall -c ivy company-fuzzy"); + }); }); }); diff --git a/test-js/config/init.el b/test-js/config/init.el new file mode 100644 index 00000000..08777729 --- /dev/null +++ b/test-js/config/init.el @@ -0,0 +1,27 @@ +;;; init.el --- Load the full configuration -*- lexical-binding: t -*- +;;; Commentary: + +;; Author: Shen, Jen-Chieh +;; URL: https://github.com/emacs-eask/cli + +(setq package-archives + '(("gnu" . "http://elpa.gnu.org/packages/") + ("nongnu" . "http://elpa.nongnu.org/nongnu/") + ("melpa" . "http://melpa.org/packages/") + ("jcs-elpa" . "https://jcs-emacs.github.io/jcs-elpa/packages/")) + package-archive-priorities + '(("gnu" . 0) + ("nongnu" . 0) + ("melpa" . 5) + ("jcs-elpa" . 10))) + +(setq package-enable-at-startup nil ; To avoid initializing twice + package-check-signature nil) + +(require 'package) + +;; Local Variables: +;; coding: utf-8 +;; no-byte-compile: t +;; End: +;;; init.el ends here From d9bcc44dc0cc23c03f69e9bcefe2193a63690f71 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Mon, 24 Mar 2025 16:37:29 -0700 Subject: [PATCH 27/70] global.test.js should create ~/Eask --- test-js/global.test.js | 25 ++++++++++++++++++------- test-js/global/Eask | 14 ++++++++++++++ 2 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 test-js/global/Eask diff --git a/test-js/global.test.js b/test-js/global.test.js index c77d4a41..2bbf4bca 100644 --- a/test-js/global.test.js +++ b/test-js/global.test.js @@ -1,10 +1,11 @@ +const fs = require("node:fs/promises"); +const path = require("node:path"); +const process = require("node:process"); + const { testUnsafe, TestContext } = require("./helpers"); describe("global", () => { // global => install to ~/.eask - // TODO may need to copy a global eask file? - // or perhaps need --insecure option? - // cp -R ./test/fixtures/home/Eask ~/Eask const ctx = new TestContext(); @@ -26,12 +27,22 @@ describe("global", () => { /* * This test modifies ~/.eask */ - testUnsafe("eask install -g", async () => { - await ctx.runEask("install -g spinner ivy beacon company fuzzy"); - }); + testUnsafe( + "eask install -g", + async () => { + // add a global Easkfile + await fs.copyFile( + "./test-js/global/Eask", + path.join(process.env.HOME, "Eask"), + ); + + await ctx.runEask("install -g spinner ivy beacon company-fuzzy"); + }, + 15000, + ); testUnsafe("eask uninstall -g", async () => { - await ctx.runEask("uninstall -g ivy fuzzy"); + await ctx.runEask("uninstall -g ivy company-fuzzy"); }); }); }); diff --git a/test-js/global/Eask b/test-js/global/Eask new file mode 100644 index 00000000..f0b6d57e --- /dev/null +++ b/test-js/global/Eask @@ -0,0 +1,14 @@ +(package "home" + "0.0.1" + "Minimal test for global config") + +(website-url "https://github.com/emacs-eask/mini.eask") +(keywords "test") + +(source 'gnu) +(source 'melpa) + +(depends-on "emacs" "26.1") +(depends-on "yaml-mode") + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 From 2646e7706c1d0938aa085bfeafc9eb3288e92490 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Mon, 24 Mar 2025 17:27:11 -0700 Subject: [PATCH 28/70] Update analyze.test.js with TestContext --- test-js/analyze.test.js | 45 +++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/test-js/analyze.test.js b/test-js/analyze.test.js index 14d85e44..ebb91b55 100644 --- a/test-js/analyze.test.js +++ b/test-js/analyze.test.js @@ -1,53 +1,40 @@ -const util = require("node:util"); -const exec = util.promisify(require("node:child_process").exec); +const { TestContext } = require("./helpers"); describe("analyze", () => { describe("dsl", () => { const cwd = "./test-js/dsl"; - it("handles plain text", async () => { - const res = await exec("eask analyze", { cwd }); - expect(res).toBeTruthy(); + const ctx = new TestContext(cwd); - const res1 = await exec("eask analyze Eask", { cwd }); - expect(res1).toBeTruthy(); + it("handles plain text", async () => { + await ctx.runEask("analyze"); + await ctx.runEask("analyze Eask"); }); it("handles json", async () => { - const res = await exec("eask analyze --json", { cwd }); - expect(res).toBeTruthy(); - - const res1 = await exec("eask analyze Eask --json", { - cwd, - }); - expect(res1).toBeTruthy(); + await ctx.runEask("analyze --json"); + await ctx.runEask("analyze Eask --json"); }); }); describe("error", () => { - const cwd = "./test-js/empty"; + const ctx = new TestContext("./test-js/empty"); + it("errors in an empty dir", async () => { - await expect(exec("eask scrog", { cwd })).rejects.toThrow(); + await expect(ctx.runEask("analyze")).rejects.toThrow(); }); }); describe("metadata", () => { - const cwd = "./test-js/metadata"; - it("handles plain text", async () => { - const res = await exec("eask analyze", { cwd }); - expect(res).toBeTruthy(); + const ctx = new TestContext("./test-js/metadata"); - const res1 = await exec("eask analyze Eask", { cwd }); - expect(res1).toBeTruthy(); + it("handles plain text", async () => { + await ctx.runEask("analyze"); + await ctx.runEask("analyze Eask"); }); it("handles json", async () => { - const res = await exec("eask analyze --json", { cwd }); - expect(res).toBeTruthy(); - - const res1 = await exec("eask analyze Eask --json", { - cwd, - }); - expect(res1).toBeTruthy(); + await ctx.runEask("analyze --json"); + await ctx.runEask("analyze Eask --json"); }); }); }); From c8621acfc30411a0f716b766e4a3516b0cb8bd1f Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Mon, 24 Mar 2025 18:23:43 -0700 Subject: [PATCH 29/70] Add default timeout and message when cmd is killed --- package.json | 3 ++- test-js/helpers.js | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index c96e7c22..9c4f296a 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "jest": "^29.7.0" }, "jest": { - "rootDir": "./test-js" + "rootDir": "./test-js", + "testTimeout": 40000 }, "files": [ "cmds", diff --git a/test-js/helpers.js b/test-js/helpers.js index 92cbd1cb..a8a440fc 100644 --- a/test-js/helpers.js +++ b/test-js/helpers.js @@ -15,6 +15,17 @@ function testUnsafe(name, fn, timeout) { } } +/** + * Global timeout in ms, set by TIMEOUT env var. + * This is used in TestContext to limit `exec`. + * @returns {number} + */ +function getTimeout() { + // parseInt returns NaN if it fails + // TIMEOUT <= 0 will be ignored too + return Number.parseInt(process.env.TIMEOUT) || 25000; +} + /** * The version string for system emacs, e.g. "30.0.50". * You can compare lexicographically, e.g. if ((await emacsVersion()) > "27") { ... } @@ -47,17 +58,23 @@ class TestContext { return exec(command, { cwd: this.cwd, signal: this.controller.signal, + timeout: getTimeout(), ...config, - }).then((obj) => { - if (process.env.DEBUG) { - console.log( - `--> ${command}\n` + - (obj.stdout ? obj.stdout : "") + - (obj.stderr ? obj.stderr : ""), - ); - } - return obj; - }); + }) + .then((obj) => { + if (process.env.DEBUG) { + console.log( + `--> ${command}\n` + + (obj.stdout ? obj.stdout : "") + + (obj.stderr ? obj.stderr : ""), + ); + } + return obj; + }) + .catch((err) => { + if (!err.code) err.message += "\nexec: TIMEOUT"; + throw err; + }); } cleanUp() { @@ -65,4 +82,4 @@ class TestContext { } } -module.exports = { testUnsafe, emacsVersion, TestContext }; +module.exports = { testUnsafe, emacsVersion, TestContext, getTimeout }; From 8b1cf4bc3cc92a7ce0465e1c0c7651a57f94d744 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Mon, 24 Mar 2025 18:30:00 -0700 Subject: [PATCH 30/70] Remove local timeouts in test files --- test-js/buttercup.test.js | 2 -- test-js/config.test.js | 30 +++++++++++++----------------- test-js/exec.test.js | 2 +- test-js/exit-status.test.js | 2 +- test-js/global.test.js | 22 +++++++++------------- test-js/install.test.js | 11 ++++++----- test-js/link.test.js | 3 +-- test-js/local.test.js | 6 ++---- test-js/outdated.test.js | 2 +- test-js/test-ecukes.test.js | 2 +- test-js/test-ert-runner.test.js | 2 +- 11 files changed, 36 insertions(+), 48 deletions(-) diff --git a/test-js/buttercup.test.js b/test-js/buttercup.test.js index a6f47c05..45b56df1 100644 --- a/test-js/buttercup.test.js +++ b/test-js/buttercup.test.js @@ -1,7 +1,5 @@ const { TestContext } = require("./helpers"); -jest.setTimeout(10000); - describe("buttercup", () => { const ctx = new TestContext("./test-js/buttercup"); diff --git a/test-js/config.test.js b/test-js/config.test.js index 65aa5d54..9b784171 100644 --- a/test-js/config.test.js +++ b/test-js/config.test.js @@ -31,23 +31,19 @@ describe("config param", () => { /* * This test modifies ~/.emacs.d/init.el and installs packages there when run with ALLOW_UNSAFE */ - testUnsafe( - "eask install -c", - async () => { - // create ~/.emacs.d - await fs.mkdir(path.join(process.env.HOME, "/.emacs.d/"), { - recursive: true, - }); - // copy init.el from fixtures - // it must enable sources for the installed packages - await fs.copyFile( - "./test-js/config/init.el", - path.join(process.env.HOME, "/.emacs.d/init.el"), - ); - await ctx.runEask("install -c spinner ivy beacon company-fuzzy"); - }, - 15000, - ); + testUnsafe("eask install -c", async () => { + // create ~/.emacs.d + await fs.mkdir(path.join(process.env.HOME, "/.emacs.d/"), { + recursive: true, + }); + // copy init.el from fixtures + // it must enable sources for the installed packages + await fs.copyFile( + "./test-js/config/init.el", + path.join(process.env.HOME, "/.emacs.d/init.el"), + ); + await ctx.runEask("install -c spinner ivy beacon company-fuzzy"); + }); testUnsafe("eask uninstall -c", async () => { await ctx.runEask("uninstall -c ivy company-fuzzy"); diff --git a/test-js/exec.test.js b/test-js/exec.test.js index 0dc4ff4b..f3cba899 100644 --- a/test-js/exec.test.js +++ b/test-js/exec.test.js @@ -3,7 +3,7 @@ const { TestContext } = require("./helpers"); describe("exec", () => { const ctx = new TestContext("./test-js/exec"); - beforeAll(async () => await ctx.runEask("install-deps"), 10000); + beforeAll(async () => await ctx.runEask("install-deps")); afterAll(() => ctx.cleanUp()); diff --git a/test-js/exit-status.test.js b/test-js/exit-status.test.js index 926c83f8..c55ce699 100644 --- a/test-js/exit-status.test.js +++ b/test-js/exit-status.test.js @@ -91,7 +91,7 @@ describe("exit-status", () => { // takes a while to install elsa it("elsa should error with no files", async () => { await expect(ctx.runEask("lint elsa")).rejects.toThrow(); - }, 10000); + }); it("indent should error with no files", async () => { await expect(ctx.runEask("lint indent")).rejects.toThrow(); diff --git a/test-js/global.test.js b/test-js/global.test.js index 2bbf4bca..c44f1111 100644 --- a/test-js/global.test.js +++ b/test-js/global.test.js @@ -27,19 +27,15 @@ describe("global", () => { /* * This test modifies ~/.eask */ - testUnsafe( - "eask install -g", - async () => { - // add a global Easkfile - await fs.copyFile( - "./test-js/global/Eask", - path.join(process.env.HOME, "Eask"), - ); - - await ctx.runEask("install -g spinner ivy beacon company-fuzzy"); - }, - 15000, - ); + testUnsafe("eask install -g", async () => { + // add a global Easkfile + await fs.copyFile( + "./test-js/global/Eask", + path.join(process.env.HOME, "Eask"), + ); + + await ctx.runEask("install -g spinner ivy beacon company-fuzzy"); + }); testUnsafe("eask uninstall -g", async () => { await ctx.runEask("uninstall -g ivy company-fuzzy"); diff --git a/test-js/install.test.js b/test-js/install.test.js index 2314ce13..3d9e5cd7 100644 --- a/test-js/install.test.js +++ b/test-js/install.test.js @@ -1,19 +1,20 @@ const { TestContext } = require("./helpers"); -jest.setTimeout(15000); - describe("install and uninstall", () => { describe("in mini.pkg.1", () => { const ctx = new TestContext("./test-js/install/"); - afterAll(() => ctx.cleanUp()); + // beforeAll(async () => await exec("eask clean all", { cwd })); // TODO also teardown? + afterAll(async () => await ctx.runEask("clean all")); + afterAll(() => ctx.cleanUp()); // TODO this can take a really really long time! - it("installs dependencies", async () => { + // TODO all later commands depend on this? + test("installs dependencies", async () => { await ctx.runEask("install-deps"); - }, 20000); + }); it("installs project package", async () => { await ctx.runEask("package"); diff --git a/test-js/link.test.js b/test-js/link.test.js index a645bef8..dae606a8 100644 --- a/test-js/link.test.js +++ b/test-js/link.test.js @@ -2,8 +2,7 @@ const { TestContext } = require("./helpers"); describe("link", () => { describe("normally", () => { - const cwd = "./test-js/link"; - const ctx = new TestContext(cwd); + const ctx = new TestContext("./test-js/link"); it("adds a link", async () => { await ctx.runEask('link add "mini.pkg.1" "./test/mini.pkg.1/"'); }); diff --git a/test-js/local.test.js b/test-js/local.test.js index 76aab5dc..60b839f2 100644 --- a/test-js/local.test.js +++ b/test-js/local.test.js @@ -9,8 +9,6 @@ const { emacsVersion, TestContext } = require("./helpers"); const fs = require("node:fs/promises"); const path = require("node:path"); -jest.setTimeout(15000); - describe("local", () => { const cwd = "./test-js/local"; const ctx = new TestContext(cwd); @@ -70,7 +68,7 @@ describe("local", () => { // TODO this times out it("prepare --dev", async () => { await ctx.runEask("prepare --dev"); - }, 20000); + }); it("package", async () => { await ctx.runEask("package"); @@ -80,7 +78,7 @@ describe("local", () => { describe("Development", () => { // TODO takes a long time, organize-imports-java? // works when installed - beforeAll(async () => await ctx.runEask("install-deps"), 15000); + beforeAll(async () => await ctx.runEask("install-deps")); // this requires install-deps it("compile", async () => { await ctx.runEask("compile"); diff --git a/test-js/outdated.test.js b/test-js/outdated.test.js index aae52ab5..97565e9c 100644 --- a/test-js/outdated.test.js +++ b/test-js/outdated.test.js @@ -6,7 +6,7 @@ describe("outdated and upgrade", () => { beforeAll(async () => { await ctx.runEask("install-deps"); await ctx.runEask("load make-outdate.el"); - }, 15000); + }); // these will run in sequence afterAll(async () => await ctx.runEask("clean all")); diff --git a/test-js/test-ecukes.test.js b/test-js/test-ecukes.test.js index 7d38aac1..952fdcc0 100644 --- a/test-js/test-ecukes.test.js +++ b/test-js/test-ecukes.test.js @@ -3,7 +3,7 @@ const { TestContext } = require("./helpers"); describe("test_ecukes", () => { const ctx = new TestContext("./test-js/ecukes"); - beforeAll(async () => await ctx.runEask("install-deps --dev"), 10000); + beforeAll(async () => await ctx.runEask("install-deps --dev")); afterAll(() => ctx.cleanUp()); test("eask test ecukes", async () => { diff --git a/test-js/test-ert-runner.test.js b/test-js/test-ert-runner.test.js index ed8cfbea..0b4ded07 100644 --- a/test-js/test-ert-runner.test.js +++ b/test-js/test-ert-runner.test.js @@ -3,7 +3,7 @@ const { TestContext } = require("./helpers"); describe("test ert-runner", () => { const ctx = new TestContext("./test-js/ert-runner"); - beforeAll(async () => await ctx.runEask("install-deps --dev"), 10000); + beforeAll(async () => await ctx.runEask("install-deps --dev")); afterAll(() => ctx.cleanUp()); From 19fec0b2add3a022bf10038e5e3f7853e4d9780b Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Mon, 24 Mar 2025 20:39:57 -0700 Subject: [PATCH 31/70] Add some doco to helpers.js --- test-js/helpers.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/test-js/helpers.js b/test-js/helpers.js index a8a440fc..292edd64 100644 --- a/test-js/helpers.js +++ b/test-js/helpers.js @@ -1,11 +1,18 @@ const util = require("node:util"); const exec = util.promisify(require("node:child_process").exec); +/* + * This file uses JsDoc syntax. + * Documentation for type helpers like @param: https://jsdoc.app/tags-type + * Documentation for types in braces: + * https://github.com/google/closure-compiler/wiki/Types-in-the-Closure-Type-System + */ + /** * As for jest.test but skips running if the ALLOW_UNSAFE env var is set. * @param {string} name - * @param {any} fn - * @param {number} timeout + * @param {function({ fail: function }): void | function(): PromiseLike.} fn + * @param {number} [timeout] */ function testUnsafe(name, fn, timeout) { if (process.env.ALLOW_UNSAFE) { @@ -50,6 +57,14 @@ class TestContext { this.controller = new AbortController(); } + /** + * Runs command with "eask" prefix. + * See https://nodejs.org/docs/latest-v20.x/api/child_process.html#child_processexeccommand-options-callback + * for additional config options. + * @param {string} command + * @param {any} config + * @returns {Promise.<{ stdout, stderr }>} + */ runEask(command, config) { return this.run(this.easkCommand + " " + command, config); } From c751ce3d3728d2102f031d0289bb8f08ca506a87 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Mon, 24 Mar 2025 21:54:00 -0700 Subject: [PATCH 32/70] fix: add some comments --- test-js/emacs.test.js | 3 +-- test-js/exec.test.js | 1 + test-js/local.test.js | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test-js/emacs.test.js b/test-js/emacs.test.js index 63f328bc..cdb73726 100644 --- a/test-js/emacs.test.js +++ b/test-js/emacs.test.js @@ -1,8 +1,7 @@ const { TestContext } = require("./helpers"); describe("emacs", () => { - const cwd = "./test-js/empty"; - const ctx = new TestContext(cwd); + const ctx = new TestContext("./test-js/empty"); beforeAll(async () => await ctx.runEask("clean all")); diff --git a/test-js/exec.test.js b/test-js/exec.test.js index f3cba899..972eae5f 100644 --- a/test-js/exec.test.js +++ b/test-js/exec.test.js @@ -24,6 +24,7 @@ describe("exec", () => { }); test("eask exec buttercup -L . --pattern 'pattern 1'", async () => { + // TODO this causes a bug on windows docker image await ctx.runEask("exec buttercup -L . --pattern 'pattern 1'"); }); diff --git a/test-js/local.test.js b/test-js/local.test.js index 60b839f2..ac42d7bc 100644 --- a/test-js/local.test.js +++ b/test-js/local.test.js @@ -165,6 +165,7 @@ describe("local", () => { }); describe("Linting", () => { + // TODO some lint commands may fail if packages are missing it("lint checkdoc", async () => { await ctx.runEask("lint checkdoc"); }); From d87f629d85e7231a4832f6f9ebc1b212dfb7f585 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Mon, 24 Mar 2025 21:54:10 -0700 Subject: [PATCH 33/70] Sketch of doco page --- .../content/Contributing/Testing/_index.en.md | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 docs/content/Contributing/Testing/_index.en.md diff --git a/docs/content/Contributing/Testing/_index.en.md b/docs/content/Contributing/Testing/_index.en.md new file mode 100644 index 00000000..d8d3c624 --- /dev/null +++ b/docs/content/Contributing/Testing/_index.en.md @@ -0,0 +1,152 @@ +--- +title: Testing +weight: 20 +--- + +{{< toc >}} + +Local testing for Eask is done using the [Jest]() testing framework. + +A custom `TestContext` class is used to manage the execution environment for each test suite. + +### Running Tests + +If you have not done so already, run `npm install --dev` + +Always run from the project root (i.e. same directory as `package.json`) + +- run all tests `npm run test` +- run a single test `npm run test path/to/test.js` +- run tests with full output `npm run test-debug` +- remove files created during test `npm run test-reset` + +### Environment Vars + +| Name | Type | Default | Meaning | +|:---------------|:-------|---------|:-------------------------------------------------------------------------------------------| +| `ALLOW_UNSAFE` | bool | 0 | Run tests in `testUnsafe` blocks. These can affect your emacs config or settings. | +| `DEBUG` | bool | 0 | Print full output from commands in test. | +| `EASK_COMMAND` | path | "eask" | Path to Eask. Usually either `eask` or `./bin/eask` (include local changes). | +| `TIMEOUT` | number | 25000 | Command timeout in ms. Note this is different than Jest's timeout, which should be larger. | + +### How to Write a Test + +**Folder structure** + +Tests should be in `test/js` +Related tests should be in the same file with the suffix `.test.js`. + +If the test needs some specific project files, put them in a new folder within `test/js` +For example, files in `test/js/foo` would be expected to be for `foo.test.js`. + +The exception is `test/js/empty`, which is simply an empty folder. +If you use it, make sure to run `eask clean all` before your tests. + +**Test File structure** + +``` javascript +const { TestContext } = require("./helpers"); + +describe("emacs", () => { + const ctx = new TestContext("./test-js/empty"); + + beforeAll(async () => await ctx.runEask("clean all")); + afterAll(() => ctx.cleanUp); + + test("eask emacs --version", async () => { + await ctx.runEask("emacs --version"); + }); + + test("eask emacs --batch --eval", async () => { + await ctx.runEask( + 'emacs --batch --eval "(require (quote ert))" --eval "(ert-deftest mytest () (should-not (display-graphic-p)))" -f ert-run-tests-batch', + ); + }); +}); +``` + +In Jest, group related tests using `describe`. Tests in the same describe block can share setup/teardown code, can be disabled as a group and are grouped under the same heading in output. + +Describe blocks can be nested, it's a good idea to add a nested `describe` when tests run in different directories. + +For each test directory you should create a new `TestContext` object. All `runEask` commands will use the `TestContext`'s working directory. + +You can also use `TestContext.cleanUp()` to abort any still-running commands that were called in that context. + +Jest's tests are in `test` blocks. Note that `it` is an alias for `test`. + +The `expect` API matches values in different ways and usually prints a diff as part of the failure report. +See Jest's [expect()](https://jestjs.io/docs/expect) API for more info. + +Errors thrown in a `test` block will fail it and report the error. +That's why many tests don't have an `expect` call, they simply check that the command succeeds. + +### Patterns + +Here are some common patterns for testing commands. +Each of these assumes that `ctx` is a `TestContext` object. + +Check a command succeeds: +``` javascript +test("eask analyze", async () => { + await ctx.runEask("analyze"); +}); +``` + +Check a command fails: +``` javascript +test("eask analyze", async () => { + await expect(ctx.runEask("analyze")).rejects.toThrow(); +}); +``` + +Check a command fails with a specific code: +``` javascript +// TODO +``` + +Check a command produces some output: +``` javascript +test("eask analyze", async () => { + const { stdout, stderr } = await ctx.runEask("analyze"); + expect(stderr).toMatch("success"); // should apppear as a substring + // If you want to check both `stderr` and `stdout`, just concatenate them + expect(stdout + "/n" + stderr).toMatch("success"); +}); +``` + +Match command output against a snapshot: +``` javascript +test("eask analyze", async () => { + const res = await ctx.runEask("analyze"); + expect(res).toMatchSnapshot(); +}); +``` + +The first time you run this Jest will create a new snapshot. You should check this in to version control. +If the snapshot changes, you can update the snapshot by running Jest with option `-u`, for example, +`npm run test -u` will update all changed snapshots. + +You can also match or ignore parts of an object to avoid time-varying or local data like usernames. + +Commands which modify global environment, for example with `-c` or `-g` options: +``` javascript +const { testUnsafe } = require('./helpers'); + +// this will only run if ALLOW_UNSAFE is != 0 +testUnsafe("global install", async () => { + // this installs in ~/.eask and changes ~/Eask + await ctx.runEask("install -g foo"); +}); +``` + +### Common Problems + +- Commands in `runEask` shouldn't include `eask`! + This is an error: `ctx.runEask("eask emacs")` +- When using `expect(...).rejects` it should be awaited +- The folder argument to `TestContext` should be relative to project root, if it doesn't exist you may get an error `NO_ENT` +- If you get an error from Jest reporting open handles, then try using `afterAll(() => ctx.cleanUp())` +- There are two timeout values: one used for Jest (set in `package.json`), and one used for `node.exec`, set via env var in `./helpers.js`. + The `node.exec` timeout is set lower than the Jest one, so changing timeout values for tests or by `jest.setTimeout` usually won't + have an effect. Instead set the timeout on the command itself `runEask("eask emacs", { timeout: 100000 })` From e9911f1e91f183dd2590dbc7dfa40f2c111ae69e Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Tue, 25 Mar 2025 10:24:14 -0700 Subject: [PATCH 34/70] Example of exit code matching --- test-js/link.test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test-js/link.test.js b/test-js/link.test.js index dae606a8..62200b61 100644 --- a/test-js/link.test.js +++ b/test-js/link.test.js @@ -20,7 +20,9 @@ describe("link", () => { const ctx = new TestContext("./test-js/empty"); it("eask link add should error", async () => { - await expect(ctx.runEask("link add")).rejects.toThrow(); + await expect(ctx.runEask("link add")).rejects.toMatchObject({ + code: 1, + }); }); it("adding an unknown package should error", async () => { From 62ab99603f327abf3a5fcca25be0dd195b73ff9e Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Tue, 25 Mar 2025 11:32:07 -0700 Subject: [PATCH 35/70] Add some file helpers --- test-js/helpers.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test-js/helpers.js b/test-js/helpers.js index 292edd64..d82a9268 100644 --- a/test-js/helpers.js +++ b/test-js/helpers.js @@ -1,5 +1,7 @@ const util = require("node:util"); const exec = util.promisify(require("node:child_process").exec); +const fs = require("node:fs/promises"); +const path = require("node:path"); /* * This file uses JsDoc syntax. @@ -95,6 +97,32 @@ class TestContext { cleanUp() { this.controller.abort(); } + + /** + * Test if a file exists using a path relative to this context's directory. + * Throws if file does not exist, to provide an explanation when used with + * expect(). + * @param {string} relativePath + * @returns {Promise.} + */ + fileExists(relativePath) { + const fullPath = path.resolve(this.cwd, relativePath); + return fs + .stat(fullPath) + .then((_) => true) + .catch((_) => { + throw Error("File does not exist: " + fullPath); + }); + } + + /** + * @param {string} relativePath + * @returns {Promise.} + */ + fileContents(relativePath) { + const fullPath = path.resolve(this.cwd, relativePath); + return fs.readFile(fullPath); + } } module.exports = { testUnsafe, emacsVersion, TestContext, getTimeout }; From e4dbe00a26dae0dd270d0e845b8d3779a959a9b7 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Tue, 25 Mar 2025 12:37:48 -0700 Subject: [PATCH 36/70] Add comprehensive tests to link.test.js --- test-js/link.test.js | 121 ++++++++++++++++--- test-js/link/link-fail/Eask | 37 ++++++ test-js/link/link-fail/RADME.md | 1 + test-js/link/link-fail/files/mini.pkg.1-1.el | 32 +++++ test-js/link/link-fail/files/mini.pkg.1-2.el | 31 +++++ test-js/link/link-fail/mini.pkg.1.el | 39 ++++++ test-js/link/link-to/Eask | 15 +++ test-js/link/link-to/link-to.el | 33 +++++ 8 files changed, 295 insertions(+), 14 deletions(-) create mode 100644 test-js/link/link-fail/Eask create mode 100644 test-js/link/link-fail/RADME.md create mode 100644 test-js/link/link-fail/files/mini.pkg.1-1.el create mode 100644 test-js/link/link-fail/files/mini.pkg.1-2.el create mode 100644 test-js/link/link-fail/mini.pkg.1.el create mode 100644 test-js/link/link-to/Eask create mode 100644 test-js/link/link-to/link-to.el diff --git a/test-js/link.test.js b/test-js/link.test.js index 62200b61..6fb5c3a2 100644 --- a/test-js/link.test.js +++ b/test-js/link.test.js @@ -1,36 +1,129 @@ const { TestContext } = require("./helpers"); describe("link", () => { - describe("normally", () => { + describe("in ./link", () => { const ctx = new TestContext("./test-js/link"); - it("adds a link", async () => { - await ctx.runEask('link add "mini.pkg.1" "./test/mini.pkg.1/"'); + + beforeAll(async () => { + await ctx.runEask("clean workspace"); + await ctx.runEask("refresh"); }); - it("lists links", async () => { + // check list command first since it is used in later tests + it("eask link list", async () => { await ctx.runEask("link list"); }); - it("deletes links", async () => { - await ctx.runEask("link delete mini.pkg.1-0.0.1"); + const linkName = "link-to"; + const linkPath = "./link-to/"; + + describe("eask link add", () => { + let addResult; // undefined if the first test fails + + it("adds a link", async () => { + addResult = await ctx.runEask(`link add "${linkName}" "${linkPath}"`); + expect(addResult.stderr).toMatch("Created link"); + }); + + it("should show the new link", async () => { + expect(addResult).toBeTruthy(); // fail if previous test failed + const { stdout, stderr } = await ctx.runEask("link list"); + // the name of the linked package should be included + // TODO unclear if this is a bug? + // Some output is on stderr, some is on stdout + const output = stderr + "/n" + stdout; + expect(output).toMatch(linkName); + }); + + // side effects of linking + it(`installs dependencies of ${linkName}`, async () => { + const { stderr } = await ctx.runEask("list"); + expect(stderr).toMatch("json-mode"); + }); + + it("generates a pkg.el in linked package", async () => { + expect(await ctx.fileExists(`${linkPath}/${linkName}-pkg.el`)).toBe( + true, + ); + }); + + it("can add the same link again", async () => { + await ctx.runEask(`link add "${linkName}" "${linkPath}"`); + }); + + it("fails to adds a link to uninstallable package", async () => { + // mini.pkg.1 contains dependencies from melpa, but this package only has gnu + await expect( + ctx.runEask('link add "mini.pkg.1" "./link-fail/"'), + ).rejects.toMatchObject({ + stderr: expect.stringContaining("Package not installable"), + }); + }); + }); + + describe("eask link delete", () => { + // this was tested in a previous command + // redo it here so that this test will fail if no link was added + beforeAll( + async () => await ctx.runEask(`link add "${linkName}" "${linkPath}"`), + ); + + it("deletes an added link", async () => { + const { stderr } = await ctx.runEask(`link delete ${linkName}-1.0.0`); + expect(stderr).toMatch("Package `link-to-1.0.0` unlinked"); + }); + + it("should show no links", async () => { + const { stderr } = await ctx.runEask("link list"); + expect(stderr).toMatch("No linked packages"); + }); }); }); describe("in an empty directory", () => { const ctx = new TestContext("./test-js/empty"); - it("eask link add should error", async () => { - await expect(ctx.runEask("link add")).rejects.toMatchObject({ - code: 1, - }); + beforeAll(async () => { + await ctx.runEask("clean all"); }); - it("adding an unknown package should error", async () => { - await expect(ctx.runEask("link add foo .")).rejects.toThrow(); + it("eask link list", async () => { + const { stderr } = await ctx.runEask("link list"); + expect(stderr).toMatch("No linked packages"); }); - it("deleting an unknown package should error", async () => { - await expect(ctx.runEask("link delete")).rejects.toThrow(); + describe("eask link add", () => { + it("should error when called with no arguments", async () => { + await expect(ctx.runEask("link add")).rejects.toMatchObject({ + code: 1, + }); + }); + + it("should error when linking a folder with no package file", async () => { + await expect(ctx.runEask("link add foo .")).rejects.toThrow(); + }); + + // TODO update this test when this bug is fixed + test.failing( + "should error when linking a non-existing folder", + async () => { + // currently this prints an error message but does not exit with a code + await expect( + ctx.runEask('link add bar "./nothing"'), + ).rejects.toThrow(); + }, + ); + }); + + describe("eask link delete", () => { + it("should error when called with no arguments", async () => { + await expect(ctx.runEask("link delete")).rejects.toThrow(); + }); + + it("should do nothing when deleting an unknown package", async () => { + const { stderr } = await ctx.runEask("link delete foo"); + expect(stderr).toMatch("No links present"); + }); }); }); }); diff --git a/test-js/link/link-fail/Eask b/test-js/link/link-fail/Eask new file mode 100644 index 00000000..480eef12 --- /dev/null +++ b/test-js/link/link-fail/Eask @@ -0,0 +1,37 @@ +(package "mini.pkg.1" + "0.0.1" + "Minimal test package") + +(website-url "https://github.com/emacs-eask/cli/tree/master/test/fixtures/mini.pkg.1") +(keywords "test" "local") + +(package-file "mini.pkg.1.el") + +(files "files/*.el") + +(script "test" "echo \"Have a nice day!~ ;)\"") +(script "extra" "echo :") +(script "info" "eask info") + +(eask-defcommand mini-test-1 "Test command 1." (message "Test 1")) +(eask-defcommand mini-test-2 "Test command 2." (message "Test 2")) +(eask-defcommand mini-test-3 + "Test command 3." + (message "Test 3: %s" eask-rest)) + +(source 'gnu) +(source 'melpa) +(source 'jcs-elpa) + +(depends-on "emacs" "26.1") +(depends-on "f") +(depends-on "s") +(depends-on "fringe-helper") +(depends-on "watch-cursor" + :repo "jcs-elpa/watch-cursor" :fetcher 'github) +(depends-on "organize-imports-java" + :repo "jcs-elpa/organize-imports-java" + :fetcher 'github + :files '(:defaults "sdk" "default")) + +(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test-js/link/link-fail/RADME.md b/test-js/link/link-fail/RADME.md new file mode 100644 index 00000000..441cfd06 --- /dev/null +++ b/test-js/link/link-fail/RADME.md @@ -0,0 +1 @@ +Minimal Emacs package to simulate development environment; only for testing purposes! diff --git a/test-js/link/link-fail/files/mini.pkg.1-1.el b/test-js/link/link-fail/files/mini.pkg.1-1.el new file mode 100644 index 00000000..1c7e7c73 --- /dev/null +++ b/test-js/link/link-fail/files/mini.pkg.1-1.el @@ -0,0 +1,32 @@ +;;; mini.pkg.1-1.el --- Extern file 1 -*- lexical-binding: t; -*- + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; files/mini.pkg.1-1.el +;; + +;;; Code: + + +(defun mini.pkg.1-1 () + "Test function 1." + (interactive) + ) + +(provide 'mini.pkg.1-1) +;;; mini.pkg.1-1.el ends here diff --git a/test-js/link/link-fail/files/mini.pkg.1-2.el b/test-js/link/link-fail/files/mini.pkg.1-2.el new file mode 100644 index 00000000..09d7eb8c --- /dev/null +++ b/test-js/link/link-fail/files/mini.pkg.1-2.el @@ -0,0 +1,31 @@ +;;; mini.pkg.1-2.el --- Extern file 2 -*- lexical-binding: t; -*- + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; files/mini.pkg.1-2.el +;; + +;;; Code: + +(defun mini.pkg.1-2 () + "Test function 2." + (interactive) + ) + +(provide 'mini.pkg.1-2) +;;; mini.pkg.1-2.el ends here diff --git a/test-js/link/link-fail/mini.pkg.1.el b/test-js/link/link-fail/mini.pkg.1.el new file mode 100644 index 00000000..1db1a166 --- /dev/null +++ b/test-js/link/link-fail/mini.pkg.1.el @@ -0,0 +1,39 @@ +;;; mini.pkg.1.el --- Minimal test package -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2025 the Eask authors. +;; Created date 2022-03-29 01:52:58 + +;; Author: Shen, Jen-Chieh +;; URL: https://github.com/emacs-eask/cli/tree/master/test/fixtures/mini.pkg.1 +;; Version: 0.0.1 +;; Package-Requires: ((emacs "24.3") (s "1.12.0") (fringe-helper "1.0.1")) +;; Keywords: test local + +;; This file is NOT part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; Minimal Emacs package to simulate development environment; only for testing +;; purposes! +;; + +;;; Code: + +(require 's) +(require 'fringe-helper) + +(provide 'mini.pkg.1) +;;; mini.pkg.1.el ends here diff --git a/test-js/link/link-to/Eask b/test-js/link/link-to/Eask new file mode 100644 index 00000000..29507781 --- /dev/null +++ b/test-js/link/link-to/Eask @@ -0,0 +1,15 @@ +(package "link-to" + "1.0.0" + "simple package to link") + +(website-url "https://example.org") +(keywords "test") + +(package-file "link-to.el") + +(script "test" "echo \"Error: no test specified\" && exit 1") + +(source "gnu") + +(depends-on "emacs" "26.1") +(depends-on "json-mode") diff --git a/test-js/link/link-to/link-to.el b/test-js/link/link-to/link-to.el new file mode 100644 index 00000000..e3b2188a --- /dev/null +++ b/test-js/link/link-to/link-to.el @@ -0,0 +1,33 @@ +;;; link-to.el --- summary -*- lexical-binding: t -*- + +;; Version: 1.0.0 +;; Package-Requires: ((emacs "26.2") (json-mode)) +;; Keywords: test + +;; This file is not part of GNU Emacs + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + + +;;; Commentary: + +;; commentary + +;;; Code: + +(message "Hello World!") + +(provide 'link-to) + +;;; link-to.el ends here From 90f573e72192025d348536172b965163cb4be1c7 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Tue, 25 Mar 2025 13:47:08 -0700 Subject: [PATCH 37/70] Move upgrade-eask test to own file --- test-js/local.test.js | 5 ----- test-js/upgrade-eask.test.js | 8 ++++++++ 2 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 test-js/upgrade-eask.test.js diff --git a/test-js/local.test.js b/test-js/local.test.js index ac42d7bc..887d8b9c 100644 --- a/test-js/local.test.js +++ b/test-js/local.test.js @@ -260,11 +260,6 @@ describe("local", () => { it("locate", async () => { await ctx.runEask("locate"); }); - // TODO hmm, this might cause weird effects - test.skip("upgrade-eask", async () => { - await ctx.runEask("upgrade-eask"); - }); - it("refresh", async () => { await ctx.runEask("refresh"); }); diff --git a/test-js/upgrade-eask.test.js b/test-js/upgrade-eask.test.js new file mode 100644 index 00000000..10c2b9a8 --- /dev/null +++ b/test-js/upgrade-eask.test.js @@ -0,0 +1,8 @@ +const { testUnsafe, TestContext } = require("./helpers"); + +describe("upgrade-eask", () => { + const ctx = new TestContext(); + testUnsafe("eask upgrade-eask", async () => { + await ctx.runEask("upgrade-eask"); + }); +}); From 8f8b559478940a925f082cac28e41ce36aa22c5d Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Tue, 25 Mar 2025 14:54:11 -0700 Subject: [PATCH 38/70] Check result of commands in install.test.js --- test-js/install.test.js | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/test-js/install.test.js b/test-js/install.test.js index 3d9e5cd7..5e5159dd 100644 --- a/test-js/install.test.js +++ b/test-js/install.test.js @@ -1,37 +1,45 @@ const { TestContext } = require("./helpers"); describe("install and uninstall", () => { - describe("in mini.pkg.1", () => { + describe("in ./install", () => { const ctx = new TestContext("./test-js/install/"); + const packageName = "mini.pkg.1"; - // beforeAll(async () => await exec("eask clean all", { cwd })); - - // TODO also teardown? - afterAll(async () => await ctx.runEask("clean all")); - afterAll(() => ctx.cleanUp()); - - // TODO this can take a really really long time! - // TODO all later commands depend on this? - test("installs dependencies", async () => { + beforeAll(async () => { + await ctx.runEask("clean all"); await ctx.runEask("install-deps"); }); + afterAll(() => ctx.cleanUp()); + it("installs project package", async () => { - await ctx.runEask("package"); - await ctx.runEask("install"); + await ctx.runEask("package"); // creates dist/.tar + await ctx.runEask("install"); // installs dependencies and generated package + const { stderr } = await ctx.runEask("list"); + expect(stderr).toMatch(packageName); }); it("installs specific packages", async () => { - await ctx.runEask("install beacon company-fuzzy transwin"); + const { stderr } = await ctx.runEask( + "install beacon company-fuzzy transwin", + ); + expect(stderr).toMatch("beacon"); + expect(stderr).toMatch("company-fuzzy"); + expect(stderr).toMatch("transwin"); }); - // TODO stateful it("uninstalls specific packages", async () => { + await ctx.runEask("install beacon transwin"); await ctx.runEask("uninstall beacon transwin"); + const { stderr } = await ctx.runEask("list"); + expect(stderr).not.toMatch("beacon"); + expect(stderr).not.toMatch("transwin"); }); it("uninstalls project package", async () => { await ctx.runEask("uninstall"); + const { stderr } = await ctx.runEask("list"); + expect(stderr).not.toMatch(packageName); }); }); From b8a8f62307d2a2bb6783cb3ffb063d3eb71714df Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Tue, 25 Mar 2025 14:54:24 -0700 Subject: [PATCH 39/70] Disable js-elpa in install.test.js to speed up test --- test-js/install/Eask | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test-js/install/Eask b/test-js/install/Eask index 480eef12..aa3c6aeb 100644 --- a/test-js/install/Eask +++ b/test-js/install/Eask @@ -21,17 +21,17 @@ (source 'gnu) (source 'melpa) -(source 'jcs-elpa) +;; (source 'jcs-elpa) (depends-on "emacs" "26.1") (depends-on "f") (depends-on "s") -(depends-on "fringe-helper") -(depends-on "watch-cursor" - :repo "jcs-elpa/watch-cursor" :fetcher 'github) -(depends-on "organize-imports-java" - :repo "jcs-elpa/organize-imports-java" - :fetcher 'github - :files '(:defaults "sdk" "default")) +;; (depends-on "fringe-helper") +;; (depends-on "watch-cursor" +;; :repo "jcs-elpa/watch-cursor" :fetcher 'github) +;; (depends-on "organize-imports-java" +;; :repo "jcs-elpa/organize-imports-java" +;; :fetcher 'github +;; :files '(:defaults "sdk" "default")) (setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 From 6535d091415b0975789c22b3ba13080d030f86b5 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Tue, 25 Mar 2025 16:15:13 -0700 Subject: [PATCH 40/70] Add output transformation helper --- test-js/helpers.js | 77 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/test-js/helpers.js b/test-js/helpers.js index d82a9268..79f976e0 100644 --- a/test-js/helpers.js +++ b/test-js/helpers.js @@ -49,6 +49,68 @@ async function emacsVersion() { return version; } +/** Provides transformations on output of node.exec(). */ +class CommandOutput { + constructor(output, cwd) { + this.stderr = output.stderr; + this.stdout = output.stdout; + this.cwd = cwd; + this.cwdAbsolute = path.resolve(cwd || "."); + } + + /** + * Both stdout and stderr concatenated as a string. + * @returns {string} + */ + combined() { + return this.stdout + "\n" + this.stderr; + } + + /** + * Output as a plain object. + * @returns {{ sdout: string, stderr: string }} + */ + raw() { + return { + stderr: this.stderr, + stdout: this.stdout, + }; + } + + /** + * Attempt to make `s` safe for snapshotting by replacing local data. + * @param {string} s + * @returns {string} + */ + sanitizeString(s) { + let working = s; + // replace absolute path + working = working.replace(RegExp(this.cwdAbsolute, "g"), "~"); + // replace relative path + working = working.replace(RegExp(this.cwd, "g"), "~"); + return working; + } + + /** + * Create a copy of this object with output safe for snapshotting. + * @param {...function(string):string[]} sanitizeFns functions to apply to the output. + * These apply after the default sanitize functions. + * @returns {CommandOutput} + */ + sanitized(...sanitizeFns) { + let sani = (s) => + sanitizeFns.reduce((s1, f) => f.call({}, s1), this.sanitizeString(s)); + + return new CommandOutput( + { + stdout: sani(this.stdout), + stderr: sani(this.stderr), + }, + this.cwd, + ); + } +} + class TestContext { /** * @param {string} cwd Current Working Directory, used for all commands. @@ -65,7 +127,7 @@ class TestContext { * for additional config options. * @param {string} command * @param {any} config - * @returns {Promise.<{ stdout, stderr }>} + * @returns {Promise.} */ runEask(command, config) { return this.run(this.easkCommand + " " + command, config); @@ -86,7 +148,7 @@ class TestContext { (obj.stderr ? obj.stderr : ""), ); } - return obj; + return new CommandOutput(obj, this.cwd); }) .catch((err) => { if (!err.code) err.message += "\nexec: TIMEOUT"; @@ -111,11 +173,12 @@ class TestContext { .stat(fullPath) .then((_) => true) .catch((_) => { - throw Error("File does not exist: " + fullPath); + throw Error("File does not exist, or is not readable: " + fullPath); }); } /** + * Get file contents as a string, relative to the context's directory. * @param {string} relativePath * @returns {Promise.} */ @@ -125,4 +188,10 @@ class TestContext { } } -module.exports = { testUnsafe, emacsVersion, TestContext, getTimeout }; +module.exports = { + testUnsafe, + emacsVersion, + TestContext, + getTimeout, + CommandOutput, +}; From b8c49796d13648a569aab61a3b27a2792f81ab93 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Mon, 24 Mar 2025 21:19:20 -0700 Subject: [PATCH 41/70] Add examples of snapshots to analyze.test.js --- test-js/__snapshots__/analyze.test.js.snap | 23 +++++++++++++++++ test-js/analyze.test.js | 30 ++++++++++++++++------ 2 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 test-js/__snapshots__/analyze.test.js.snap diff --git a/test-js/__snapshots__/analyze.test.js.snap b/test-js/__snapshots__/analyze.test.js.snap new file mode 100644 index 00000000..c7ecd818 --- /dev/null +++ b/test-js/__snapshots__/analyze.test.js.snap @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`analyze in ./dsl matches snapshot 1`] = ` +{ + "stderr": " +~/Eask:7:18 Error: Multiple definition of \`package' +~/Eask:10:55 Error: Multiple definition of \`website-url' +~/Eask:12:16 Error: Multiple definition of \`keywords' +~/Eask:15:15 Warning: Warning regarding duplicate author name, name +~/Eask:18:17 Warning: Warning regarding duplicate license name, GPLv3 +~/Eask:21:29 Error: Multiple definition of \`package-file' +~/Eask:23:35 Warning: Pkg-file seems to be missing \`check-pkg.el' +~/Eask:24:35 Error: Multiple definition of \`package-descriptor' +~/Eask:28:61 Error: Run-script with the same key name is not allowed: \`test\` +~/Eask:31:13 Error: Multiple definition of source \`gnu' +~/Eask:33:24 Error: Unknown package archive \`magic-archive' +~/Eask:36:20 Error: Define dependencies with the same name \`emacs' +~/Eask:39:19 Error: Define dependencies with the same name \`dash' +~/Eask:44:2 Error: Define dependencies with the same name \`f' +", + "stdout": "", +} +`; diff --git a/test-js/analyze.test.js b/test-js/analyze.test.js index ebb91b55..c373733d 100644 --- a/test-js/analyze.test.js +++ b/test-js/analyze.test.js @@ -1,30 +1,44 @@ const { TestContext } = require("./helpers"); describe("analyze", () => { - describe("dsl", () => { - const cwd = "./test-js/dsl"; - const ctx = new TestContext(cwd); + describe("in ./dsl", () => { + const ctx = new TestContext("./test-js/dsl"); it("handles plain text", async () => { await ctx.runEask("analyze"); await ctx.runEask("analyze Eask"); }); - it("handles json", async () => { - await ctx.runEask("analyze --json"); + it("handles json option", async () => { + const { stderr } = await ctx.runEask("analyze --json"); await ctx.runEask("analyze Eask --json"); + + // try to parse output, errors if not valid + JSON.parse(stderr); + }); + + it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res.sanitized().raw(); + expect(resClean).toMatchSnapshot(); + }); + + it("should report multiple definitions", async () => { + const { stderr } = await ctx.runEask("analyze"); + // expect this substring + expect(stderr).toMatch("Multiple definition of `package'"); }); }); - describe("error", () => { + describe("in ./empty", () => { const ctx = new TestContext("./test-js/empty"); - it("errors in an empty dir", async () => { + it("should error", async () => { await expect(ctx.runEask("analyze")).rejects.toThrow(); }); }); - describe("metadata", () => { + describe("in ./metadata", () => { const ctx = new TestContext("./test-js/metadata"); it("handles plain text", async () => { From b2f72c089efc7b888ef8bb3bdb2076a628e0e0c0 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Tue, 25 Mar 2025 16:33:38 -0700 Subject: [PATCH 42/70] Update doco with snapshot example --- .../content/Contributing/Testing/_index.en.md | 96 +++++++++++++++---- 1 file changed, 76 insertions(+), 20 deletions(-) diff --git a/docs/content/Contributing/Testing/_index.en.md b/docs/content/Contributing/Testing/_index.en.md index d8d3c624..7b22e943 100644 --- a/docs/content/Contributing/Testing/_index.en.md +++ b/docs/content/Contributing/Testing/_index.en.md @@ -5,10 +5,16 @@ weight: 20 {{< toc >}} -Local testing for Eask is done using the [Jest]() testing framework. +This describes how to run tests locally, and how to write new tests for Eask. + +Local testing for Eask is done using the [Jest](https://jestjs.io) testing framework. + +- TODO why jest A custom `TestContext` class is used to manage the execution environment for each test suite. +- TODO perhaps not relevant here + ### Running Tests If you have not done so already, run `npm install --dev` @@ -20,21 +26,28 @@ Always run from the project root (i.e. same directory as `package.json`) - run tests with full output `npm run test-debug` - remove files created during test `npm run test-reset` +Since `npm run test` just runs Jest, you can also pass Jest options to the +commands above. +For example +- run tests whose names (in `test()` blocks) match `npm run test -t 'eask lint .*'` +- re-run failed tests `npm run test -f` + ### Environment Vars -| Name | Type | Default | Meaning | -|:---------------|:-------|---------|:-------------------------------------------------------------------------------------------| -| `ALLOW_UNSAFE` | bool | 0 | Run tests in `testUnsafe` blocks. These can affect your emacs config or settings. | -| `DEBUG` | bool | 0 | Print full output from commands in test. | -| `EASK_COMMAND` | path | "eask" | Path to Eask. Usually either `eask` or `./bin/eask` (include local changes). | -| `TIMEOUT` | number | 25000 | Command timeout in ms. Note this is different than Jest's timeout, which should be larger. | +| Name | Type | Default | Meaning | +|:---------------|:-------|---------|:--------------------------------------------------------------------------------------------------| +| `ALLOW_UNSAFE` | bool | 0 | Run tests in `testUnsafe` blocks. These can **overwrite** your personal emacs config or settings. | +| `DEBUG` | bool | 0 | Print full output from commands in test. | +| `EASK_COMMAND` | path | "eask" | Path to Eask. Usually either `eask` or `./bin/eask` (include local changes). | +| `TIMEOUT` | number | 25000 | Command timeout in ms. Note this is different than Jest's timeout, which should be greater. | ### How to Write a Test **Folder structure** -Tests should be in `test/js` -Related tests should be in the same file with the suffix `.test.js`. +Tests should be in `test/js`. +Related tests should be in the same file with the suffix `.test.js` and are usually named after the +feature or command that they test, for example `link.test.js` tests the `eask link` command. If the test needs some specific project files, put them in a new folder within `test/js` For example, files in `test/js/foo` would be expected to be for `foo.test.js`. @@ -65,20 +78,29 @@ describe("emacs", () => { }); ``` -In Jest, group related tests using `describe`. Tests in the same describe block can share setup/teardown code, can be disabled as a group and are grouped under the same heading in output. +In Jest, you group related tests using `describe`. Tests in the same describe block can share setup/teardown code, +can be disabled as a group and are grouped under the same heading in output. -Describe blocks can be nested, it's a good idea to add a nested `describe` when tests run in different directories. +`describe` blocks can be nested within other `describe` blocks. +It's a good idea to add a nested `describe` when tests run in different directories, or to match a "given, when, then" style of testing. -For each test directory you should create a new `TestContext` object. All `runEask` commands will use the `TestContext`'s working directory. +For each test directory you should create a new `TestContext` object. +All `runEask` commands will use the `TestContext`'s working directory. You can also use `TestContext.cleanUp()` to abort any still-running commands that were called in that context. +Note that it sends a signal to *all* processes started using the context's `runEask` command. +If used in an `afterEach` hook (i.e. after every test) it may result in failures. Jest's tests are in `test` blocks. Note that `it` is an alias for `test`. +Tests can be selectively disabled in code, like so: +- `test.only(name, fn)` runs only that test in the file +- `test.skip(name, fn)` skips running the test but still prints its name +- `test.failing(name, fn)` invert the meaning of the test: it *should* fail. The `expect` API matches values in different ways and usually prints a diff as part of the failure report. See Jest's [expect()](https://jestjs.io/docs/expect) API for more info. -Errors thrown in a `test` block will fail it and report the error. +Uncaught errors thrown in a `test` block will fail it and report the error. That's why many tests don't have an `expect` call, they simply check that the command succeeds. ### Patterns @@ -102,7 +124,12 @@ test("eask analyze", async () => { Check a command fails with a specific code: ``` javascript -// TODO +test("eask link add should error", async () => { + // the error object should have property code = 1 + await expect(ctx.runEask("link add")).rejects.toMatchObject({ + code: 1, + }); +}); ``` Check a command produces some output: @@ -125,9 +152,39 @@ test("eask analyze", async () => { The first time you run this Jest will create a new snapshot. You should check this in to version control. If the snapshot changes, you can update the snapshot by running Jest with option `-u`, for example, -`npm run test -u` will update all changed snapshots. +`npm run test -- -u` will update all changed snapshots. + +Often snapshots will include data that varies with time or environment, for example timestamps or file paths. +The snapshot above includes absolute file paths that will be different on every machine. + +Output from `runEask` is wrapped in a helper class `CommandOutput` which provides some transformations to help. +The simplest just removes the absolute file paths: +``` javascript +it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res.sanitized() // a CommandOutput object with absolute paths replaced by "~" + .raw(); // an object { stderr, stdout } suitable for snapshotting + expect(resClean).toMatchSnapshot(); +}); +``` + +You can include custom replacement functions. Here, numbers will be replaced by `"x"`. +Then strings `"x:x"` will be replaced by `"y"`. +``` javascript +it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res + .sanitized( + (x) => x.replace(/[0-9]+/g, "x"), + (x) => x.replace(/x:x/g, "y"), + ) + .raw(); + expect(resClean).toMatchSnapshot(); +}); +``` -You can also match or ignore parts of an object to avoid time-varying or local data like usernames. +It's important to use the `g` regex flag so all occurrences of the match are replaced, or you could use `replaceAll`. +User provided functions run in addition to the default sanitize function and run in the order they were given. Commands which modify global environment, for example with `-c` or `-g` options: ``` javascript @@ -142,10 +199,9 @@ testUnsafe("global install", async () => { ### Common Problems -- Commands in `runEask` shouldn't include `eask`! - This is an error: `ctx.runEask("eask emacs")` -- When using `expect(...).rejects` it should be awaited -- The folder argument to `TestContext` should be relative to project root, if it doesn't exist you may get an error `NO_ENT` +- When using `runEask()`, pass only the Eask *arguments*, not the `eask` command itself. +- When using `expect(...).rejects` it should be awaited so that the promise rejects before the test completes. +- The folder argument to `TestContext` should be relative to project root, if it doesn't exist you may get an error `ENOENT` - If you get an error from Jest reporting open handles, then try using `afterAll(() => ctx.cleanUp())` - There are two timeout values: one used for Jest (set in `package.json`), and one used for `node.exec`, set via env var in `./helpers.js`. The `node.exec` timeout is set lower than the Jest one, so changing timeout values for tests or by `jest.setTimeout` usually won't From b00e55a0ac0dba03fbe9530a0d1d5865e9e99246 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Tue, 25 Mar 2025 20:41:24 -0700 Subject: [PATCH 43/70] Simplify options.test.js using test table --- test-js/options.test.js | 106 +++++++++------------------------------- 1 file changed, 24 insertions(+), 82 deletions(-) diff --git a/test-js/options.test.js b/test-js/options.test.js index 7e85643f..0953f817 100644 --- a/test-js/options.test.js +++ b/test-js/options.test.js @@ -8,87 +8,29 @@ describe("options", () => { await expect(ctx.runEask("info -global")).rejects.toThrow(); }); - test("eask info -a", async () => { - await ctx.runEask("info -a"); - }); - - test("eask info --all", async () => { - await ctx.runEask("info --all"); - }); - - test("eask info -q", async () => { - await ctx.runEask("info -q"); - }); - - test("eask info --quick", async () => { - await ctx.runEask("info --quick"); - }); - - test("eask info -f", async () => { - await ctx.runEask("info -f"); - }); - - test("eask info --force", async () => { - await ctx.runEask("info --force"); - }); - - test("eask info --debug", async () => { - await ctx.runEask("info --debug"); - }); - - test("eask info --strict", async () => { - await ctx.runEask("info --strict"); - }); - - test("eask info --allow-error", async () => { - await ctx.runEask("info --allow-error"); - }); - - test("eask info --insecure", async () => { - await ctx.runEask("info --insecure"); - }); - - test("eask info --timestamps", async () => { - await ctx.runEask("info --timestamps"); - }); - - test("eask info --log-level", async () => { - await ctx.runEask("info --log-level"); - }); - - test("eask info --elapsed-time", async () => { - await ctx.runEask("info --elapsed-time"); - }); - - test("eask info --et", async () => { - await ctx.runEask("info --et"); - }); - - test("eask info --no-color", async () => { - await ctx.runEask("info --no-color"); - }); - - test("eask info --proxy localhost:8080", async () => { - await ctx.runEask("info --proxy localhost:8080"); - }); - - test("eask info --http-proxy localhost:8080", async () => { - await ctx.runEask("info --http-proxy localhost:8080"); - }); - - test("eask info --https-proxy localhost:8080", async () => { - await ctx.runEask("info --https-proxy localhost:8080"); - }); - - test("eask info --no-proxy localhost:8080", async () => { - await ctx.runEask("info --no-proxy localhost:8080"); - }); - - test("eask info -v 4", async () => { - await ctx.runEask("info -v 4"); - }); - - test("eask info --verbose 4", async () => { - await ctx.runEask("info --verbose 4"); + test.each([ + "-a", + "--all", + "-q", + "--quick", + "-f", + "--force", + "--debug", + "--strict", + "--allow-error", + "--insecure", + "--timestamps", + "--log-level", + "--elapsed-time", + "--et", + "--no-color", + "--proxy localhost:8080", + "--http-proxy localhost:8080", + "--https-proxy localhost:8080", + "--no-proxy localhost:8080", + "-v 4", + "--verbose 4", + ])("eask info %s", async (opt) => { + await ctx.runEask(`info ${opt}`); }); }); From 269a03c18e2ee45787e302a9184a90b78a3e5794 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 26 Mar 2025 09:24:27 -0700 Subject: [PATCH 44/70] Update bug descriptions in link.test.js --- test-js/link.test.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/test-js/link.test.js b/test-js/link.test.js index 6fb5c3a2..845880af 100644 --- a/test-js/link.test.js +++ b/test-js/link.test.js @@ -29,8 +29,7 @@ describe("link", () => { expect(addResult).toBeTruthy(); // fail if previous test failed const { stdout, stderr } = await ctx.runEask("link list"); // the name of the linked package should be included - // TODO unclear if this is a bug? - // Some output is on stderr, some is on stdout + // FIXME: Some output is on stderr, some is on stdout const output = stderr + "/n" + stdout; expect(output).toMatch(linkName); }); @@ -51,7 +50,12 @@ describe("link", () => { await ctx.runEask(`link add "${linkName}" "${linkPath}"`); }); - it("fails to adds a link to uninstallable package", async () => { + // FIXME: bug + // - fails when there is a pkg-file in link-fail + // - succeeds when no pkg-file + // this means: 1st run it adds link-fail, generates new pkg.el + // 2nd run it fails to add link-fail! + it.skip("fails to add a link to uninstallable package", async () => { // mini.pkg.1 contains dependencies from melpa, but this package only has gnu await expect( ctx.runEask('link add "mini.pkg.1" "./link-fail/"'), @@ -62,11 +66,12 @@ describe("link", () => { }); describe("eask link delete", () => { - // this was tested in a previous command - // redo it here so that this test will fail if no link was added - beforeAll( - async () => await ctx.runEask(`link add "${linkName}" "${linkPath}"`), - ); + beforeAll(async () => { + await ctx.runEask("clean workspace"); + // this was tested in a previous command + // redo it here so that this test will fail if no link was added + await ctx.runEask(`link add "${linkName}" "${linkPath}"`); + }); it("deletes an added link", async () => { const { stderr } = await ctx.runEask(`link delete ${linkName}-1.0.0`); @@ -103,7 +108,7 @@ describe("link", () => { await expect(ctx.runEask("link add foo .")).rejects.toThrow(); }); - // TODO update this test when this bug is fixed + // FIXME: update this test when this bug is fixed test.failing( "should error when linking a non-existing folder", async () => { From 53b30e94f784226361466de74354994abaf82e74 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 26 Mar 2025 09:59:22 -0700 Subject: [PATCH 45/70] Sanitize windows style paths --- test-js/helpers.js | 15 +++++++++++++-- test-js/helpers.test.js | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 test-js/helpers.test.js diff --git a/test-js/helpers.js b/test-js/helpers.js index 79f976e0..340915ab 100644 --- a/test-js/helpers.js +++ b/test-js/helpers.js @@ -84,10 +84,21 @@ class CommandOutput { */ sanitizeString(s) { let working = s; + // windows paths + if (this.cwdAbsolute.startsWith(":", 1)) { + // cwdAbsolute is a windows path e.g. C:\foo\bar + // Eask outputs windows paths like d:/a/cli/Eask + let cwdTranslated = this.cwdAbsolute.replaceAll("\\", "/"); + // lowercase the drive letter + cwdTranslated = + cwdTranslated[0].toLowerCase() + cwdTranslated.substring(1); + working = working.replaceAll(cwdTranslated, "~"); + } + // replace absolute path - working = working.replace(RegExp(this.cwdAbsolute, "g"), "~"); + working = working.replaceAll(this.cwdAbsolute, "~"); // replace relative path - working = working.replace(RegExp(this.cwd, "g"), "~"); + working = working.replaceAll(this.cwd, "~"); return working; } diff --git a/test-js/helpers.test.js b/test-js/helpers.test.js new file mode 100644 index 00000000..ae82aa81 --- /dev/null +++ b/test-js/helpers.test.js @@ -0,0 +1,36 @@ +const { CommandOutput } = require("./helpers"); +const path = require("node:path"); + +describe("CommandOutput", () => { + describe("sanitizeString", () => { + let out = new CommandOutput({}, "./test-js"); + + it("replaces relative paths", () => { + let res = out.sanitizeString("look at ./test-js/foo.js"); + expect(res).toBe("look at ~/foo.js"); + }); + + it("replaces relative path literally", () => { + let res = out.sanitizeString("look at a/test-js/foo.js"); + expect(res).toBe("look at a/test-js/foo.js"); + }); + + it("replaces absolute paths", () => { + let res = out.sanitizeString( + `look at ${path.resolve("./test-js", "foo.js")}`, + ); + expect(res).toBe(`look at ${path.join("~", "foo.js")}`); + }); + + it("replaces windows formatted paths", () => { + let out = new CommandOutput({}, "./test-js/options"); + // force a windows style path + out.cwdAbsolute = "D:\\a\\cli\\cli\\test-js\\options"; + // when on windows Eask translates those paths like + let res = out.sanitizeString( + "d:/a/cli/cli/test-js/options/Eask:7:18 Error: Multiple definition of `package'", + ); + expect(res).toBe("~/Eask:7:18 Error: Multiple definition of `package'"); + }); + }); +}); From e7bb0cdf05daec36452f270c38387b2edfb67e64 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 26 Mar 2025 10:23:52 -0700 Subject: [PATCH 46/70] fix: try using double quotes to fix windows issue in exec.test.js --- test-js/exec.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test-js/exec.test.js b/test-js/exec.test.js index 972eae5f..8e903694 100644 --- a/test-js/exec.test.js +++ b/test-js/exec.test.js @@ -24,8 +24,7 @@ describe("exec", () => { }); test("eask exec buttercup -L . --pattern 'pattern 1'", async () => { - // TODO this causes a bug on windows docker image - await ctx.runEask("exec buttercup -L . --pattern 'pattern 1'"); + await ctx.runEask('exec buttercup -L . --pattern "pattern 1"'); }); test("should error with no args", async () => { From 39244bc51285c02048f75f8f2078fefaf64949d7 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 26 Mar 2025 10:58:23 -0700 Subject: [PATCH 47/70] Teardown global env when ALLOW_UNSAFE is true --- test-js/global.test.js | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/test-js/global.test.js b/test-js/global.test.js index c44f1111..a68c9875 100644 --- a/test-js/global.test.js +++ b/test-js/global.test.js @@ -25,15 +25,27 @@ describe("global", () => { describe("install", () => { /* - * This test modifies ~/.eask + * This test modifies ~/.eask and ~/Eask */ - testUnsafe("eask install -g", async () => { + beforeAll(async () => { // add a global Easkfile - await fs.copyFile( - "./test-js/global/Eask", - path.join(process.env.HOME, "Eask"), - ); + if (process.env.ALLOW_UNSAFE) { + await fs.copyFile( + "./test-js/global/Eask", + path.join(process.env.HOME, "Eask"), + ); + } + }); + afterAll(async () => { + if (process.env.ALLOW_UNSAFE) { + // remove test changes + await ctx.runEask("uninstall -g spinner ivy beacon company-fuzzy"); + await fs.rm(path.join(process.env.HOME, "Eask")); + } + }); + + testUnsafe("eask install -g", async () => { await ctx.runEask("install -g spinner ivy beacon company-fuzzy"); }); From 94c1bdff89d2dd6a27b371b2687528a02776f51a Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 26 Mar 2025 10:58:49 -0700 Subject: [PATCH 48/70] Check for global Easkfile in info -g test --- test-js/options.test.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/test-js/options.test.js b/test-js/options.test.js index 0953f817..7069b0ac 100644 --- a/test-js/options.test.js +++ b/test-js/options.test.js @@ -3,9 +3,19 @@ const { TestContext } = require("./helpers"); describe("options", () => { const ctx = new TestContext("./test-js/options"); - test("eask info -g should error", async () => { - await expect(ctx.runEask("info -g")).rejects.toThrow(); - await expect(ctx.runEask("info -global")).rejects.toThrow(); + describe("eask info errors", () => { + const ctx = new TestContext(process.env.HOME); + test("eask info should error without an Easkfile", async () => { + const hasGlobal = + (await ctx.fileExists("Eask").catch(() => false)) || + (await ctx.fileExists("Easkfile").catch(() => false)); + // If there is a global Easkfile then just skip testing + // Better to not test than to raise false errors + if (!hasGlobal) { + await expect(ctx.runEask("info -g")).rejects.toThrow(); + await expect(ctx.runEask("info --global")).rejects.toThrow(); + } + }); }); test.each([ From b9f0ad5f8f4accb5a75a1aa78d7da95a6c8c9871 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 26 Mar 2025 11:07:59 -0700 Subject: [PATCH 49/70] Add removeFiles helper method --- test-js/helpers.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test-js/helpers.js b/test-js/helpers.js index 340915ab..615290e9 100644 --- a/test-js/helpers.js +++ b/test-js/helpers.js @@ -197,6 +197,20 @@ class TestContext { const fullPath = path.resolve(this.cwd, relativePath); return fs.readFile(fullPath); } + + /** + * Removes files or directories under the context's directory. + * Errors are silently ignored. + * @param {...string} filesOrDirs files or directories to remove + * @returns {Promise.} + */ + async removeFiles(...filesOrDirs) { + for (let f of filesOrDirs) { + await fs + .rm(path.join(this.cwd, f), { recursive: true, retries: 1 }) + .catch(() => {}); // ignore "does not exist errors" + } + } } module.exports = { From c76c44c0bb60790cb09c05ef76eefeb01846edd9 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 26 Mar 2025 11:47:01 -0700 Subject: [PATCH 50/70] Tidy up generated files in local.test.js --- test-js/local.test.js | 193 ++++++++++++++++++++++-------------------- 1 file changed, 99 insertions(+), 94 deletions(-) diff --git a/test-js/local.test.js b/test-js/local.test.js index 887d8b9c..4127dcbc 100644 --- a/test-js/local.test.js +++ b/test-js/local.test.js @@ -6,13 +6,12 @@ const { emacsVersion, TestContext } = require("./helpers"); -const fs = require("node:fs/promises"); -const path = require("node:path"); - describe("local", () => { const cwd = "./test-js/local"; const ctx = new TestContext(cwd); + // NOTE: install-deps takes a long time in this package + afterAll(() => ctx.cleanUp()); describe("info commands", () => { @@ -35,14 +34,18 @@ describe("local", () => { it("bump", async () => { await ctx.runEask("bump major minor patch"); }); + // NOTE: eask cat is a long running command it("cat", async () => { + // cat requires e2ansi, installing it takes a while await ctx.runEask("cat package.json --insecure"); await ctx.runEask("cat package.json --number --insecure"); }); it("concat", async () => { await ctx.runEask("concat"); }); + // NOTE: eask loc is a long running command it("loc", async () => { + // installs markdown mode if ((await emacsVersion()) > "27.1") { await ctx.runEask("loc"); await ctx.runEask("loc Eask"); @@ -61,14 +64,9 @@ describe("local", () => { }); }); - describe("Preparation", () => { - afterAll(async () => await ctx.runEask("clean all")); - - // install-deps - // TODO this times out - it("prepare --dev", async () => { - await ctx.runEask("prepare --dev"); - }); + describe.skip("Preparation", () => { + beforeAll(async () => await ctx.runEask("prepare --dev")); + afterAll(async () => await ctx.runEask("clean dist")); it("package", async () => { await ctx.runEask("package"); @@ -76,8 +74,6 @@ describe("local", () => { }); describe("Development", () => { - // TODO takes a long time, organize-imports-java? - // works when installed beforeAll(async () => await ctx.runEask("install-deps")); // this requires install-deps it("compile", async () => { @@ -110,95 +106,114 @@ describe("local", () => { }); }); - // TODO requires install-deps describe("Execution", () => { + beforeAll(async () => await ctx.runEask("install-deps")); + test("eval", async () => { await ctx.runEask('eval "(progn (require \'mini.pkg.1))"'); }); }); describe("Generating", () => { - it("generate autoloads", async () => { - await ctx.runEask("generate autoloads"); + beforeAll(async () => { + // from generate ignore elisp + await ctx.removeFiles(".gitignore"); }); - it("generate pkg-file", async () => { - await ctx.runEask("generate pkg-file"); + + afterAll(async () => { + await ctx.runEask("clean autoloads").catch(() => {}); + await ctx.runEask("clean pkg-file").catch(() => {}); + + await ctx.removeFiles( + "recipes", // from generate recipes + ".gitignore", // from generate ignore elisp + ); }); - it("generate recipe -y", async () => { - await ctx.runEask("generate recipe -y"); + + it.each([ + "generate autoloads", + "generate pkg-file", + "generate recipe -y", + "generate ignore elisp", + ])("eask %s", async (cmd) => { + await ctx.runEask(cmd); }); - // await ctx.runEask("generate license gpl-3.0"); # XXX: Avoid API rate limit exceeded error - it("generate ignore elisp", async () => { - await ctx.runEask("generate ignore elisp"); + + it.skip("eask generate license", async () => { + // XXX: Avoid API rate limit exceeded error + await ctx.runEask("generate license gpl-3.0"); }); }); describe("Generating tests", () => { - it("generate test ert", async () => { - await ctx.runEask("generate test ert"); - await fs.rm(path.join(cwd, "/test"), { recursive: true, retries: 1 }); - }); - it("generate test ert-runner", async () => { - await ctx.runEask("generate test ert-runner"); - }); - it("generate test buttercup", async () => { - await ctx.runEask("generate test buttercup"); - }); - it("generate test ecukes", async () => { - await ctx.runEask("generate test ecukes"); + // some tests fail if ./test already exists + beforeEach(async () => await ctx.removeFiles("features", "test", "tests")); + afterAll(async () => await ctx.removeFiles("features", "test", "tests")); + + it.each([ + "generate test ert", + "generate test ert-runner", + "generate test buttercup", + "generate test ecukes", + ])("eask %s", async (cmd) => { + await ctx.runEask(cmd); }); }); describe("Generating workflow", () => { - it("generate workflow circle-ci", async () => { - await ctx.runEask("generate workflow circle-ci"); - }); - it("generate workflow github", async () => { - await ctx.runEask("generate workflow github"); - }); - it("generate workflow gitlab", async () => { - await ctx.runEask("generate workflow gitlab"); - }); - it("generate workflow travis-ci", async () => { - await ctx.runEask("generate workflow travis-ci"); + beforeEach( + async () => + await ctx.removeFiles( + ".circleci", + ".gitlab-ci.yml", + ".github", + ".travis.yml", + ), + ); + afterAll( + async () => + await ctx.removeFiles( + ".circleci", + ".gitlab-ci.yml", + ".github", + ".travis.yml", + ), + ); + + it.each([ + "generate workflow circle-ci", + "generate workflow github", + "generate workflow gitlab", + "generate workflow travis-ci", + ])("eask %s", async (cmd) => { + await ctx.runEask(cmd); }); }); describe("Linting", () => { - // TODO some lint commands may fail if packages are missing - it("lint checkdoc", async () => { - await ctx.runEask("lint checkdoc"); - }); - it("lint declare", async () => { - await ctx.runEask("lint declare"); - }); - it("lint elint", async () => { - await ctx.runEask("lint elint"); - }); - it("lint elisp-lint", async () => { - await ctx.runEask("lint elisp-lint"); - }); - // XXX: Elsa is not stable, ignore it for now - test.skip("lint elsa", async () => { - await ctx.runEask("lint elsa"); - }); - it("lint indent", async () => { - await ctx.runEask("lint indent"); - }); - it("lint keywords", async () => { - await ctx.runEask("lint keywords"); - }); - it("lint license", async () => { - await ctx.runEask("lint license"); - }); - it("lint package", async () => { - await ctx.runEask("lint package"); + // some lint commands may fail if packages are missing + beforeAll(async () => await ctx.runEask("install-deps")); + it.each([ + "lint checkdoc", + "lint declare", + "lint elint", + "lint elisp-lint", + "lint indent", + "lint keywords", + "lint license", + "lint package", + ])("eask %s", async (cmd) => { + await ctx.runEask(cmd); }); it("lint regexps", async () => { if ((await emacsVersion()) > "27.1") { await ctx.runEask("lint regexps"); } }); + // XXX: Elsa is not stable, ignore it for now + test.skip("lint elsa", async () => { + await ctx.runEask("lint elsa"); + }); }); describe("Testing", () => { @@ -221,26 +236,16 @@ describe("local", () => { }); describe("Cleaning", () => { - it("clean .eask", async () => { - await ctx.runEask("clean .eask"); - }); - it("clean elc", async () => { - await ctx.runEask("clean elc"); - }); - it("clean dist", async () => { - await ctx.runEask("clean dist"); - }); - it("clean autoloads", async () => { - await ctx.runEask("clean autoloads"); - }); - it("clean pkg-file", async () => { - await ctx.runEask("clean pkg-file"); - }); - it("clean log-file", async () => { - await ctx.runEask("clean log-file"); - }); - it("clean all", async () => { - await ctx.runEask("clean all"); + it.each([ + "clean .eask", + "clean elc", + "clean dist", + "clean autoloads", + "clean pkg-file", + "clean log-file", + "clean all", + ])("eask %s", async (cmd) => { + await ctx.runEask(cmd); }); }); From 687c2bb82d54a78a164d94a475b6a28d89a231dd Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 26 Mar 2025 11:49:17 -0700 Subject: [PATCH 51/70] Move ./test-js to ./test/jest --- {test-js => test/jest}/__snapshots__/analyze.test.js.snap | 0 {test-js => test/jest}/analyze.test.js | 0 {test-js => test/jest}/buttercup.test.js | 0 {test-js => test/jest}/buttercup/.gitignore | 0 {test-js => test/jest}/buttercup/Eask | 0 {test-js => test/jest}/buttercup/test-fail/buttercup-test.el | 0 {test-js => test/jest}/buttercup/test-ok/buttercup-test.el | 0 {test-js => test/jest}/config.test.js | 0 {test-js => test/jest}/config/init.el | 0 {test-js => test/jest}/docker.test.js | 0 {test-js => test/jest}/docker/Eask | 0 {test-js => test/jest}/docker/RADME.md | 0 {test-js => test/jest}/docker/files/mini.pkg.1-1.el | 0 {test-js => test/jest}/docker/files/mini.pkg.1-2.el | 0 {test-js => test/jest}/docker/mini.pkg.1.el | 0 {test-js => test/jest}/dsl/.gitignore | 0 {test-js => test/jest}/dsl/Eask | 0 {test-js => test/jest}/dsl/check-dsl.el | 0 {test-js => test/jest}/ecukes/Eask | 0 {test-js => test/jest}/ecukes/features/foo.feature | 0 .../jest}/ecukes/features/step-definitions/ecukes-steps.el | 0 {test-js => test/jest}/ecukes/features/support/env.el | 0 {test-js => test/jest}/emacs.test.js | 0 {test-js => test/jest}/empty/.gitkeep | 0 {test-js => test/jest}/ert-runner/.gitignore | 0 {test-js => test/jest}/ert-runner/Eask | 0 {test-js => test/jest}/ert-runner/test/ert-runner-test.el | 0 {test-js => test/jest}/ert/.gitignore | 0 {test-js => test/jest}/ert/Eask | 0 {test-js => test/jest}/ert/test-nil-message/ert-test.el | 0 {test-js => test/jest}/ert/test/ert-test.el | 0 {test-js => test/jest}/exec.test.js | 0 {test-js => test/jest}/exec/.gitignore | 0 {test-js => test/jest}/exec/Eask | 0 {test-js => test/jest}/exec/bin/github-elpa.bat | 0 {test-js => test/jest}/exec/exec.el | 0 {test-js => test/jest}/exec/test/test-dummy.el | 0 {test-js => test/jest}/exit-status.test.js | 0 {test-js => test/jest}/global.test.js | 0 {test-js => test/jest}/global/Eask | 0 {test-js => test/jest}/helpers.js | 0 {test-js => test/jest}/helpers.test.js | 0 {test-js => test/jest}/install.test.js | 0 {test-js => test/jest}/install/Eask | 0 {test-js => test/jest}/install/RADME.md | 0 {test-js => test/jest}/install/files/mini.pkg.1-1.el | 0 {test-js => test/jest}/install/files/mini.pkg.1-2.el | 0 {test-js => test/jest}/install/mini.pkg.1.el | 0 {test-js => test/jest}/link.test.js | 0 {test-js => test/jest}/link/.gitkeep | 0 {test-js => test/jest}/link/Eask | 0 {test-js => test/jest}/link/link-fail/Eask | 0 {test-js => test/jest}/link/link-fail/RADME.md | 0 {test-js => test/jest}/link/link-fail/files/mini.pkg.1-1.el | 0 {test-js => test/jest}/link/link-fail/files/mini.pkg.1-2.el | 0 {test-js => test/jest}/link/link-fail/mini.pkg.1.el | 0 {test-js => test/jest}/link/link-to/Eask | 0 {test-js => test/jest}/link/link-to/link-to.el | 0 {test-js => test/jest}/local.test.js | 0 {test-js => test/jest}/local/Eask | 0 {test-js => test/jest}/local/RADME.md | 0 {test-js => test/jest}/local/files/mini.pkg.1-1.el | 0 {test-js => test/jest}/local/files/mini.pkg.1-2.el | 0 {test-js => test/jest}/local/mini.pkg.1.el | 0 {test-js => test/jest}/metadata/.gitignore | 0 {test-js => test/jest}/metadata/Eask | 0 {test-js => test/jest}/metadata/check-metadata.el | 0 {test-js => test/jest}/mini.pkg.1/Eask | 0 {test-js => test/jest}/mini.pkg.1/RADME.md | 0 {test-js => test/jest}/mini.pkg.1/files/mini.pkg.1-1.el | 0 {test-js => test/jest}/mini.pkg.1/files/mini.pkg.1-2.el | 0 {test-js => test/jest}/mini.pkg.1/mini.pkg.1.el | 0 {test-js => test/jest}/options.test.js | 0 {test-js => test/jest}/options/.gitignore | 0 {test-js => test/jest}/options/Eask | 0 {test-js => test/jest}/outdated.test.js | 0 {test-js => test/jest}/outdated_upgrade/.gitignore | 0 {test-js => test/jest}/outdated_upgrade/Eask | 0 {test-js => test/jest}/outdated_upgrade/make-outdate.el | 0 {test-js => test/jest}/search.test.js | 0 {test-js => test/jest}/search/.gitignore | 0 {test-js => test/jest}/search/Eask | 0 {test-js => test/jest}/test-ecukes.test.js | 0 {test-js => test/jest}/test-ert-runner.test.js | 0 {test-js => test/jest}/test-ert.test.js | 0 {test-js => test/jest}/upgrade-eask.test.js | 0 86 files changed, 0 insertions(+), 0 deletions(-) rename {test-js => test/jest}/__snapshots__/analyze.test.js.snap (100%) rename {test-js => test/jest}/analyze.test.js (100%) rename {test-js => test/jest}/buttercup.test.js (100%) rename {test-js => test/jest}/buttercup/.gitignore (100%) rename {test-js => test/jest}/buttercup/Eask (100%) rename {test-js => test/jest}/buttercup/test-fail/buttercup-test.el (100%) rename {test-js => test/jest}/buttercup/test-ok/buttercup-test.el (100%) rename {test-js => test/jest}/config.test.js (100%) rename {test-js => test/jest}/config/init.el (100%) rename {test-js => test/jest}/docker.test.js (100%) rename {test-js => test/jest}/docker/Eask (100%) rename {test-js => test/jest}/docker/RADME.md (100%) rename {test-js => test/jest}/docker/files/mini.pkg.1-1.el (100%) rename {test-js => test/jest}/docker/files/mini.pkg.1-2.el (100%) rename {test-js => test/jest}/docker/mini.pkg.1.el (100%) rename {test-js => test/jest}/dsl/.gitignore (100%) rename {test-js => test/jest}/dsl/Eask (100%) rename {test-js => test/jest}/dsl/check-dsl.el (100%) rename {test-js => test/jest}/ecukes/Eask (100%) rename {test-js => test/jest}/ecukes/features/foo.feature (100%) rename {test-js => test/jest}/ecukes/features/step-definitions/ecukes-steps.el (100%) rename {test-js => test/jest}/ecukes/features/support/env.el (100%) rename {test-js => test/jest}/emacs.test.js (100%) rename {test-js => test/jest}/empty/.gitkeep (100%) rename {test-js => test/jest}/ert-runner/.gitignore (100%) rename {test-js => test/jest}/ert-runner/Eask (100%) rename {test-js => test/jest}/ert-runner/test/ert-runner-test.el (100%) rename {test-js => test/jest}/ert/.gitignore (100%) rename {test-js => test/jest}/ert/Eask (100%) rename {test-js => test/jest}/ert/test-nil-message/ert-test.el (100%) rename {test-js => test/jest}/ert/test/ert-test.el (100%) rename {test-js => test/jest}/exec.test.js (100%) rename {test-js => test/jest}/exec/.gitignore (100%) rename {test-js => test/jest}/exec/Eask (100%) rename {test-js => test/jest}/exec/bin/github-elpa.bat (100%) rename {test-js => test/jest}/exec/exec.el (100%) rename {test-js => test/jest}/exec/test/test-dummy.el (100%) rename {test-js => test/jest}/exit-status.test.js (100%) rename {test-js => test/jest}/global.test.js (100%) rename {test-js => test/jest}/global/Eask (100%) rename {test-js => test/jest}/helpers.js (100%) rename {test-js => test/jest}/helpers.test.js (100%) rename {test-js => test/jest}/install.test.js (100%) rename {test-js => test/jest}/install/Eask (100%) rename {test-js => test/jest}/install/RADME.md (100%) rename {test-js => test/jest}/install/files/mini.pkg.1-1.el (100%) rename {test-js => test/jest}/install/files/mini.pkg.1-2.el (100%) rename {test-js => test/jest}/install/mini.pkg.1.el (100%) rename {test-js => test/jest}/link.test.js (100%) rename {test-js => test/jest}/link/.gitkeep (100%) rename {test-js => test/jest}/link/Eask (100%) rename {test-js => test/jest}/link/link-fail/Eask (100%) rename {test-js => test/jest}/link/link-fail/RADME.md (100%) rename {test-js => test/jest}/link/link-fail/files/mini.pkg.1-1.el (100%) rename {test-js => test/jest}/link/link-fail/files/mini.pkg.1-2.el (100%) rename {test-js => test/jest}/link/link-fail/mini.pkg.1.el (100%) rename {test-js => test/jest}/link/link-to/Eask (100%) rename {test-js => test/jest}/link/link-to/link-to.el (100%) rename {test-js => test/jest}/local.test.js (100%) rename {test-js => test/jest}/local/Eask (100%) rename {test-js => test/jest}/local/RADME.md (100%) rename {test-js => test/jest}/local/files/mini.pkg.1-1.el (100%) rename {test-js => test/jest}/local/files/mini.pkg.1-2.el (100%) rename {test-js => test/jest}/local/mini.pkg.1.el (100%) rename {test-js => test/jest}/metadata/.gitignore (100%) rename {test-js => test/jest}/metadata/Eask (100%) rename {test-js => test/jest}/metadata/check-metadata.el (100%) rename {test-js => test/jest}/mini.pkg.1/Eask (100%) rename {test-js => test/jest}/mini.pkg.1/RADME.md (100%) rename {test-js => test/jest}/mini.pkg.1/files/mini.pkg.1-1.el (100%) rename {test-js => test/jest}/mini.pkg.1/files/mini.pkg.1-2.el (100%) rename {test-js => test/jest}/mini.pkg.1/mini.pkg.1.el (100%) rename {test-js => test/jest}/options.test.js (100%) rename {test-js => test/jest}/options/.gitignore (100%) rename {test-js => test/jest}/options/Eask (100%) rename {test-js => test/jest}/outdated.test.js (100%) rename {test-js => test/jest}/outdated_upgrade/.gitignore (100%) rename {test-js => test/jest}/outdated_upgrade/Eask (100%) rename {test-js => test/jest}/outdated_upgrade/make-outdate.el (100%) rename {test-js => test/jest}/search.test.js (100%) rename {test-js => test/jest}/search/.gitignore (100%) rename {test-js => test/jest}/search/Eask (100%) rename {test-js => test/jest}/test-ecukes.test.js (100%) rename {test-js => test/jest}/test-ert-runner.test.js (100%) rename {test-js => test/jest}/test-ert.test.js (100%) rename {test-js => test/jest}/upgrade-eask.test.js (100%) diff --git a/test-js/__snapshots__/analyze.test.js.snap b/test/jest/__snapshots__/analyze.test.js.snap similarity index 100% rename from test-js/__snapshots__/analyze.test.js.snap rename to test/jest/__snapshots__/analyze.test.js.snap diff --git a/test-js/analyze.test.js b/test/jest/analyze.test.js similarity index 100% rename from test-js/analyze.test.js rename to test/jest/analyze.test.js diff --git a/test-js/buttercup.test.js b/test/jest/buttercup.test.js similarity index 100% rename from test-js/buttercup.test.js rename to test/jest/buttercup.test.js diff --git a/test-js/buttercup/.gitignore b/test/jest/buttercup/.gitignore similarity index 100% rename from test-js/buttercup/.gitignore rename to test/jest/buttercup/.gitignore diff --git a/test-js/buttercup/Eask b/test/jest/buttercup/Eask similarity index 100% rename from test-js/buttercup/Eask rename to test/jest/buttercup/Eask diff --git a/test-js/buttercup/test-fail/buttercup-test.el b/test/jest/buttercup/test-fail/buttercup-test.el similarity index 100% rename from test-js/buttercup/test-fail/buttercup-test.el rename to test/jest/buttercup/test-fail/buttercup-test.el diff --git a/test-js/buttercup/test-ok/buttercup-test.el b/test/jest/buttercup/test-ok/buttercup-test.el similarity index 100% rename from test-js/buttercup/test-ok/buttercup-test.el rename to test/jest/buttercup/test-ok/buttercup-test.el diff --git a/test-js/config.test.js b/test/jest/config.test.js similarity index 100% rename from test-js/config.test.js rename to test/jest/config.test.js diff --git a/test-js/config/init.el b/test/jest/config/init.el similarity index 100% rename from test-js/config/init.el rename to test/jest/config/init.el diff --git a/test-js/docker.test.js b/test/jest/docker.test.js similarity index 100% rename from test-js/docker.test.js rename to test/jest/docker.test.js diff --git a/test-js/docker/Eask b/test/jest/docker/Eask similarity index 100% rename from test-js/docker/Eask rename to test/jest/docker/Eask diff --git a/test-js/docker/RADME.md b/test/jest/docker/RADME.md similarity index 100% rename from test-js/docker/RADME.md rename to test/jest/docker/RADME.md diff --git a/test-js/docker/files/mini.pkg.1-1.el b/test/jest/docker/files/mini.pkg.1-1.el similarity index 100% rename from test-js/docker/files/mini.pkg.1-1.el rename to test/jest/docker/files/mini.pkg.1-1.el diff --git a/test-js/docker/files/mini.pkg.1-2.el b/test/jest/docker/files/mini.pkg.1-2.el similarity index 100% rename from test-js/docker/files/mini.pkg.1-2.el rename to test/jest/docker/files/mini.pkg.1-2.el diff --git a/test-js/docker/mini.pkg.1.el b/test/jest/docker/mini.pkg.1.el similarity index 100% rename from test-js/docker/mini.pkg.1.el rename to test/jest/docker/mini.pkg.1.el diff --git a/test-js/dsl/.gitignore b/test/jest/dsl/.gitignore similarity index 100% rename from test-js/dsl/.gitignore rename to test/jest/dsl/.gitignore diff --git a/test-js/dsl/Eask b/test/jest/dsl/Eask similarity index 100% rename from test-js/dsl/Eask rename to test/jest/dsl/Eask diff --git a/test-js/dsl/check-dsl.el b/test/jest/dsl/check-dsl.el similarity index 100% rename from test-js/dsl/check-dsl.el rename to test/jest/dsl/check-dsl.el diff --git a/test-js/ecukes/Eask b/test/jest/ecukes/Eask similarity index 100% rename from test-js/ecukes/Eask rename to test/jest/ecukes/Eask diff --git a/test-js/ecukes/features/foo.feature b/test/jest/ecukes/features/foo.feature similarity index 100% rename from test-js/ecukes/features/foo.feature rename to test/jest/ecukes/features/foo.feature diff --git a/test-js/ecukes/features/step-definitions/ecukes-steps.el b/test/jest/ecukes/features/step-definitions/ecukes-steps.el similarity index 100% rename from test-js/ecukes/features/step-definitions/ecukes-steps.el rename to test/jest/ecukes/features/step-definitions/ecukes-steps.el diff --git a/test-js/ecukes/features/support/env.el b/test/jest/ecukes/features/support/env.el similarity index 100% rename from test-js/ecukes/features/support/env.el rename to test/jest/ecukes/features/support/env.el diff --git a/test-js/emacs.test.js b/test/jest/emacs.test.js similarity index 100% rename from test-js/emacs.test.js rename to test/jest/emacs.test.js diff --git a/test-js/empty/.gitkeep b/test/jest/empty/.gitkeep similarity index 100% rename from test-js/empty/.gitkeep rename to test/jest/empty/.gitkeep diff --git a/test-js/ert-runner/.gitignore b/test/jest/ert-runner/.gitignore similarity index 100% rename from test-js/ert-runner/.gitignore rename to test/jest/ert-runner/.gitignore diff --git a/test-js/ert-runner/Eask b/test/jest/ert-runner/Eask similarity index 100% rename from test-js/ert-runner/Eask rename to test/jest/ert-runner/Eask diff --git a/test-js/ert-runner/test/ert-runner-test.el b/test/jest/ert-runner/test/ert-runner-test.el similarity index 100% rename from test-js/ert-runner/test/ert-runner-test.el rename to test/jest/ert-runner/test/ert-runner-test.el diff --git a/test-js/ert/.gitignore b/test/jest/ert/.gitignore similarity index 100% rename from test-js/ert/.gitignore rename to test/jest/ert/.gitignore diff --git a/test-js/ert/Eask b/test/jest/ert/Eask similarity index 100% rename from test-js/ert/Eask rename to test/jest/ert/Eask diff --git a/test-js/ert/test-nil-message/ert-test.el b/test/jest/ert/test-nil-message/ert-test.el similarity index 100% rename from test-js/ert/test-nil-message/ert-test.el rename to test/jest/ert/test-nil-message/ert-test.el diff --git a/test-js/ert/test/ert-test.el b/test/jest/ert/test/ert-test.el similarity index 100% rename from test-js/ert/test/ert-test.el rename to test/jest/ert/test/ert-test.el diff --git a/test-js/exec.test.js b/test/jest/exec.test.js similarity index 100% rename from test-js/exec.test.js rename to test/jest/exec.test.js diff --git a/test-js/exec/.gitignore b/test/jest/exec/.gitignore similarity index 100% rename from test-js/exec/.gitignore rename to test/jest/exec/.gitignore diff --git a/test-js/exec/Eask b/test/jest/exec/Eask similarity index 100% rename from test-js/exec/Eask rename to test/jest/exec/Eask diff --git a/test-js/exec/bin/github-elpa.bat b/test/jest/exec/bin/github-elpa.bat similarity index 100% rename from test-js/exec/bin/github-elpa.bat rename to test/jest/exec/bin/github-elpa.bat diff --git a/test-js/exec/exec.el b/test/jest/exec/exec.el similarity index 100% rename from test-js/exec/exec.el rename to test/jest/exec/exec.el diff --git a/test-js/exec/test/test-dummy.el b/test/jest/exec/test/test-dummy.el similarity index 100% rename from test-js/exec/test/test-dummy.el rename to test/jest/exec/test/test-dummy.el diff --git a/test-js/exit-status.test.js b/test/jest/exit-status.test.js similarity index 100% rename from test-js/exit-status.test.js rename to test/jest/exit-status.test.js diff --git a/test-js/global.test.js b/test/jest/global.test.js similarity index 100% rename from test-js/global.test.js rename to test/jest/global.test.js diff --git a/test-js/global/Eask b/test/jest/global/Eask similarity index 100% rename from test-js/global/Eask rename to test/jest/global/Eask diff --git a/test-js/helpers.js b/test/jest/helpers.js similarity index 100% rename from test-js/helpers.js rename to test/jest/helpers.js diff --git a/test-js/helpers.test.js b/test/jest/helpers.test.js similarity index 100% rename from test-js/helpers.test.js rename to test/jest/helpers.test.js diff --git a/test-js/install.test.js b/test/jest/install.test.js similarity index 100% rename from test-js/install.test.js rename to test/jest/install.test.js diff --git a/test-js/install/Eask b/test/jest/install/Eask similarity index 100% rename from test-js/install/Eask rename to test/jest/install/Eask diff --git a/test-js/install/RADME.md b/test/jest/install/RADME.md similarity index 100% rename from test-js/install/RADME.md rename to test/jest/install/RADME.md diff --git a/test-js/install/files/mini.pkg.1-1.el b/test/jest/install/files/mini.pkg.1-1.el similarity index 100% rename from test-js/install/files/mini.pkg.1-1.el rename to test/jest/install/files/mini.pkg.1-1.el diff --git a/test-js/install/files/mini.pkg.1-2.el b/test/jest/install/files/mini.pkg.1-2.el similarity index 100% rename from test-js/install/files/mini.pkg.1-2.el rename to test/jest/install/files/mini.pkg.1-2.el diff --git a/test-js/install/mini.pkg.1.el b/test/jest/install/mini.pkg.1.el similarity index 100% rename from test-js/install/mini.pkg.1.el rename to test/jest/install/mini.pkg.1.el diff --git a/test-js/link.test.js b/test/jest/link.test.js similarity index 100% rename from test-js/link.test.js rename to test/jest/link.test.js diff --git a/test-js/link/.gitkeep b/test/jest/link/.gitkeep similarity index 100% rename from test-js/link/.gitkeep rename to test/jest/link/.gitkeep diff --git a/test-js/link/Eask b/test/jest/link/Eask similarity index 100% rename from test-js/link/Eask rename to test/jest/link/Eask diff --git a/test-js/link/link-fail/Eask b/test/jest/link/link-fail/Eask similarity index 100% rename from test-js/link/link-fail/Eask rename to test/jest/link/link-fail/Eask diff --git a/test-js/link/link-fail/RADME.md b/test/jest/link/link-fail/RADME.md similarity index 100% rename from test-js/link/link-fail/RADME.md rename to test/jest/link/link-fail/RADME.md diff --git a/test-js/link/link-fail/files/mini.pkg.1-1.el b/test/jest/link/link-fail/files/mini.pkg.1-1.el similarity index 100% rename from test-js/link/link-fail/files/mini.pkg.1-1.el rename to test/jest/link/link-fail/files/mini.pkg.1-1.el diff --git a/test-js/link/link-fail/files/mini.pkg.1-2.el b/test/jest/link/link-fail/files/mini.pkg.1-2.el similarity index 100% rename from test-js/link/link-fail/files/mini.pkg.1-2.el rename to test/jest/link/link-fail/files/mini.pkg.1-2.el diff --git a/test-js/link/link-fail/mini.pkg.1.el b/test/jest/link/link-fail/mini.pkg.1.el similarity index 100% rename from test-js/link/link-fail/mini.pkg.1.el rename to test/jest/link/link-fail/mini.pkg.1.el diff --git a/test-js/link/link-to/Eask b/test/jest/link/link-to/Eask similarity index 100% rename from test-js/link/link-to/Eask rename to test/jest/link/link-to/Eask diff --git a/test-js/link/link-to/link-to.el b/test/jest/link/link-to/link-to.el similarity index 100% rename from test-js/link/link-to/link-to.el rename to test/jest/link/link-to/link-to.el diff --git a/test-js/local.test.js b/test/jest/local.test.js similarity index 100% rename from test-js/local.test.js rename to test/jest/local.test.js diff --git a/test-js/local/Eask b/test/jest/local/Eask similarity index 100% rename from test-js/local/Eask rename to test/jest/local/Eask diff --git a/test-js/local/RADME.md b/test/jest/local/RADME.md similarity index 100% rename from test-js/local/RADME.md rename to test/jest/local/RADME.md diff --git a/test-js/local/files/mini.pkg.1-1.el b/test/jest/local/files/mini.pkg.1-1.el similarity index 100% rename from test-js/local/files/mini.pkg.1-1.el rename to test/jest/local/files/mini.pkg.1-1.el diff --git a/test-js/local/files/mini.pkg.1-2.el b/test/jest/local/files/mini.pkg.1-2.el similarity index 100% rename from test-js/local/files/mini.pkg.1-2.el rename to test/jest/local/files/mini.pkg.1-2.el diff --git a/test-js/local/mini.pkg.1.el b/test/jest/local/mini.pkg.1.el similarity index 100% rename from test-js/local/mini.pkg.1.el rename to test/jest/local/mini.pkg.1.el diff --git a/test-js/metadata/.gitignore b/test/jest/metadata/.gitignore similarity index 100% rename from test-js/metadata/.gitignore rename to test/jest/metadata/.gitignore diff --git a/test-js/metadata/Eask b/test/jest/metadata/Eask similarity index 100% rename from test-js/metadata/Eask rename to test/jest/metadata/Eask diff --git a/test-js/metadata/check-metadata.el b/test/jest/metadata/check-metadata.el similarity index 100% rename from test-js/metadata/check-metadata.el rename to test/jest/metadata/check-metadata.el diff --git a/test-js/mini.pkg.1/Eask b/test/jest/mini.pkg.1/Eask similarity index 100% rename from test-js/mini.pkg.1/Eask rename to test/jest/mini.pkg.1/Eask diff --git a/test-js/mini.pkg.1/RADME.md b/test/jest/mini.pkg.1/RADME.md similarity index 100% rename from test-js/mini.pkg.1/RADME.md rename to test/jest/mini.pkg.1/RADME.md diff --git a/test-js/mini.pkg.1/files/mini.pkg.1-1.el b/test/jest/mini.pkg.1/files/mini.pkg.1-1.el similarity index 100% rename from test-js/mini.pkg.1/files/mini.pkg.1-1.el rename to test/jest/mini.pkg.1/files/mini.pkg.1-1.el diff --git a/test-js/mini.pkg.1/files/mini.pkg.1-2.el b/test/jest/mini.pkg.1/files/mini.pkg.1-2.el similarity index 100% rename from test-js/mini.pkg.1/files/mini.pkg.1-2.el rename to test/jest/mini.pkg.1/files/mini.pkg.1-2.el diff --git a/test-js/mini.pkg.1/mini.pkg.1.el b/test/jest/mini.pkg.1/mini.pkg.1.el similarity index 100% rename from test-js/mini.pkg.1/mini.pkg.1.el rename to test/jest/mini.pkg.1/mini.pkg.1.el diff --git a/test-js/options.test.js b/test/jest/options.test.js similarity index 100% rename from test-js/options.test.js rename to test/jest/options.test.js diff --git a/test-js/options/.gitignore b/test/jest/options/.gitignore similarity index 100% rename from test-js/options/.gitignore rename to test/jest/options/.gitignore diff --git a/test-js/options/Eask b/test/jest/options/Eask similarity index 100% rename from test-js/options/Eask rename to test/jest/options/Eask diff --git a/test-js/outdated.test.js b/test/jest/outdated.test.js similarity index 100% rename from test-js/outdated.test.js rename to test/jest/outdated.test.js diff --git a/test-js/outdated_upgrade/.gitignore b/test/jest/outdated_upgrade/.gitignore similarity index 100% rename from test-js/outdated_upgrade/.gitignore rename to test/jest/outdated_upgrade/.gitignore diff --git a/test-js/outdated_upgrade/Eask b/test/jest/outdated_upgrade/Eask similarity index 100% rename from test-js/outdated_upgrade/Eask rename to test/jest/outdated_upgrade/Eask diff --git a/test-js/outdated_upgrade/make-outdate.el b/test/jest/outdated_upgrade/make-outdate.el similarity index 100% rename from test-js/outdated_upgrade/make-outdate.el rename to test/jest/outdated_upgrade/make-outdate.el diff --git a/test-js/search.test.js b/test/jest/search.test.js similarity index 100% rename from test-js/search.test.js rename to test/jest/search.test.js diff --git a/test-js/search/.gitignore b/test/jest/search/.gitignore similarity index 100% rename from test-js/search/.gitignore rename to test/jest/search/.gitignore diff --git a/test-js/search/Eask b/test/jest/search/Eask similarity index 100% rename from test-js/search/Eask rename to test/jest/search/Eask diff --git a/test-js/test-ecukes.test.js b/test/jest/test-ecukes.test.js similarity index 100% rename from test-js/test-ecukes.test.js rename to test/jest/test-ecukes.test.js diff --git a/test-js/test-ert-runner.test.js b/test/jest/test-ert-runner.test.js similarity index 100% rename from test-js/test-ert-runner.test.js rename to test/jest/test-ert-runner.test.js diff --git a/test-js/test-ert.test.js b/test/jest/test-ert.test.js similarity index 100% rename from test-js/test-ert.test.js rename to test/jest/test-ert.test.js diff --git a/test-js/upgrade-eask.test.js b/test/jest/upgrade-eask.test.js similarity index 100% rename from test-js/upgrade-eask.test.js rename to test/jest/upgrade-eask.test.js From 0eab96e3d56cab60f58ae986b0cf3691d59a7d43 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 26 Mar 2025 11:59:50 -0700 Subject: [PATCH 52/70] Update local patch test-js => test/jest --- docs/content/Contributing/Testing/_index.en.md | 2 +- package.json | 4 ++-- test/jest/analyze.test.js | 6 +++--- test/jest/buttercup.test.js | 2 +- test/jest/config.test.js | 2 +- test/jest/docker.test.js | 2 +- test/jest/emacs.test.js | 2 +- test/jest/exec.test.js | 2 +- test/jest/exit-status.test.js | 4 +--- test/jest/global.test.js | 2 +- test/jest/helpers.test.js | 16 ++++++++-------- test/jest/install.test.js | 4 ++-- test/jest/link.test.js | 4 ++-- test/jest/local.test.js | 2 +- test/jest/options.test.js | 2 +- test/jest/outdated.test.js | 2 +- test/jest/search.test.js | 2 +- test/jest/test-ecukes.test.js | 2 +- test/jest/test-ert-runner.test.js | 2 +- test/jest/test-ert.test.js | 2 +- 20 files changed, 32 insertions(+), 34 deletions(-) diff --git a/docs/content/Contributing/Testing/_index.en.md b/docs/content/Contributing/Testing/_index.en.md index 7b22e943..2f8042f4 100644 --- a/docs/content/Contributing/Testing/_index.en.md +++ b/docs/content/Contributing/Testing/_index.en.md @@ -61,7 +61,7 @@ If you use it, make sure to run `eask clean all` before your tests. const { TestContext } = require("./helpers"); describe("emacs", () => { - const ctx = new TestContext("./test-js/empty"); + const ctx = new TestContext("./test/jest/empty"); beforeAll(async () => await ctx.runEask("clean all")); afterAll(() => ctx.cleanUp); diff --git a/package.json b/package.json index 9c4f296a..796ff478 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "test-docker": "env ALLOW_UNSAFE=1 jest", "test-debug": "env DEBUG=1 jest", "test": "jest", - "test-reset": "rm -rf ./test-js/.eask ./test-js/*/.eask; git restore ./test-js/*/", + "test-reset": "rm -rf ./test/jest/.eask ./test/jest/*/.eask; git restore ./test/jest/*/", "pkg-all": "pkg package.json", "pkg-linux-arm64": "pkg package.json -t node*-linuxstatic-arm64 --output dist/eask --public", "pkg-linux-x64": "pkg package.json -t node*-linuxstatic-x64 --output dist/eask --public", @@ -40,7 +40,7 @@ "jest": "^29.7.0" }, "jest": { - "rootDir": "./test-js", + "rootDir": "./test/jest", "testTimeout": 40000 }, "files": [ diff --git a/test/jest/analyze.test.js b/test/jest/analyze.test.js index c373733d..cef00035 100644 --- a/test/jest/analyze.test.js +++ b/test/jest/analyze.test.js @@ -2,7 +2,7 @@ const { TestContext } = require("./helpers"); describe("analyze", () => { describe("in ./dsl", () => { - const ctx = new TestContext("./test-js/dsl"); + const ctx = new TestContext("./test/jest/dsl"); it("handles plain text", async () => { await ctx.runEask("analyze"); @@ -31,7 +31,7 @@ describe("analyze", () => { }); describe("in ./empty", () => { - const ctx = new TestContext("./test-js/empty"); + const ctx = new TestContext("./test/jest/empty"); it("should error", async () => { await expect(ctx.runEask("analyze")).rejects.toThrow(); @@ -39,7 +39,7 @@ describe("analyze", () => { }); describe("in ./metadata", () => { - const ctx = new TestContext("./test-js/metadata"); + const ctx = new TestContext("./test/jest/metadata"); it("handles plain text", async () => { await ctx.runEask("analyze"); diff --git a/test/jest/buttercup.test.js b/test/jest/buttercup.test.js index 45b56df1..7b7293de 100644 --- a/test/jest/buttercup.test.js +++ b/test/jest/buttercup.test.js @@ -1,7 +1,7 @@ const { TestContext } = require("./helpers"); describe("buttercup", () => { - const ctx = new TestContext("./test-js/buttercup"); + const ctx = new TestContext("./test/jest/buttercup"); beforeAll(async () => await ctx.runEask("install-deps --dev")); diff --git a/test/jest/config.test.js b/test/jest/config.test.js index 9b784171..afe47f85 100644 --- a/test/jest/config.test.js +++ b/test/jest/config.test.js @@ -39,7 +39,7 @@ describe("config param", () => { // copy init.el from fixtures // it must enable sources for the installed packages await fs.copyFile( - "./test-js/config/init.el", + "./test/jest/config/init.el", path.join(process.env.HOME, "/.emacs.d/init.el"), ); await ctx.runEask("install -c spinner ivy beacon company-fuzzy"); diff --git a/test/jest/docker.test.js b/test/jest/docker.test.js index 273a19ef..0a95c079 100644 --- a/test/jest/docker.test.js +++ b/test/jest/docker.test.js @@ -1,7 +1,7 @@ const { TestContext } = require("./helpers"); describe("docker", () => { - const ctx = new TestContext("./test-js/docker"); + const ctx = new TestContext("./test/jest/docker"); afterAll(() => ctx.cleanUp()); diff --git a/test/jest/emacs.test.js b/test/jest/emacs.test.js index cdb73726..d35d9252 100644 --- a/test/jest/emacs.test.js +++ b/test/jest/emacs.test.js @@ -1,7 +1,7 @@ const { TestContext } = require("./helpers"); describe("emacs", () => { - const ctx = new TestContext("./test-js/empty"); + const ctx = new TestContext("./test/jest/empty"); beforeAll(async () => await ctx.runEask("clean all")); diff --git a/test/jest/exec.test.js b/test/jest/exec.test.js index 8e903694..2ff26bf3 100644 --- a/test/jest/exec.test.js +++ b/test/jest/exec.test.js @@ -1,7 +1,7 @@ const { TestContext } = require("./helpers"); describe("exec", () => { - const ctx = new TestContext("./test-js/exec"); + const ctx = new TestContext("./test/jest/exec"); beforeAll(async () => await ctx.runEask("install-deps")); diff --git a/test/jest/exit-status.test.js b/test/jest/exit-status.test.js index c55ce699..f028d0af 100644 --- a/test/jest/exit-status.test.js +++ b/test/jest/exit-status.test.js @@ -1,9 +1,7 @@ const { TestContext } = require("./helpers"); describe("exit-status", () => { - const ctx = new TestContext("./test-js/empty"); - - // beforeAll(async () => await ctx.runEask("install-deps"), 10000); + const ctx = new TestContext("./test/jest/empty"); afterAll(() => ctx.cleanUp()); diff --git a/test/jest/global.test.js b/test/jest/global.test.js index a68c9875..3b7bda06 100644 --- a/test/jest/global.test.js +++ b/test/jest/global.test.js @@ -31,7 +31,7 @@ describe("global", () => { // add a global Easkfile if (process.env.ALLOW_UNSAFE) { await fs.copyFile( - "./test-js/global/Eask", + "./test/jest/global/Eask", path.join(process.env.HOME, "Eask"), ); } diff --git a/test/jest/helpers.test.js b/test/jest/helpers.test.js index ae82aa81..888017a7 100644 --- a/test/jest/helpers.test.js +++ b/test/jest/helpers.test.js @@ -3,32 +3,32 @@ const path = require("node:path"); describe("CommandOutput", () => { describe("sanitizeString", () => { - let out = new CommandOutput({}, "./test-js"); + let out = new CommandOutput({}, "./test/jest"); it("replaces relative paths", () => { - let res = out.sanitizeString("look at ./test-js/foo.js"); + let res = out.sanitizeString("look at ./test/jest/foo.js"); expect(res).toBe("look at ~/foo.js"); }); it("replaces relative path literally", () => { - let res = out.sanitizeString("look at a/test-js/foo.js"); - expect(res).toBe("look at a/test-js/foo.js"); + let res = out.sanitizeString("look at a/test/jest/foo.js"); + expect(res).toBe("look at a/test/jest/foo.js"); }); it("replaces absolute paths", () => { let res = out.sanitizeString( - `look at ${path.resolve("./test-js", "foo.js")}`, + `look at ${path.resolve("./test/jest", "foo.js")}`, ); expect(res).toBe(`look at ${path.join("~", "foo.js")}`); }); it("replaces windows formatted paths", () => { - let out = new CommandOutput({}, "./test-js/options"); + let out = new CommandOutput({}, "./test/jest/options"); // force a windows style path - out.cwdAbsolute = "D:\\a\\cli\\cli\\test-js\\options"; + out.cwdAbsolute = "D:\\a\\cli\\cli\\test/jest\\options"; // when on windows Eask translates those paths like let res = out.sanitizeString( - "d:/a/cli/cli/test-js/options/Eask:7:18 Error: Multiple definition of `package'", + "d:/a/cli/cli/test/jest/options/Eask:7:18 Error: Multiple definition of `package'", ); expect(res).toBe("~/Eask:7:18 Error: Multiple definition of `package'"); }); diff --git a/test/jest/install.test.js b/test/jest/install.test.js index 5e5159dd..8883da4b 100644 --- a/test/jest/install.test.js +++ b/test/jest/install.test.js @@ -2,7 +2,7 @@ const { TestContext } = require("./helpers"); describe("install and uninstall", () => { describe("in ./install", () => { - const ctx = new TestContext("./test-js/install/"); + const ctx = new TestContext("./test/jest/install/"); const packageName = "mini.pkg.1"; beforeAll(async () => { @@ -44,7 +44,7 @@ describe("install and uninstall", () => { }); describe("in an empty project", () => { - const ctx = new TestContext("./test-js/empty"); + const ctx = new TestContext("./test/jest/empty"); beforeAll(async () => await ctx.runEask("clean all")); afterAll(() => ctx.cleanUp()); diff --git a/test/jest/link.test.js b/test/jest/link.test.js index 845880af..04633991 100644 --- a/test/jest/link.test.js +++ b/test/jest/link.test.js @@ -2,7 +2,7 @@ const { TestContext } = require("./helpers"); describe("link", () => { describe("in ./link", () => { - const ctx = new TestContext("./test-js/link"); + const ctx = new TestContext("./test/jest/link"); beforeAll(async () => { await ctx.runEask("clean workspace"); @@ -86,7 +86,7 @@ describe("link", () => { }); describe("in an empty directory", () => { - const ctx = new TestContext("./test-js/empty"); + const ctx = new TestContext("./test/jest/empty"); beforeAll(async () => { await ctx.runEask("clean all"); diff --git a/test/jest/local.test.js b/test/jest/local.test.js index 4127dcbc..99daa14c 100644 --- a/test/jest/local.test.js +++ b/test/jest/local.test.js @@ -7,7 +7,7 @@ const { emacsVersion, TestContext } = require("./helpers"); describe("local", () => { - const cwd = "./test-js/local"; + const cwd = "./test/jest/local"; const ctx = new TestContext(cwd); // NOTE: install-deps takes a long time in this package diff --git a/test/jest/options.test.js b/test/jest/options.test.js index 7069b0ac..bcc97e0b 100644 --- a/test/jest/options.test.js +++ b/test/jest/options.test.js @@ -1,7 +1,7 @@ const { TestContext } = require("./helpers"); describe("options", () => { - const ctx = new TestContext("./test-js/options"); + const ctx = new TestContext("./test/jest/options"); describe("eask info errors", () => { const ctx = new TestContext(process.env.HOME); diff --git a/test/jest/outdated.test.js b/test/jest/outdated.test.js index 97565e9c..39dc934b 100644 --- a/test/jest/outdated.test.js +++ b/test/jest/outdated.test.js @@ -1,7 +1,7 @@ const { TestContext } = require("./helpers"); describe("outdated and upgrade", () => { - const ctx = new TestContext("./test-js/outdated_upgrade"); + const ctx = new TestContext("./test/jest/outdated_upgrade"); beforeAll(async () => { await ctx.runEask("install-deps"); diff --git a/test/jest/search.test.js b/test/jest/search.test.js index 2c1d64f1..b1a158e9 100644 --- a/test/jest/search.test.js +++ b/test/jest/search.test.js @@ -1,7 +1,7 @@ const { TestContext } = require("./helpers"); describe("search", () => { - const cwd = "./test-js/search"; + const cwd = "./test/jest/search"; const ctx = new TestContext(cwd); test("eask search company", async () => { diff --git a/test/jest/test-ecukes.test.js b/test/jest/test-ecukes.test.js index 952fdcc0..4a525b2f 100644 --- a/test/jest/test-ecukes.test.js +++ b/test/jest/test-ecukes.test.js @@ -1,7 +1,7 @@ const { TestContext } = require("./helpers"); describe("test_ecukes", () => { - const ctx = new TestContext("./test-js/ecukes"); + const ctx = new TestContext("./test/jest/ecukes"); beforeAll(async () => await ctx.runEask("install-deps --dev")); afterAll(() => ctx.cleanUp()); diff --git a/test/jest/test-ert-runner.test.js b/test/jest/test-ert-runner.test.js index 0b4ded07..c40486b0 100644 --- a/test/jest/test-ert-runner.test.js +++ b/test/jest/test-ert-runner.test.js @@ -1,7 +1,7 @@ const { TestContext } = require("./helpers"); describe("test ert-runner", () => { - const ctx = new TestContext("./test-js/ert-runner"); + const ctx = new TestContext("./test/jest/ert-runner"); beforeAll(async () => await ctx.runEask("install-deps --dev")); diff --git a/test/jest/test-ert.test.js b/test/jest/test-ert.test.js index c811301a..c44a8697 100644 --- a/test/jest/test-ert.test.js +++ b/test/jest/test-ert.test.js @@ -1,7 +1,7 @@ const { TestContext } = require("./helpers"); describe("test-ert", () => { - const ctx = new TestContext("./test-js/ert"); + const ctx = new TestContext("./test/jest/ert"); afterAll(() => ctx.cleanUp()); From 670c571bf7355451de6f5f4a407f7ae92520fc39 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 26 Mar 2025 17:55:30 -0700 Subject: [PATCH 53/70] Increase docker.test.js timeout --- test/jest/docker.test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/jest/docker.test.js b/test/jest/docker.test.js index 0a95c079..3d122a76 100644 --- a/test/jest/docker.test.js +++ b/test/jest/docker.test.js @@ -1,11 +1,14 @@ const { TestContext } = require("./helpers"); +jest.setTimeout(60000); + describe("docker", () => { const ctx = new TestContext("./test/jest/docker"); afterAll(() => ctx.cleanUp()); test("eask docker 27.1 info", async () => { - await ctx.runEask("docker 27.1 info"); + // this can take a long time to pull and build the image + await ctx.runEask("docker 27.1 info", { timeout: 40000 }); }); }); From f804013978ab2b6b6a36da5741fb69c10964adb3 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 26 Mar 2025 19:21:03 -0700 Subject: [PATCH 54/70] Tweak timeouts of local.test.js --- test/jest/local.test.js | 7 ++++++- test/jest/local/Eask | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/test/jest/local.test.js b/test/jest/local.test.js index 99daa14c..ac58a30e 100644 --- a/test/jest/local.test.js +++ b/test/jest/local.test.js @@ -6,11 +6,16 @@ const { emacsVersion, TestContext } = require("./helpers"); +jest.setTimeout(60000); + describe("local", () => { const cwd = "./test/jest/local"; const ctx = new TestContext(cwd); // NOTE: install-deps takes a long time in this package + // this is because of recipe dependencies triggering + // "temporary archives" build. + beforeAll(async () => await ctx.runEask("install-deps", { timeout: 40000 })); afterAll(() => ctx.cleanUp()); @@ -64,7 +69,7 @@ describe("local", () => { }); }); - describe.skip("Preparation", () => { + describe("Preparation", () => { beforeAll(async () => await ctx.runEask("prepare --dev")); afterAll(async () => await ctx.runEask("clean dist")); diff --git a/test/jest/local/Eask b/test/jest/local/Eask index 480eef12..bacb363d 100644 --- a/test/jest/local/Eask +++ b/test/jest/local/Eask @@ -27,6 +27,8 @@ (depends-on "f") (depends-on "s") (depends-on "fringe-helper") +;; FIXME: including these takes a really long time +;; perhaps move to a dedicated test file (depends-on "watch-cursor" :repo "jcs-elpa/watch-cursor" :fetcher 'github) (depends-on "organize-imports-java" From 01e9c2c90b02d82afcff1565bb57309a363ada56 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Wed, 26 Mar 2025 19:21:29 -0700 Subject: [PATCH 55/70] docs: comment on boolean env vars --- .../content/Contributing/Testing/_index.en.md | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/content/Contributing/Testing/_index.en.md b/docs/content/Contributing/Testing/_index.en.md index 2f8042f4..f9c55b40 100644 --- a/docs/content/Contributing/Testing/_index.en.md +++ b/docs/content/Contributing/Testing/_index.en.md @@ -8,12 +8,9 @@ weight: 20 This describes how to run tests locally, and how to write new tests for Eask. Local testing for Eask is done using the [Jest](https://jestjs.io) testing framework. - -- TODO why jest - -A custom `TestContext` class is used to manage the execution environment for each test suite. - -- TODO perhaps not relevant here +Jest is a mature and well supported testing framework written in Javascript. +Jest was chosen for much the [same reasons as Javascript](https://emacs-eask.github.io/FAQ/#-why-javascript) was chosen for this project. +In addition, Jest is easy to learn and has built in support for snapshot based testing. ### Running Tests @@ -36,10 +33,14 @@ For example | Name | Type | Default | Meaning | |:---------------|:-------|---------|:--------------------------------------------------------------------------------------------------| -| `ALLOW_UNSAFE` | bool | 0 | Run tests in `testUnsafe` blocks. These can **overwrite** your personal emacs config or settings. | -| `DEBUG` | bool | 0 | Print full output from commands in test. | -| `EASK_COMMAND` | path | "eask" | Path to Eask. Usually either `eask` or `./bin/eask` (include local changes). | -| `TIMEOUT` | number | 25000 | Command timeout in ms. Note this is different than Jest's timeout, which should be greater. | +| `ALLOW_UNSAFE` | bool* | false | Run tests in `testUnsafe` blocks. These can **overwrite** your personal emacs config or settings. | +| `DEBUG` | bool* | false | Print full output from commands in test. | +| `EASK_COMMAND` | path | "eask" | Path to Eask. Usually either `eask` or `$PWD/bin/eask` to use local changes. | +| `TIMEOUT` | number | 25000 | Command timeout in ms. Note this is different than Jest's timeout, which should be greater. | + +(*) Node.js handles environment variables as strings. That means that `DEBUG=0`, `DEBUG=false` all _enable_ `DEBUG`. + The only setting which disables a boolean flag is null, for example `DEBUG=` + ### How to Write a Test @@ -78,7 +79,7 @@ describe("emacs", () => { }); ``` -In Jest, you group related tests using `describe`. Tests in the same describe block can share setup/teardown code, +In Jest, you group related tests using `describe`. Tests in the same `describe` block can share setup/teardown code, can be disabled as a group and are grouped under the same heading in output. `describe` blocks can be nested within other `describe` blocks. @@ -200,6 +201,7 @@ testUnsafe("global install", async () => { ### Common Problems - When using `runEask()`, pass only the Eask *arguments*, not the `eask` command itself. +- Always `await` any expressions that trigger commands. - When using `expect(...).rejects` it should be awaited so that the promise rejects before the test completes. - The folder argument to `TestContext` should be relative to project root, if it doesn't exist you may get an error `ENOENT` - If you get an error from Jest reporting open handles, then try using `afterAll(() => ctx.cleanUp())` From 8ff24e0546c7dcdcc044020a0599139414ddea38 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 27 Mar 2025 21:13:58 -0700 Subject: [PATCH 56/70] rename npm script test-docker to test-ci --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 796ff478..6e7efa65 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "A set of command-line tools to build Emacs packages", "main": "eask", "scripts": { - "test-docker": "env ALLOW_UNSAFE=1 jest", + "test-unsafe": "env ALLOW_UNSAFE=1 jest", "test-debug": "env DEBUG=1 jest", "test": "jest", "test-reset": "rm -rf ./test/jest/.eask ./test/jest/*/.eask; git restore ./test/jest/*/", From 395039c91c7c494b0dfa27d1aa74a254a0b746ae Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 27 Mar 2025 21:22:26 -0700 Subject: [PATCH 57/70] use jest tests in workflows --- .github/workflows/analyze.yml | 2 +- .github/workflows/config.yml | 4 ++-- .github/workflows/docker.yml | 4 ++-- .github/workflows/emacs.yml | 2 +- .github/workflows/exec.yml | 2 +- .github/workflows/exit_status.yml | 2 +- .github/workflows/global.yml | 2 +- .github/workflows/install.yml | 2 +- .github/workflows/link.yml | 2 +- .github/workflows/local.yml | 2 +- .github/workflows/options.yml | 2 +- .github/workflows/outdated_upgrade.yml | 2 +- .github/workflows/search.yml | 2 +- .github/workflows/test_buttercup.yml | 2 +- .github/workflows/test_ecukes.yml | 2 +- .github/workflows/test_ert-runner.yml | 2 +- .github/workflows/test_ert.yml | 2 +- 17 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 68ddcfdf..dada58f2 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -73,4 +73,4 @@ jobs: - name: Testing... run: | - make command-analyze + npm run test-unsafe test/jest/analyze.test.js diff --git a/.github/workflows/config.yml b/.github/workflows/config.yml index 12afb128..f8d55034 100644 --- a/.github/workflows/config.yml +++ b/.github/workflows/config.yml @@ -5,7 +5,7 @@ on: branches: - master paths: - - 'eask' + - 'eask' - '**.yml' - lisp/** - cmds/** @@ -73,4 +73,4 @@ jobs: - name: Testing... run: | - make command-config + npm run test-unsafe test/jest/config.test.js diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0914f887..256010f1 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -29,7 +29,7 @@ jobs: strategy: fail-fast: false matrix: - os: + os: - ubuntu-latest # XXX: `macos-latest` on arm64 is not possible as well!? # See https://stackoverflow.com/questions/77675906/github-actions-build-docker-image-on-arm64-macos-latest-xlarge @@ -67,4 +67,4 @@ jobs: - name: Testing... run: | - make command-docker + npm run test-unsafe test/jest/docker.test.js diff --git a/.github/workflows/emacs.yml b/.github/workflows/emacs.yml index dacf340d..095f7371 100644 --- a/.github/workflows/emacs.yml +++ b/.github/workflows/emacs.yml @@ -73,4 +73,4 @@ jobs: - name: Testing... run: | - make command-emacs + npm run test-unsafe test/jest/emacs.test.js diff --git a/.github/workflows/exec.yml b/.github/workflows/exec.yml index 21d1c64b..9284d298 100644 --- a/.github/workflows/exec.yml +++ b/.github/workflows/exec.yml @@ -70,4 +70,4 @@ jobs: - name: Testing... run: | - make command-exec + npm run test-unsafe test/jest/exec.test.js diff --git a/.github/workflows/exit_status.yml b/.github/workflows/exit_status.yml index 3c0f96e0..6876bf04 100644 --- a/.github/workflows/exit_status.yml +++ b/.github/workflows/exit_status.yml @@ -50,4 +50,4 @@ jobs: - name: Testing... run: | - make command-exit-status + npm run test-unsafe test/jest/exit-status.test.js diff --git a/.github/workflows/global.yml b/.github/workflows/global.yml index a9087a02..ef5f199a 100644 --- a/.github/workflows/global.yml +++ b/.github/workflows/global.yml @@ -73,4 +73,4 @@ jobs: - name: Testing... run: | - make command-global + npm run test-unsafe test/jest/global.test.js diff --git a/.github/workflows/install.yml b/.github/workflows/install.yml index 64345cf9..66fff457 100644 --- a/.github/workflows/install.yml +++ b/.github/workflows/install.yml @@ -73,4 +73,4 @@ jobs: - name: Testing... run: | - make command-install + npm run test-unsafe test/jest/install.test.js diff --git a/.github/workflows/link.yml b/.github/workflows/link.yml index 7a575d9a..2ea8a3e2 100644 --- a/.github/workflows/link.yml +++ b/.github/workflows/link.yml @@ -70,4 +70,4 @@ jobs: - name: Testing... run: | - make command-link + npm run test-unsafe test/jest/link.test.js diff --git a/.github/workflows/local.yml b/.github/workflows/local.yml index ac56b500..ee3527e1 100644 --- a/.github/workflows/local.yml +++ b/.github/workflows/local.yml @@ -73,4 +73,4 @@ jobs: - name: Testing... run: | - make command-local + npm run test-unsafe test/jest/local.test.js diff --git a/.github/workflows/options.yml b/.github/workflows/options.yml index 35e18ed1..9bdf4ab1 100644 --- a/.github/workflows/options.yml +++ b/.github/workflows/options.yml @@ -52,4 +52,4 @@ jobs: - name: Testing... run: | - make test-options + npm run test-unsafe test/jest/options.test.js diff --git a/.github/workflows/outdated_upgrade.yml b/.github/workflows/outdated_upgrade.yml index 2654c941..1aa533f6 100644 --- a/.github/workflows/outdated_upgrade.yml +++ b/.github/workflows/outdated_upgrade.yml @@ -52,4 +52,4 @@ jobs: - name: Testing... run: | - make command-outdated-upgrade + npm run test-unsafe test/jest/outdated.test.js diff --git a/.github/workflows/search.yml b/.github/workflows/search.yml index a79a86f5..b3a9336a 100644 --- a/.github/workflows/search.yml +++ b/.github/workflows/search.yml @@ -52,4 +52,4 @@ jobs: - name: Testing... run: | - make command-search + npm run test-unsafe test/jest/search.test.js diff --git a/.github/workflows/test_buttercup.yml b/.github/workflows/test_buttercup.yml index d8a8dca0..683343d1 100644 --- a/.github/workflows/test_buttercup.yml +++ b/.github/workflows/test_buttercup.yml @@ -52,4 +52,4 @@ jobs: - name: Testing... run: | - make test-buttercup + npm run test-unsafe test/jest/buttercup.test.js diff --git a/.github/workflows/test_ecukes.yml b/.github/workflows/test_ecukes.yml index 5633087f..13c93001 100644 --- a/.github/workflows/test_ecukes.yml +++ b/.github/workflows/test_ecukes.yml @@ -52,4 +52,4 @@ jobs: - name: Testing... run: | - make test-ecukes + npm run test-unsafe test/jest/test-ecukes.test.js diff --git a/.github/workflows/test_ert-runner.yml b/.github/workflows/test_ert-runner.yml index 7decd111..9ac6c49a 100644 --- a/.github/workflows/test_ert-runner.yml +++ b/.github/workflows/test_ert-runner.yml @@ -52,4 +52,4 @@ jobs: - name: Testing... run: | - make test-ert-runner + npm run test-unsafe test/jest/test-ert-runner.test.js diff --git a/.github/workflows/test_ert.yml b/.github/workflows/test_ert.yml index 9b652994..a5c60fb1 100644 --- a/.github/workflows/test_ert.yml +++ b/.github/workflows/test_ert.yml @@ -52,4 +52,4 @@ jobs: - name: Testing... run: | - make test-ert + npm run test-unsafe test/jest/test-ert.test.js From 046dfebd3b5c50f0109536fb3613458c60be54d3 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 27 Mar 2025 21:59:42 -0700 Subject: [PATCH 58/70] Only run eask loc on emacs >= 28.1 --- test/jest/local.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jest/local.test.js b/test/jest/local.test.js index ac58a30e..d8de59aa 100644 --- a/test/jest/local.test.js +++ b/test/jest/local.test.js @@ -50,8 +50,8 @@ describe("local", () => { }); // NOTE: eask loc is a long running command it("loc", async () => { - // installs markdown mode - if ((await emacsVersion()) > "27.1") { + // installs markdown mode -- depends on emacs 28.1 + if ((await emacsVersion()) >= "28.1") { await ctx.runEask("loc"); await ctx.runEask("loc Eask"); } From bc9c240044b27cb9a414d1cd2e2fcbda9460e823 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 27 Mar 2025 22:00:19 -0700 Subject: [PATCH 59/70] Increase timeout in config.test.js --- test/jest/config.test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/jest/config.test.js b/test/jest/config.test.js index afe47f85..fe864f3b 100644 --- a/test/jest/config.test.js +++ b/test/jest/config.test.js @@ -42,7 +42,9 @@ describe("config param", () => { "./test/jest/config/init.el", path.join(process.env.HOME, "/.emacs.d/init.el"), ); - await ctx.runEask("install -c spinner ivy beacon company-fuzzy"); + await ctx.runEask("install -c spinner ivy beacon company-fuzzy", { + timeout: 35000, + }); }); testUnsafe("eask uninstall -c", async () => { From f082f127163b0bc6d87f15fbc0477ed001292ab9 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 27 Mar 2025 22:00:40 -0700 Subject: [PATCH 60/70] docs: add method doco to helpers.js --- test/jest/helpers.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/jest/helpers.js b/test/jest/helpers.js index 615290e9..efda9ddb 100644 --- a/test/jest/helpers.js +++ b/test/jest/helpers.js @@ -144,6 +144,15 @@ class TestContext { return this.run(this.easkCommand + " " + command, config); } + /** + * Runs a command in the context's directory. + * Prefer using Node APIs for commands like copy, delete etc. + * See https://nodejs.org/docs/latest-v20.x/api/child_process.html#child_processexeccommand-options-callback + * for additional config options. + * @param {string} command + * @param {any} config + * @returns {Promise.} + */ run(command, config) { return exec(command, { cwd: this.cwd, @@ -167,6 +176,10 @@ class TestContext { }); } + /** + * Abort any processes created using `runEask` or `run`. + * @returns {void} + */ cleanUp() { this.controller.abort(); } From 1a093bc0337ec546bca2bd691b7f2f62437fa23a Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 27 Mar 2025 22:10:20 -0700 Subject: [PATCH 61/70] In config.test.js throw if init.el exists --- test/jest/config.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jest/config.test.js b/test/jest/config.test.js index fe864f3b..7b782c4b 100644 --- a/test/jest/config.test.js +++ b/test/jest/config.test.js @@ -41,6 +41,7 @@ describe("config param", () => { await fs.copyFile( "./test/jest/config/init.el", path.join(process.env.HOME, "/.emacs.d/init.el"), + fs.constants.COPYFILE_EXCL, // throw if init.el already exists ); await ctx.runEask("install -c spinner ivy beacon company-fuzzy", { timeout: 35000, From 714dce4e91af2e8d6858412a361d09c13e37a37f Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 27 Mar 2025 22:11:52 -0700 Subject: [PATCH 62/70] Add workflow for upgrade-eask test --- .github/workflows/upgrade-eask.yml | 55 ++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .github/workflows/upgrade-eask.yml diff --git a/.github/workflows/upgrade-eask.yml b/.github/workflows/upgrade-eask.yml new file mode 100644 index 00000000..7eb95625 --- /dev/null +++ b/.github/workflows/upgrade-eask.yml @@ -0,0 +1,55 @@ +name: Upgrade Eask + +on: + push: + branches: + - master + paths: + - 'eask' + - '**.yml' + - lisp/** + - cmds/** + - src/** + - test/** + pull_request: + branches: + - master + paths-ignore: + - '**/docs.yml' + - '**.md' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + emacs-version: + - 30.1 + + steps: + - uses: jcs090218/setup-emacs@master + with: + version: ${{ matrix.emacs-version }} + + - uses: actions/checkout@v4 + + - name: Prepare Eask (Unix) + if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest' + run: | + chmod -R 777 ./ + .github/scripts/setup-eask + + - name: Prepare Eask (Windows) + if: matrix.os == 'windows-latest' + run: .github/scripts/setup-eask.ps1 + + - name: Testing... + run: | + npm run test-unsafe test/jest/upgrade-eask.test.js From e31f0f5a441a99d7c310fee5ccfb61d7c667d21b Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 27 Mar 2025 22:44:27 -0700 Subject: [PATCH 63/70] Remove makefile targets and old script files --- Makefile | 89 ------------ test/commands/analyze/dsl/.gitignore | 14 -- test/commands/analyze/dsl/Eask | 44 ------ test/commands/analyze/dsl/check-dsl.el | 37 ----- test/commands/analyze/dsl/run.sh | 34 ----- test/commands/analyze/error/run.sh | 31 ---- test/commands/analyze/metadata/.gitignore | 14 -- test/commands/analyze/metadata/Eask | 16 --- .../analyze/metadata/check-metadata.el | 37 ----- test/commands/analyze/metadata/run.sh | 34 ----- test/commands/bump/run.sh | 31 ---- test/commands/compile/run.sh | 30 ---- test/commands/concat/run.sh | 31 ---- test/commands/config/run.sh | 38 ----- test/commands/docker/run.sh | 28 ---- test/commands/docs/run.sh | 31 ---- test/commands/emacs/run.sh | 29 ---- test/commands/eval/run.sh | 30 ---- test/commands/exec/.gitignore | 14 -- test/commands/exec/Eask | 20 --- test/commands/exec/bin/github-elpa.bat | 2 - test/commands/exec/exec.el | 37 ----- test/commands/exec/run.sh | 39 ----- test/commands/exec/test/test-dummy.el | 36 ----- test/commands/format/run.sh | 33 ----- test/commands/global/run.sh | 38 ----- test/commands/info/run.sh | 29 ---- test/commands/init/run.sh | 39 ----- test/commands/install/run.sh | 57 -------- test/commands/link/run.sh | 40 ------ test/commands/lint/run.sh | 52 ------- test/commands/local/run.sh | 134 ------------------ test/commands/outdated_upgrade/.gitignore | 14 -- test/commands/outdated_upgrade/Eask | 13 -- .../commands/outdated_upgrade/make-outdate.el | 59 -------- test/commands/outdated_upgrade/run.sh | 34 ----- test/commands/recipe/run.sh | 31 ---- test/commands/run/run.sh | 33 ----- test/commands/search/.gitignore | 14 -- test/commands/search/Eask | 10 -- test/commands/search/run.sh | 33 ----- test/commands/source/run.sh | 35 ----- test/commands/test/buttercup/.gitignore | 14 -- test/commands/test/buttercup/Eask | 13 -- test/commands/test/buttercup/run.sh | 50 ------- .../buttercup/test-fail/buttercup-test.el | 31 ---- .../test/buttercup/test-ok/buttercup-test.el | 31 ---- test/commands/test/ecukes/Eask | 13 -- .../commands/test/ecukes/features/foo.feature | 0 .../features/step-definitions/ecukes-steps.el | 0 .../test/ecukes/features/support/env.el | 0 test/commands/test/ecukes/run.sh | 29 ---- test/commands/test/ert-runner/.gitignore | 14 -- test/commands/test/ert-runner/Eask | 13 -- test/commands/test/ert-runner/run.sh | 28 ---- .../test/ert-runner/test/ert-runner-test.el | 31 ---- test/commands/test/ert/.gitignore | 14 -- test/commands/test/ert/Eask | 10 -- test/commands/test/ert/run.sh | 37 ----- .../test/ert/test-nil-message/ert-test.el | 30 ---- test/commands/test/ert/test/ert-test.el | 30 ---- test/options/.gitignore | 14 -- test/options/Eask | 12 -- test/options/run.sh | 53 ------- 64 files changed, 1911 deletions(-) delete mode 100644 test/commands/analyze/dsl/.gitignore delete mode 100644 test/commands/analyze/dsl/Eask delete mode 100644 test/commands/analyze/dsl/check-dsl.el delete mode 100644 test/commands/analyze/dsl/run.sh delete mode 100755 test/commands/analyze/error/run.sh delete mode 100644 test/commands/analyze/metadata/.gitignore delete mode 100644 test/commands/analyze/metadata/Eask delete mode 100644 test/commands/analyze/metadata/check-metadata.el delete mode 100644 test/commands/analyze/metadata/run.sh delete mode 100755 test/commands/bump/run.sh delete mode 100755 test/commands/compile/run.sh delete mode 100755 test/commands/concat/run.sh delete mode 100644 test/commands/config/run.sh delete mode 100644 test/commands/docker/run.sh delete mode 100755 test/commands/docs/run.sh delete mode 100644 test/commands/emacs/run.sh delete mode 100755 test/commands/eval/run.sh delete mode 100644 test/commands/exec/.gitignore delete mode 100644 test/commands/exec/Eask delete mode 100644 test/commands/exec/bin/github-elpa.bat delete mode 100644 test/commands/exec/exec.el delete mode 100755 test/commands/exec/run.sh delete mode 100644 test/commands/exec/test/test-dummy.el delete mode 100755 test/commands/format/run.sh delete mode 100644 test/commands/global/run.sh delete mode 100755 test/commands/info/run.sh delete mode 100755 test/commands/init/run.sh delete mode 100755 test/commands/install/run.sh delete mode 100755 test/commands/link/run.sh delete mode 100755 test/commands/lint/run.sh delete mode 100644 test/commands/local/run.sh delete mode 100644 test/commands/outdated_upgrade/.gitignore delete mode 100644 test/commands/outdated_upgrade/Eask delete mode 100644 test/commands/outdated_upgrade/make-outdate.el delete mode 100644 test/commands/outdated_upgrade/run.sh delete mode 100755 test/commands/recipe/run.sh delete mode 100755 test/commands/run/run.sh delete mode 100644 test/commands/search/.gitignore delete mode 100644 test/commands/search/Eask delete mode 100755 test/commands/search/run.sh delete mode 100755 test/commands/source/run.sh delete mode 100644 test/commands/test/buttercup/.gitignore delete mode 100644 test/commands/test/buttercup/Eask delete mode 100755 test/commands/test/buttercup/run.sh delete mode 100644 test/commands/test/buttercup/test-fail/buttercup-test.el delete mode 100644 test/commands/test/buttercup/test-ok/buttercup-test.el delete mode 100644 test/commands/test/ecukes/Eask delete mode 100644 test/commands/test/ecukes/features/foo.feature delete mode 100644 test/commands/test/ecukes/features/step-definitions/ecukes-steps.el delete mode 100644 test/commands/test/ecukes/features/support/env.el delete mode 100644 test/commands/test/ecukes/run.sh delete mode 100644 test/commands/test/ert-runner/.gitignore delete mode 100644 test/commands/test/ert-runner/Eask delete mode 100644 test/commands/test/ert-runner/run.sh delete mode 100644 test/commands/test/ert-runner/test/ert-runner-test.el delete mode 100644 test/commands/test/ert/.gitignore delete mode 100644 test/commands/test/ert/Eask delete mode 100755 test/commands/test/ert/run.sh delete mode 100644 test/commands/test/ert/test-nil-message/ert-test.el delete mode 100644 test/commands/test/ert/test/ert-test.el delete mode 100644 test/options/.gitignore delete mode 100644 test/options/Eask delete mode 100755 test/options/run.sh diff --git a/Makefile b/Makefile index 4a984bcc..84b5233e 100644 --- a/Makefile +++ b/Makefile @@ -14,97 +14,8 @@ test-compat: @echo "Test compatibility..." $(EASK) load ./test/development/compat.el --allow-error -test-options: - ./test/options/run.sh - color: ./test/color/run.sh error: ./test/error/run.sh - -command-global: - ./test/commands/global/run.sh - -command-config: - ./test/commands/config/run.sh - -command-local: - ./test/commands/local/run.sh - -# new tests which check missing args not covered by existing tests -command-exit-status: command-bump command-concat command-docs command-eval command-format command-info command-init command-lint command-recipe command-run command-source - -command-analyze: - ./test/commands/analyze/dsl/run.sh - ./test/commands/analyze/metadata/run.sh - ./test/commands/analyze/error/run.sh - -command-bump: - ./test/commands/bump/run.sh - -command-compile: - ./test/commands/compile/run.sh - -command-concat: - ./test/commands/concat/run.sh - -command-docker: - ./test/commands/docker/run.sh - -command-docs: - ./test/commands/docs/run.sh - -command-eval: - ./test/commands/eval/run.sh - -command-exec: - ./test/commands/exec/run.sh - -command-emacs: - ./test/commands/emacs/run.sh - -command-format: - ./test/commands/format/run.sh - -command-info: - ./test/commands/info/run.sh - -command-init: - ./test/commands/init/run.sh - -command-install: - ./test/commands/install/run.sh - -command-link: - ./test/commands/link/run.sh - -command-lint: - ./test/commands/lint/run.sh - -command-outdated-upgrade: - ./test/commands/outdated_upgrade/run.sh - -command-recipe: - ./test/commands/recipe/run.sh - -command-run: - ./test/commands/run/run.sh - -command-search: - ./test/commands/search/run.sh - -command-source: - ./test/commands/source/run.sh - -test-ert: - ./test/commands/test/ert/run.sh - -test-ert-runner: - ./test/commands/test/ert-runner/run.sh - -test-buttercup: - ./test/commands/test/buttercup/run.sh - -test-ecukes: - ./test/commands/test/ecukes/run.sh diff --git a/test/commands/analyze/dsl/.gitignore b/test/commands/analyze/dsl/.gitignore deleted file mode 100644 index a50232f7..00000000 --- a/test/commands/analyze/dsl/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# ignore these directories -/.git -/recipes - -# ignore generated files -*.elc - -# eask packages -.eask/ -dist/ - -# packaging -*-autoloads.el -*-pkg.el diff --git a/test/commands/analyze/dsl/Eask b/test/commands/analyze/dsl/Eask deleted file mode 100644 index a7dd0905..00000000 --- a/test/commands/analyze/dsl/Eask +++ /dev/null @@ -1,44 +0,0 @@ -(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 - -;; -;;; Below are errors/warnings to lint - -(package "check-dsl" "0.0.1" "Test for DSL") ; duplicate `package` directive -(package "" "" "") - -(website-url "https://github.com/emacs-eask/check-dsl") ; duplicate url -(website-url "https://github.com/emacs-eask/check-dsl") -(keywords "dsl") ; duplicate keywords -(keywords "dsl") - -(author "name") ; duplicate `author` -(author "name") - -(license "GPLv3") ; duplicate `license` -(license "GPLv3") - -(package-file "check-dsl.el") ; duplicate `package-file` directive -(package-file "check-dsl.el") - -(package-descriptor "check-pkg.el") ; duplicate `package-descriptor` directive -(package-descriptor "check-pkg.el") - -;; duplicate scripts -(script "test" "echo \"Error: no test specified\" && exit 1") -(script "test" "echo \"Error: no test specified\" && exit 1") - -(source 'gnu) ; duplicate archives -(source 'gnu) - -(source "magic-archive") ; Unkown archive - -(depends-on "emacs" "26.1") ; duplicate `emacs` dependency -(depends-on "emacs") - -(depends-on "dash") ; duplicate dependency -(depends-on "dash") - -(development - (depends-on "f") ; duplicate dependency - (depends-on "f") - ) diff --git a/test/commands/analyze/dsl/check-dsl.el b/test/commands/analyze/dsl/check-dsl.el deleted file mode 100644 index e6407257..00000000 --- a/test/commands/analyze/dsl/check-dsl.el +++ /dev/null @@ -1,37 +0,0 @@ -;;; check-dsl.el --- Test for DSL -*- lexical-binding: t; -*- - -;; Copyright (C) 2022-2025 the Eask authors. -;; Created date 2022-04-19 15:16:50 - -;; Author: Shen, Jen-Chieh -;; URL: https://github.com/emacs-eask/check-dsl -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3") (dash "0.1")) -;; Keywords: dsl - -;; This file is NOT part of GNU Emacs. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; -;; Test for DSL. -;; - -;;; Code: - - - -(provide 'check-dsl) -;;; check-dsl.el ends here diff --git a/test/commands/analyze/dsl/run.sh b/test/commands/analyze/dsl/run.sh deleted file mode 100644 index 420452ed..00000000 --- a/test/commands/analyze/dsl/run.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/analyze `analyze` -# - -set -e - -# Naviate to the test package -cd $(dirname "$0") - -echo "Testing analyze command... (Plain text)" -eask analyze -eask analyze Eask - -echo "Testing analyze command... (JSON format)" -eask analyze --json -eask analyze Eask --json diff --git a/test/commands/analyze/error/run.sh b/test/commands/analyze/error/run.sh deleted file mode 100755 index 6cb90c21..00000000 --- a/test/commands/analyze/error/run.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/analyze `analyze` errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -# Naviate to the test package -cd $(dirname "$0") - -echo "Testing analyze command... no files" -should_error eask analyze diff --git a/test/commands/analyze/metadata/.gitignore b/test/commands/analyze/metadata/.gitignore deleted file mode 100644 index a50232f7..00000000 --- a/test/commands/analyze/metadata/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# ignore these directories -/.git -/recipes - -# ignore generated files -*.elc - -# eask packages -.eask/ -dist/ - -# packaging -*-autoloads.el -*-pkg.el diff --git a/test/commands/analyze/metadata/Eask b/test/commands/analyze/metadata/Eask deleted file mode 100644 index 25b9ca66..00000000 --- a/test/commands/analyze/metadata/Eask +++ /dev/null @@ -1,16 +0,0 @@ -(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 - -;; -;;; Below are errors/warnings to lint - -(package "check-metadata?" ; unmatched - "0.0.1?" ; unmatched and invalid version syntax - "Test for unmatch metadata?" ; unmatched - ) - -(website-url "https://github.com/emacs-eask/check-metadata?") ; unmatched -(keywords "metadata?") ; missing - -(package-file "check-metadata.el") - -(depends-on "s") ; unmatch dependency diff --git a/test/commands/analyze/metadata/check-metadata.el b/test/commands/analyze/metadata/check-metadata.el deleted file mode 100644 index 301968d8..00000000 --- a/test/commands/analyze/metadata/check-metadata.el +++ /dev/null @@ -1,37 +0,0 @@ -;;; check-metadata.el --- Test for unmatch metadata -*- lexical-binding: t; -*- - -;; Copyright (C) 2022-2025 the Eask authors. -;; Created date 2022-04-19 15:16:50 - -;; Author: Shen, Jen-Chieh -;; URL: https://github.com/emacs-eask/check-metadata -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3") (dash "0.1")) -;; Keywords: metadata - -;; This file is NOT part of GNU Emacs. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; -;; Test for unmatch metadata. -;; - -;;; Code: - - - -(provide 'check-metadata) -;;; check-metadata.el ends here diff --git a/test/commands/analyze/metadata/run.sh b/test/commands/analyze/metadata/run.sh deleted file mode 100644 index 21fc672b..00000000 --- a/test/commands/analyze/metadata/run.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/checker `analyze` -# - -set -e - -# Naviate to the test package -cd $(dirname "$0") - -echo "Testing analyze command... (Plain text)" -eask analyze -eask analyze Eask - -echo "Testing analyze command... (JSON format)" -eask analyze --json -eask analyze Eask --json diff --git a/test/commands/bump/run.sh b/test/commands/bump/run.sh deleted file mode 100755 index fabac56e..00000000 --- a/test/commands/bump/run.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/bump `bump` errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -# Naviate to the test package -cd $(dirname "$0") - -echo "Testing bump command... no files" -should_error eask bump diff --git a/test/commands/compile/run.sh b/test/commands/compile/run.sh deleted file mode 100755 index 45fc58ef..00000000 --- a/test/commands/compile/run.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/compile `compile` errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -cd $(dirname "$0") - -echo "Testing compile command... no files" -should_error eask compile diff --git a/test/commands/concat/run.sh b/test/commands/concat/run.sh deleted file mode 100755 index 6c4031bb..00000000 --- a/test/commands/concat/run.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/concat `concat` errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -# Naviate to the test package -cd $(dirname "$0") - -echo "Testing concat command... no files" -should_error eask concat diff --git a/test/commands/config/run.sh b/test/commands/config/run.sh deleted file mode 100644 index 13bdc61f..00000000 --- a/test/commands/config/run.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Here we test all config (~/.emacs.d/) that the Emacser can be use daily! -# -# Notice, to make config commands work; we need a minimum configuration -# (home/.emacs.d), and place it under to the default Emacs directory! -# - -set -e - -echo "Copy test configuration" -./test/fixtures/home/scripts/setup.sh - -echo "Testing config (~/.emacs.d/) commands..." -eask archives -c - -eask install -c spinner ivy beacon company fuzzy -eask uninstall -c ivy fuzzy - -eask list -c --depth=0 -eask outdated -c diff --git a/test/commands/docker/run.sh b/test/commands/docker/run.sh deleted file mode 100644 index 5d74d1b9..00000000 --- a/test/commands/docker/run.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2023-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command `docker` -# - -set -e - -# Naviate to the test package -cd "./test/fixtures/mini.pkg.1/" - -eask docker 27.1 info diff --git a/test/commands/docs/run.sh b/test/commands/docs/run.sh deleted file mode 100755 index 0d72878c..00000000 --- a/test/commands/docs/run.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/docs `docs` errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -# Naviate to the test package -cd $(dirname "$0") - -echo "Testing docs command... no files" -should_error eask docs diff --git a/test/commands/emacs/run.sh b/test/commands/emacs/run.sh deleted file mode 100644 index c99dabee..00000000 --- a/test/commands/emacs/run.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command `emacs` -# - -set -e - -echo "Test command 'emacs'..." -cd $(dirname "$0") - -eask emacs --version -eask emacs --batch --eval "(require (quote ert))" --eval "(ert-deftest mytest () (should-not (display-graphic-p)))" -f ert-run-tests-batch diff --git a/test/commands/eval/run.sh b/test/commands/eval/run.sh deleted file mode 100755 index 238a89b7..00000000 --- a/test/commands/eval/run.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/eval `eval` errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -cd $(dirname "$0") - -echo "Testing eval command... no arg" -should_error eask eval diff --git a/test/commands/exec/.gitignore b/test/commands/exec/.gitignore deleted file mode 100644 index a50232f7..00000000 --- a/test/commands/exec/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# ignore these directories -/.git -/recipes - -# ignore generated files -*.elc - -# eask packages -.eask/ -dist/ - -# packaging -*-autoloads.el -*-pkg.el diff --git a/test/commands/exec/Eask b/test/commands/exec/Eask deleted file mode 100644 index 3a9b9b2b..00000000 --- a/test/commands/exec/Eask +++ /dev/null @@ -1,20 +0,0 @@ -(package "exec" - "0.0.1" - "Test project for command exec") - -(website-url "https://github.com/emacs-eask/exec") -(keywords "exec") - -(package-file "exec.el") - -(exec-paths "./bin/") - -(source 'gnu) -(source 'melpa) - -(depends-on "emacs" "26.1") -(depends-on "ert-runner") -(depends-on "github-elpa") -(depends-on "buttercup") - -(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test/commands/exec/bin/github-elpa.bat b/test/commands/exec/bin/github-elpa.bat deleted file mode 100644 index b444158f..00000000 --- a/test/commands/exec/bin/github-elpa.bat +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -echo Test from github-elpa.bat diff --git a/test/commands/exec/exec.el b/test/commands/exec/exec.el deleted file mode 100644 index c9d67827..00000000 --- a/test/commands/exec/exec.el +++ /dev/null @@ -1,37 +0,0 @@ -;;; exec.el --- Test project for command exec -*- lexical-binding: t; -*- - -;; Copyright (C) 2022-2025 the Eask authors. -;; Created date 2022-03-29 14:10:40 - -;; Author: Shen, Jen-Chieh -;; URL: https://github.com/emacs-eask/exec -;; Version: 0.0.1 -;; Package-Requires: ((emacs "26.1")) -;; Keywords: exec - -;; This file is NOT part of GNU Emacs. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; -;; Test project for command exec. -;; - -;;; Code: - -(require 'cl-lib) - -(provide 'exec) -;;; exec.el ends here diff --git a/test/commands/exec/run.sh b/test/commands/exec/run.sh deleted file mode 100755 index 472e1155..00000000 --- a/test/commands/exec/run.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command `exec` -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -echo "Test command 'exec'..." -cd $(dirname "$0") - -eask install-deps -eask exec ert-runner -h -eask exec github-elpa -h -eask exec echo hello world - -eask exec buttercup -L . -eask exec buttercup -L . --pattern 'pattern 1' - -echo "Testing exec command... no files" -should_error eask exec diff --git a/test/commands/exec/test/test-dummy.el b/test/commands/exec/test/test-dummy.el deleted file mode 100644 index bae38926..00000000 --- a/test/commands/exec/test/test-dummy.el +++ /dev/null @@ -1,36 +0,0 @@ -;;; test-dummy.el --- Dummy buttercup test -*- lexical-binding: t; -*- - -;; Copyright (C) 2023 the Eask authors. - -;; This file is not part of GNU Emacs. - -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; -;; Dummy buttercup test. -;; - -;;; Code: - -(describe "Dumm Test" - (it "pattern 1" - (let ((dummy-var-1 t)) - (expect dummy-var-1 :to-be t))) - (it "pattern 2" - (let ((dummy-var-2 nil)) - (expect dummy-var-2 :to-be nil)))) - -(provide 'test-dummy) -;;; test-dummy.el ends here diff --git a/test/commands/format/run.sh b/test/commands/format/run.sh deleted file mode 100755 index f62fbeb4..00000000 --- a/test/commands/format/run.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/format errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -cd $(dirname "$0") - -echo "Testing elfmt command... no files" -should_error eask format elfmt - -echo "Testing elisp-autofmt command... no files" -should_error eask format elisp-autofmt diff --git a/test/commands/global/run.sh b/test/commands/global/run.sh deleted file mode 100644 index afdb54f8..00000000 --- a/test/commands/global/run.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2023-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Here we test all global (~/.eask/) that the Emacser can be use daily! -# -# Notice, to make config commands work; we need a minimum configuration -# (home/.emacs.d), and place it under to the default Emacs directory! -# - -set -e - -echo "Copy test configuration" -./test/fixtures/home/scripts/setup.sh - -echo "Testing global (~/) commands..." -eask archives -g - -eask install -g spinner ivy beacon company fuzzy -eask uninstall -g ivy fuzzy - -eask list -g --depth=0 -eask outdated -g diff --git a/test/commands/info/run.sh b/test/commands/info/run.sh deleted file mode 100755 index 47bf52bb..00000000 --- a/test/commands/info/run.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/info errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -echo "Testing info command... no files" -should_error eask -g info -# When run in the current directory this sees the eask file from the main project diff --git a/test/commands/init/run.sh b/test/commands/init/run.sh deleted file mode 100755 index 039e6eb7..00000000 --- a/test/commands/init/run.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test eask init errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -cd $(dirname "$0") - -echo "Testing init --from cask command... no files" -should_error eask init --from cask - -echo "Testing init --from keg command... no files" -should_error eask init --from keg - -echo "Testing init --from eldev command... no files" -should_error eask init --from eldev - -echo "Testing init --from source command... no files" -should_error eask init --from source diff --git a/test/commands/install/run.sh b/test/commands/install/run.sh deleted file mode 100755 index 02bd31c2..00000000 --- a/test/commands/install/run.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test commands related to install, and uninstall -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -echo "Test commands related to install, and uninstall" - -# Naviate to the test package -cd "./test/fixtures/mini.pkg.1/" - -echo "Install dependencies" -eask install-deps - -echo "Install project package" -eask package -eask install - -echo "Install by sepcifying packages" -eask install beacon company-fuzzy transwin - -echo "Uninstall by sepcifying packages" -eask uninstall beacon transwin - -echo "Uninstall project package" -eask uninstall - -echo "Test eask install ... no files" -cd - -cd $(dirname "$0") -should_error eask install - -echo "Test eask uninstall ... no files" -should_error eask uninstall - -echo "Test eask reinstall ... no files" -should_error eask reinstall diff --git a/test/commands/link/run.sh b/test/commands/link/run.sh deleted file mode 100755 index 8b457087..00000000 --- a/test/commands/link/run.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2023-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Here we test all local (workspace) commands by simulating a Emacs -# pacakge development environment! -# -# Notice, below we clone a random packae (repo) that uses Eask as the -# dependencies management tool. -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -eask link add "mini.pkg.1" "./test/fixtures/mini.pkg.1/" -eask link list -eask link delete mini.pkg.1-0.0.1 - -cd $(dirname "$0") - -echo "Testing link command... no files" -should_error eask link add # not enough args -should_error eask link add foo . # missing package, prints help -should_error eask link delete diff --git a/test/commands/lint/run.sh b/test/commands/lint/run.sh deleted file mode 100755 index 467c5918..00000000 --- a/test/commands/lint/run.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/lint errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -# Naviate to the test package -cd $(dirname "$0") - -echo "Testing lint checkdoc command... no files" -should_error eask lint checkdoc - -echo "Testing lint declare command... no files" -should_error eask lint declare - -echo "Testing lint elint command... no files" -should_error eask lint elint - -echo "Testing lint elisp-lint command... no files" -should_error eask lint elisp-lint - -echo "Testing lint elsa command... no files" -should_error eask lint elsa - -echo "Testing lint indent command... no files" -should_error eask lint indent - -echo "Testing lint keywords command... no files" -should_error eask lint keywords - -echo "Testing lint regexps command... no files" -should_error eask lint regexps diff --git a/test/commands/local/run.sh b/test/commands/local/run.sh deleted file mode 100644 index 228cb59b..00000000 --- a/test/commands/local/run.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Here we test all local (workspace) commands by simulating a Emacs -# pacakge development environment! -# -# Notice, below we clone a random packae (repo) that uses Eask as the -# dependencies management tool. -# - -set -e - -# Naviate to the test package -cd "./test/fixtures/mini.pkg.1/" - -echo "Testing local commands..." -eask info -eask status -eask archives -eask archives --all -eask list --depth=0 -eask bump major minor patch -eask cat package.json --insecure -eask cat package.json --number --insecure -eask concat -#eask loc # Only 27.1+ -#eask loc Eask # Only 27.1+ - -# Documentation -#eask docs # Only 28.1+ -#eask docs *.el # Only 28.1+ - -# PATH environment -eask path -eask path bin -eask load-path -eask load-path bin - -# Preparation -eask prepare --dev -eask package - -# Development -eask compile -eask compile --clean -eask recompile -eask recompile --clean -eask recipe -eask keywords -eask run script -eask run script test -eask run script extra -- Extra arguments! -eask run script --all -eask run command -eask run command test -eask run command mini-test-3 -- Extra arguments! -eask run command --all - -# Exection -eask eval "(progn (require 'mini.pkg.1))" - -# Generating -eask generate autoloads -eask generate pkg-file -eask generate recipe -y -#eask generate license gpl-3.0 # XXX: Avoid API rate limit exceeded error -eask generate ignore elisp - -# Generating tests -eask generate test ert -rm -rf test -eask generate test ert-runner -eask generate test buttercup -eask generate test ecukes - -# Generating workflow -eask generate workflow circle-ci -eask generate workflow github -eask generate workflow gitlab -eask generate workflow travis-ci - -# Linting -eask lint checkdoc -eask lint declare -eask lint elint -eask lint elisp-lint -#eask lint elsa # XXX: Elsa is not stable, ignore it for now -eask lint indent -eask lint keywords -eask lint license -eask lint package -#eask lint regexps # Only 27.1+ - -# Testing -eask test activate - -# Formatting -#eask format elisp-autofmt # Only 29.1+ -eask format elfmt - -# Cleaning -eask clean .eask -eask clean elc -eask clean dist -eask clean autoloads -eask clean pkg-file -eask clean log-file -eask clean all - -# Control DSL -eask source add test "https://test.elpa.com" -eask source delete test -eask source list - -# Util -eask locate -eask upgrade-eask -eask refresh diff --git a/test/commands/outdated_upgrade/.gitignore b/test/commands/outdated_upgrade/.gitignore deleted file mode 100644 index a50232f7..00000000 --- a/test/commands/outdated_upgrade/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# ignore these directories -/.git -/recipes - -# ignore generated files -*.elc - -# eask packages -.eask/ -dist/ - -# packaging -*-autoloads.el -*-pkg.el diff --git a/test/commands/outdated_upgrade/Eask b/test/commands/outdated_upgrade/Eask deleted file mode 100644 index 00283012..00000000 --- a/test/commands/outdated_upgrade/Eask +++ /dev/null @@ -1,13 +0,0 @@ -(package "outdated-upgrade" - "0.0.1" - "Test project for command outdated and upgrade") - -(package-file "outdated-upgrade.el") - -(source 'gnu) -(source 'melpa) - -(depends-on "f") -(depends-on "s") - -(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test/commands/outdated_upgrade/make-outdate.el b/test/commands/outdated_upgrade/make-outdate.el deleted file mode 100644 index 63d6c5d7..00000000 --- a/test/commands/outdated_upgrade/make-outdate.el +++ /dev/null @@ -1,59 +0,0 @@ -;;; make-outdate.el --- Make some packages outdate -*- lexical-binding: t; -*- - -;; Copyright (C) 2022-2025 the Eask authors. - -;; This file is not part of GNU Emacs. - -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; -;; Make some packages outdate -;; - -;;; Code: - -(eask-pkg-init) - -(require 'f) - -(defconst make-outdate-version "20001122.1234" - "Outdate version.") - -(defun make-outdate-package (name) - "Make package (NAME) outdate." - (let* ((dir (file-name-directory (locate-library name))) - (pkg (concat dir name "-pkg.el"))) - (with-current-buffer (find-file pkg) - (goto-char (point-min)) - (when (re-search-forward "\"[0-9.]*\"" nil t) - (save-excursion - (let ((end (point))) - (backward-sexp) - (delete-region (point) end) - (insert (format "\"%s\"" make-outdate-version))))) - (save-buffer) - (kill-this-buffer)) - (let ((dest (expand-file-name (concat name "-" make-outdate-version "/") package-user-dir))) - (eask-info "Moving %s" dir) - (eask-info " to %s" dest) - (ignore-errors (make-directory dest t)) - (f-copy-contents dir dest) - (ignore-errors (delete-directory dir t))))) - -(make-outdate-package "dash") -(make-outdate-package "f") - -(provide 'make-outdate) -;;; make-outdate.el ends here diff --git a/test/commands/outdated_upgrade/run.sh b/test/commands/outdated_upgrade/run.sh deleted file mode 100644 index 779792fe..00000000 --- a/test/commands/outdated_upgrade/run.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command `exec` -# - -set -e - -echo "Test command 'search'..." -cd $(dirname "$0") - -eask prepare -eask load make-outdate.el - -eask outdated -eask outdated --depth 0 - -eask upgrade diff --git a/test/commands/recipe/run.sh b/test/commands/recipe/run.sh deleted file mode 100755 index ba9373bc..00000000 --- a/test/commands/recipe/run.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/recipe `recipe` errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -# Naviate to the test package -cd $(dirname "$0") - -echo "Testing recipe command... no files" -should_error eask recipe diff --git a/test/commands/run/run.sh b/test/commands/run/run.sh deleted file mode 100755 index 56596557..00000000 --- a/test/commands/run/run.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/run errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -cd $(dirname "$0") - -echo "Testing 'run command' command... no files" -should_error eask run command - -echo "Testing 'run script' command... no files" -should_error eask run script -g # needs to avoid parent Eask file diff --git a/test/commands/search/.gitignore b/test/commands/search/.gitignore deleted file mode 100644 index a50232f7..00000000 --- a/test/commands/search/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# ignore these directories -/.git -/recipes - -# ignore generated files -*.elc - -# eask packages -.eask/ -dist/ - -# packaging -*-autoloads.el -*-pkg.el diff --git a/test/commands/search/Eask b/test/commands/search/Eask deleted file mode 100644 index 51558d01..00000000 --- a/test/commands/search/Eask +++ /dev/null @@ -1,10 +0,0 @@ -(package "search" - "0.0.1" - "Test project for command `search'") - -(package-file "search.el") - -(source 'gnu) -(source 'melpa) - -(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test/commands/search/run.sh b/test/commands/search/run.sh deleted file mode 100755 index a3962e59..00000000 --- a/test/commands/search/run.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2023 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command `search` -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -echo "Test command 'search'..." -cd $(dirname "$0") - -should_error eask search -eask search company -eask search company dash --depth 0 -eask search company dash f s --depth 0 -g diff --git a/test/commands/source/run.sh b/test/commands/source/run.sh deleted file mode 100755 index 61365006..00000000 --- a/test/commands/source/run.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command/source errors -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -cd $(dirname "$0") - -echo "Testing source command... errors" -should_error eask source -should_error eask source add -should_error eask source add foo # name not found, show help - -should_error eask source delete -should_error eask source delete foo # name not found, show help diff --git a/test/commands/test/buttercup/.gitignore b/test/commands/test/buttercup/.gitignore deleted file mode 100644 index a50232f7..00000000 --- a/test/commands/test/buttercup/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# ignore these directories -/.git -/recipes - -# ignore generated files -*.elc - -# eask packages -.eask/ -dist/ - -# packaging -*-autoloads.el -*-pkg.el diff --git a/test/commands/test/buttercup/Eask b/test/commands/test/buttercup/Eask deleted file mode 100644 index d026ebbc..00000000 --- a/test/commands/test/buttercup/Eask +++ /dev/null @@ -1,13 +0,0 @@ -(package "buttercup" - "0.0.1" - "Test project for command `buttercup'") - -(package-file "buttercup.el") - -(source 'gnu) -(source 'melpa) - -(development - (depends-on "buttercup")) - -(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test/commands/test/buttercup/run.sh b/test/commands/test/buttercup/run.sh deleted file mode 100755 index 10a2400f..00000000 --- a/test/commands/test/buttercup/run.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command `buttercup` -# - -set -e - -echo "Test command 'buttercup'..." -cd $(dirname "$0") - -eask install-deps --dev -if eask test buttercup; then - # this runs all tests, so should error - echo "expected error" - exit 1 -fi - -# buttercup takes directories as arguments -eask test buttercup ./test-ok -if eask test buttercup ./test-ok ./test-fail; then - echo "expected error" - exit 1 -fi - -# buttercup does not take options -eask test buttercup --no-color ./test-ok - -# Because load-path is manually set, cannot refer to parent directories. -# Note this does work if you do ../buttercup/test-ok/, but not for any other directory. -if eask test buttercup ../ert/ 2>&1 | grep 'No suites defined'; then - echo "expected error" - exit 1 -fi diff --git a/test/commands/test/buttercup/test-fail/buttercup-test.el b/test/commands/test/buttercup/test-fail/buttercup-test.el deleted file mode 100644 index 6f61aad4..00000000 --- a/test/commands/test/buttercup/test-fail/buttercup-test.el +++ /dev/null @@ -1,31 +0,0 @@ -;;; buttercup-test.el --- Test the command buttercup -*- lexical-binding: t; -*- - -;; Copyright (C) 2022-2025 the Eask authors. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: - -;; Tests for the command buttercup - -;;; Code: - -(require 'buttercup) -(require 'debug) - -(describe "A failing suite" - (it "contains a spec with a false expectation" - (expect t :to-be nil))) - -;;; buttercup-test.el ends here diff --git a/test/commands/test/buttercup/test-ok/buttercup-test.el b/test/commands/test/buttercup/test-ok/buttercup-test.el deleted file mode 100644 index ed52b235..00000000 --- a/test/commands/test/buttercup/test-ok/buttercup-test.el +++ /dev/null @@ -1,31 +0,0 @@ -;;; buttercup-test.el --- Test the command buttercup -*- lexical-binding: t; -*- - -;; Copyright (C) 2022-2025 the Eask authors. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: - -;; Tests for the command buttercup - -;;; Code: - -(require 'buttercup) -(require 'debug) - -(describe "A suite" - (it "contains a spec with an expectation" - (expect t :to-be t))) - -;;; buttercup-test.el ends here diff --git a/test/commands/test/ecukes/Eask b/test/commands/test/ecukes/Eask deleted file mode 100644 index cc5ec20f..00000000 --- a/test/commands/test/ecukes/Eask +++ /dev/null @@ -1,13 +0,0 @@ -(package "ecukes" - "0.0.1" - "Test project for command `ecukes'") - -(package-file "ecukes.el") - -(source 'gnu) -(source 'melpa) - -(development - (depends-on "ecukes")) - -(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test/commands/test/ecukes/features/foo.feature b/test/commands/test/ecukes/features/foo.feature deleted file mode 100644 index e69de29b..00000000 diff --git a/test/commands/test/ecukes/features/step-definitions/ecukes-steps.el b/test/commands/test/ecukes/features/step-definitions/ecukes-steps.el deleted file mode 100644 index e69de29b..00000000 diff --git a/test/commands/test/ecukes/features/support/env.el b/test/commands/test/ecukes/features/support/env.el deleted file mode 100644 index e69de29b..00000000 diff --git a/test/commands/test/ecukes/run.sh b/test/commands/test/ecukes/run.sh deleted file mode 100644 index 4db00b88..00000000 --- a/test/commands/test/ecukes/run.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2024-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command `ecukes` -# - -set -e - -echo "Test command 'ecukes'..." -cd $(dirname "$0") - -eask test ecukes -eask test ecukes ./features/foo.feature diff --git a/test/commands/test/ert-runner/.gitignore b/test/commands/test/ert-runner/.gitignore deleted file mode 100644 index a50232f7..00000000 --- a/test/commands/test/ert-runner/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# ignore these directories -/.git -/recipes - -# ignore generated files -*.elc - -# eask packages -.eask/ -dist/ - -# packaging -*-autoloads.el -*-pkg.el diff --git a/test/commands/test/ert-runner/Eask b/test/commands/test/ert-runner/Eask deleted file mode 100644 index 3050d52e..00000000 --- a/test/commands/test/ert-runner/Eask +++ /dev/null @@ -1,13 +0,0 @@ -(package "ert-runner" - "0.0.1" - "Test project for command `ert-runner'") - -(package-file "ert-runner.el") - -(source 'gnu) -(source 'melpa) - -(development - (depends-on "ert-runner")) - -(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test/commands/test/ert-runner/run.sh b/test/commands/test/ert-runner/run.sh deleted file mode 100644 index 2310af2e..00000000 --- a/test/commands/test/ert-runner/run.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command `ert-runner` -# - -set -e - -echo "Test command 'ert-runner'..." -cd $(dirname "$0") - -eask test ert-runner ./test/*.el diff --git a/test/commands/test/ert-runner/test/ert-runner-test.el b/test/commands/test/ert-runner/test/ert-runner-test.el deleted file mode 100644 index 9255e819..00000000 --- a/test/commands/test/ert-runner/test/ert-runner-test.el +++ /dev/null @@ -1,31 +0,0 @@ -;;; ert-runner-test.el --- Test the command ert-runner -*- lexical-binding: t; -*- - -;; Copyright (C) 2022-2025 the Eask authors. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: - -;; Tests for the command ert-runner - -;;; Code: - -(require 'ert) -(require 'debug) - -(ert-deftest ert-runner-test-1 () - (should (= 1 1))) - -(provide 'ert-runner-test) -;;; ert-runner-test.el ends here diff --git a/test/commands/test/ert/.gitignore b/test/commands/test/ert/.gitignore deleted file mode 100644 index a50232f7..00000000 --- a/test/commands/test/ert/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# ignore these directories -/.git -/recipes - -# ignore generated files -*.elc - -# eask packages -.eask/ -dist/ - -# packaging -*-autoloads.el -*-pkg.el diff --git a/test/commands/test/ert/Eask b/test/commands/test/ert/Eask deleted file mode 100644 index 0d433c3d..00000000 --- a/test/commands/test/ert/Eask +++ /dev/null @@ -1,10 +0,0 @@ -(package "ert" - "0.0.1" - "Test project for command `ert'") - -(package-file "ert.el") - -(source 'gnu) -(source 'melpa) - -(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test/commands/test/ert/run.sh b/test/commands/test/ert/run.sh deleted file mode 100755 index 1d829364..00000000 --- a/test/commands/test/ert/run.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test command `ert` -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -echo "Test command 'ert'..." -cd $(dirname "$0") - -eask test ert ./test/*.el - -# regression -echo "Test ert: nil message" -eask test ert ./test-nil-message/*.el - -echo "Testing ert command... no files" -should_error eask test ert diff --git a/test/commands/test/ert/test-nil-message/ert-test.el b/test/commands/test/ert/test-nil-message/ert-test.el deleted file mode 100644 index 64d20a16..00000000 --- a/test/commands/test/ert/test-nil-message/ert-test.el +++ /dev/null @@ -1,30 +0,0 @@ -;;; ert-test.el --- Test the command ert -*- lexical-binding: t; -*- - -;; Copyright (C) 2024-2025 the Eask authors. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: - -;; Tests for the command ert - -;;; Code: - -(require 'ert) -(require 'debug) - -(ert-deftest ert-test-1 () - (should-not (message nil))) - -;;; ert-test.el ends here diff --git a/test/commands/test/ert/test/ert-test.el b/test/commands/test/ert/test/ert-test.el deleted file mode 100644 index fa5e835a..00000000 --- a/test/commands/test/ert/test/ert-test.el +++ /dev/null @@ -1,30 +0,0 @@ -;;; ert-test.el --- Test the command ert -*- lexical-binding: t; -*- - -;; Copyright (C) 2024-2025 the Eask authors. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: - -;; Tests for the command ert - -;;; Code: - -(require 'ert) -(require 'debug) - -(ert-deftest ert-test-1 () - (should (= 1 1))) - -;;; ert-test.el ends here diff --git a/test/options/.gitignore b/test/options/.gitignore deleted file mode 100644 index a50232f7..00000000 --- a/test/options/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# ignore these directories -/.git -/recipes - -# ignore generated files -*.elc - -# eask packages -.eask/ -dist/ - -# packaging -*-autoloads.el -*-pkg.el diff --git a/test/options/Eask b/test/options/Eask deleted file mode 100644 index ee70be40..00000000 --- a/test/options/Eask +++ /dev/null @@ -1,12 +0,0 @@ -(package "options" - "0.0.0" - "Test all options flag") - -(website-url "https://github.com/emacs-eask/options") -(keywords "test") - -(package-file "options.el") - -(source 'gnu) - -(depends-on "emacs" "26.1") diff --git a/test/options/run.sh b/test/options/run.sh deleted file mode 100755 index 6eb8911e..00000000 --- a/test/options/run.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2022-2025 the Eask authors. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -## Commentary: -# -# Test all options flag -# - -set -e - -source ./test/fixtures/home/scripts/testing.sh - -echo "Test all options flag" -cd $(dirname "$0") - -# Please have these flags in order, see `eask` file in the project root! -should_error eask info -g -should_error eask info --global -eask info -a -eask info --all -eask info -q -eask info --quick -eask info -f -eask info --force -eask info --debug -eask info --strict -eask info --allow-error -eask info --insecure -eask info --timestamps -eask info --log-level -eask info --elapsed-time -eask info --et -eask info --no-color -eask info --proxy localhost:8080 -eask info --http-proxy localhost:8080 -eask info --https-proxy localhost:8080 -eask info --no-proxy localhost:8080 -eask info -v 4 -eask info --verbose 4 From 3744c67d821ba607590be097496a8ca31e5297e8 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Fri, 28 Mar 2025 10:14:15 -0700 Subject: [PATCH 64/70] docs: Add sections on snapshots and timeouts --- .../content/Contributing/Testing/_index.en.md | 176 +++++++++++++++--- 1 file changed, 148 insertions(+), 28 deletions(-) diff --git a/docs/content/Contributing/Testing/_index.en.md b/docs/content/Contributing/Testing/_index.en.md index f9c55b40..7ae4b8ec 100644 --- a/docs/content/Contributing/Testing/_index.en.md +++ b/docs/content/Contributing/Testing/_index.en.md @@ -1,5 +1,5 @@ --- -title: Testing +title: 🔨 Testing weight: 20 --- @@ -33,15 +33,14 @@ For example | Name | Type | Default | Meaning | |:---------------|:-------|---------|:--------------------------------------------------------------------------------------------------| -| `ALLOW_UNSAFE` | bool* | false | Run tests in `testUnsafe` blocks. These can **overwrite** your personal emacs config or settings. | -| `DEBUG` | bool* | false | Print full output from commands in test. | +| `ALLOW_UNSAFE` | bool* | false | Run tests in `testUnsafe` blocks. These can **overwrite** your personal emacs config or settings. | +| `DEBUG` | bool* | false | Print full output from commands in test. | | `EASK_COMMAND` | path | "eask" | Path to Eask. Usually either `eask` or `$PWD/bin/eask` to use local changes. | | `TIMEOUT` | number | 25000 | Command timeout in ms. Note this is different than Jest's timeout, which should be greater. | (*) Node.js handles environment variables as strings. That means that `DEBUG=0`, `DEBUG=false` all _enable_ `DEBUG`. The only setting which disables a boolean flag is null, for example `DEBUG=` - ### How to Write a Test **Folder structure** @@ -88,10 +87,6 @@ It's a good idea to add a nested `describe` when tests run in different director For each test directory you should create a new `TestContext` object. All `runEask` commands will use the `TestContext`'s working directory. -You can also use `TestContext.cleanUp()` to abort any still-running commands that were called in that context. -Note that it sends a signal to *all* processes started using the context's `runEask` command. -If used in an `afterEach` hook (i.e. after every test) it may result in failures. - Jest's tests are in `test` blocks. Note that `it` is an alias for `test`. Tests can be selectively disabled in code, like so: - `test.only(name, fn)` runs only that test in the file @@ -104,26 +99,150 @@ See Jest's [expect()](https://jestjs.io/docs/expect) API for more info. Uncaught errors thrown in a `test` block will fail it and report the error. That's why many tests don't have an `expect` call, they simply check that the command succeeds. +Output from `runEask` is wrapped in a helper class `CommandOutput` which provides some transformation methods. +For example, if you have `const out = await ctx.runEask("analyze");`, then +- `out.combined()` concatenates both stdout and stderr as a string, +- `out.raw()` returns a plain object with just `stdout` and `stderr` as properties, +- `out.sanitized()` replaces all absolute paths that match the context's path + +Since the class wraps the output of Node's `exec()` method you can still access `stdout` and `stderr`: +``` javascript +const { stderr, stdout } = await ctx.runEask("analyze"); +``` + +Some commands create files or directories which should be removed after the test runs. +For example, `eask generate ignore elisp` creates a `.gitignore` file. +You can use the context's `removeFiles` method to remove files and directories relative +to the context's path: +``` javascript + describe("Generating", () => { + beforeAll(async () => await ctx.removeFiles(".gitignore")); + afterAll(async () => await ctx.removeFiles(".gitignore")); + + it("eask generate ignore elisp", async () => { + await ctx.runEask("generate ignore elisp"); + }); + }); +``` +Note that `removeFiles()` will recursively remove directories, but does not accept patterns. +So, to remove all files in `./test` just call `ctx.remove("test")`. +You can pass multiple files or directory names in single call: `ctx.remove("test", ".gitignore")`. + +Use `TestContext.cleanUp()` to immediately abort any still-running commands that were called in that context. +Use this if Jest reports "open handles were detected" after a test run. +Note that `cleanUp` sends a signal to *all* processes started using the context's `runEask` command. +If used in an `afterEach` hook (i.e. after every test) it may result in failures. + +### Snapshots + +[Snapshot tests](https://jestjs.io/docs/snapshot-testing) match the output of a test against a saved copy of the expected output. +For example +``` javascript +test("eask analyze", async () => { + const res = await ctx.runEask("analyze"); + expect(res.raw()).toMatchSnapshot(); +}); +``` + +The first time you run this Jest will create a new snapshot saved in an adjacent `__snapshot__` directory. + +You should check this file in to version control as it forms a critical part of the test. +If the snapshot changes, you can update the snapshot by running Jest with option `-u`, for example, +`npm run test -- -u` will update all changed snapshots. + +Any type of output can be used for a snapshot test. You could snapshot the contents of a file after changing it +``` javascript +test("eask analyze", async () => { + await ctx.runEask("foo"); + const file = ctx.fileContents("Easkfile"); // file as a string + expect(file).toMatchSnapshot(); +}); +``` + +Often snapshots will include data that varies with time or environment, for example timestamps or file paths. +The snapshot of `eask analyze` contains absolute file paths that will be different on every machine. + +Output from `runEask` is wrapped in a helper class `CommandOutput` which provides some transformation methods. +The simplest just removes the absolute file paths: +``` javascript +it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res.sanitized() // a CommandOutput object with absolute paths replaced by "~" + .raw(); // an object { stderr, stdout } suitable for snapshotting + expect(resClean).toMatchSnapshot(); +}); +``` + +You can include custom replacement functions. Here, numbers will be replaced by `"x"`. +Then strings `"x:x"` will be replaced by `"y"`. +``` javascript +it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res + .sanitized( + (x) => x.replace(/[0-9]+/g, "x"), + (x) => x.replaceAll("x:x", "y"), + ) + .raw(); + expect(resClean).toMatchSnapshot(); +}); +``` + +It's important to use the `g` regex flag so all occurrences of the match are replaced, or you could use `replaceAll`. +User provided functions run in addition to the default sanitize function and run in the order they were given. + +### Timeouts + +There are two timeout settings, one for Jest and one for Node's `exec()`. +All timeout values are in milliseconds. + +Since the `exec()` timeout immediately terminates the running command and reports output, it is much better to +use that instead of Jest's timeout. + +To change a timeout for a single command +``` javascript +ctx.runEask("analyze", { timeout: 10000}) +``` + +To change the global timeout for a single run, use the env var +``` shell +env TIMEOUT=30000 npm run test +``` + +To change the global timeout permanently, set the default in `./helpers.js`. + +If you change either global timeout, **make sure the global Jest timeout is greater** by setting it in `package.json` + +``` json +"jest": { + "rootDir": "./test/jest", + "testTimeout": 40000 +} +``` + ### Patterns Here are some common patterns for testing commands. Each of these assumes that `ctx` is a `TestContext` object. -Check a command succeeds: +**Check a command succeeds:** ``` javascript test("eask analyze", async () => { await ctx.runEask("analyze"); }); ``` -Check a command fails: +Uncaught errors thrown in a `test` block will fail the test and report the error. +Failed commands will include stderr and stdout. + +**Check a command fails:** ``` javascript test("eask analyze", async () => { await expect(ctx.runEask("analyze")).rejects.toThrow(); }); ``` -Check a command fails with a specific code: +**Check a command fails with a specific code:** ``` javascript test("eask link add should error", async () => { // the error object should have property code = 1 @@ -133,17 +252,22 @@ test("eask link add should error", async () => { }); ``` -Check a command produces some output: +**Check a command produces some output:** ``` javascript test("eask analyze", async () => { - const { stdout, stderr } = await ctx.runEask("analyze"); - expect(stderr).toMatch("success"); // should apppear as a substring + const out = await ctx.runEask("analyze"); + expect(out.stderr).toMatch("success"); // should apppear as a substring // If you want to check both `stderr` and `stdout`, just concatenate them - expect(stdout + "/n" + stderr).toMatch("success"); + expect(out.stdout + "/n" + out.stderr).toMatch("success"); + // Same thing using helper methods + expect(out.combined()).toMatch("success"); }); ``` -Match command output against a snapshot: +**Check command output against a snapshot:** + +Simple output matching + ``` javascript test("eask analyze", async () => { const res = await ctx.runEask("analyze"); @@ -151,15 +275,10 @@ test("eask analyze", async () => { }); ``` -The first time you run this Jest will create a new snapshot. You should check this in to version control. -If the snapshot changes, you can update the snapshot by running Jest with option `-u`, for example, -`npm run test -- -u` will update all changed snapshots. +Update all changed snapshots: +`npm run test -- -u` -Often snapshots will include data that varies with time or environment, for example timestamps or file paths. -The snapshot above includes absolute file paths that will be different on every machine. - -Output from `runEask` is wrapped in a helper class `CommandOutput` which provides some transformations to help. -The simplest just removes the absolute file paths: +Remove absolute file paths from output: ``` javascript it("matches snapshot", async () => { const res = await ctx.runEask("analyze"); @@ -169,8 +288,7 @@ it("matches snapshot", async () => { }); ``` -You can include custom replacement functions. Here, numbers will be replaced by `"x"`. -Then strings `"x:x"` will be replaced by `"y"`. +Apply custom transformations for sanitizing output: ``` javascript it("matches snapshot", async () => { const res = await ctx.runEask("analyze"); @@ -184,10 +302,12 @@ it("matches snapshot", async () => { }); ``` -It's important to use the `g` regex flag so all occurrences of the match are replaced, or you could use `replaceAll`. User provided functions run in addition to the default sanitize function and run in the order they were given. -Commands which modify global environment, for example with `-c` or `-g` options: +**Commands which modify the user's environment:** + +For example, commands which use `-c` or `-g` options. + ``` javascript const { testUnsafe } = require('./helpers'); From 8799ad04886a818d57f3f27feb8a9a4b0a1e46a5 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Fri, 28 Mar 2025 15:31:34 -0700 Subject: [PATCH 65/70] docs: move Testing page onto "Developing Eask" page --- .../Contributing/Developing-Eask/_index.en.md | 331 +++++++++++++++++- .../content/Contributing/Testing/_index.en.md | 330 ----------------- 2 files changed, 322 insertions(+), 339 deletions(-) delete mode 100644 docs/content/Contributing/Testing/_index.en.md diff --git a/docs/content/Contributing/Developing-Eask/_index.en.md b/docs/content/Contributing/Developing-Eask/_index.en.md index 772909c6..d15c9e3a 100644 --- a/docs/content/Contributing/Developing-Eask/_index.en.md +++ b/docs/content/Contributing/Developing-Eask/_index.en.md @@ -5,7 +5,7 @@ weight: 20 {{< toc >}} -### 🚩 Prerequisites +## 🚩 Prerequisites To make changes to Eask, you should have: @@ -14,7 +14,7 @@ To make changes to Eask, you should have: 3. [yargs][] for CLI parser. 4. [Emacs][], 26.1 or above! -### 📝 Building +## 📝 Building To build the development environment, you would have to install Eask using the [build from source](https://emacs-eask.github.io/Getting-Started/Install-Eask/#-build-from-source) @@ -31,16 +31,329 @@ It should print out the location of the `eask` executable. You should be able to identify the Eask executable's location, even you have multiple Eask versions installed! -### 📈 Testing +## 📈 Testing -Eask does not offer local testing, all our tests are accomplished using GitHub -Actions. Please fork our repository, and push your changes to your fork. GitHub -Actions should pick up the test for you! +Local testing for Eask is done using the [Jest](https://jestjs.io) testing framework. +Jest is a mature and well supported testing framework written in Javascript. +Jest was chosen for much the [same reasons as Javascript](https://emacs-eask.github.io/FAQ/#-why-javascript) was chosen for this project. +In addition, Jest is easy to learn and has built in support for snapshot based testing. -Make sure you have GitHub Actions enabled in your repository (forked). Got to -**Settings** -> **Actions** -> **General** -> **Actions Permissions**; make sure -you have checked the correct options. +### Running Tests +If you have not done so already, run `npm install --dev` + +Always run from the project root (i.e. same directory as `package.json`) + +- run all tests `npm run test` +- run a single test `npm run test path/to/test.js` +- run tests with full output `npm run test-debug` +- remove files created during test `npm run test-reset` + +Since `npm run test` just runs Jest, you can also pass Jest options to the +commands above. +For example +- run tests whose names (in `test()` blocks) match `npm run test -t 'eask lint .*'` +- re-run failed tests `npm run test -f` + +### Environment Vars + +| Name | Type | Default | Meaning | +|:---------------|:-------|---------|:--------------------------------------------------------------------------------------------------| +| `ALLOW_UNSAFE` | bool* | false | Run tests in `testUnsafe` blocks. These can **overwrite** your personal emacs config or settings. | +| `DEBUG` | bool* | false | Print full output from commands in test. | +| `EASK_COMMAND` | path | "eask" | Path to Eask. Usually either `eask` or `$PWD/bin/eask` to use local changes. | +| `TIMEOUT` | number | 25000 | Command timeout in ms. Note this is different than Jest's timeout, which should be greater. | + +(*) Node.js handles environment variables as strings. That means that `DEBUG=0`, `DEBUG=false` all _enable_ `DEBUG`. + The only setting which disables a boolean flag is null, for example `DEBUG=` + +### How to Write a Test + +**Folder structure** + +Tests should be in `test/js`. +Related tests should be in the same file with the suffix `.test.js` and are usually named after the +feature or command that they test, for example `link.test.js` tests the `eask link` command. + +If the test needs some specific project files, put them in a new folder within `test/js` +For example, files in `test/js/foo` would be expected to be for `foo.test.js`. + +The exception is `test/js/empty`, which is simply an empty folder. +If you use it, make sure to run `eask clean all` before your tests. + +**Test File structure** + +``` javascript +const { TestContext } = require("./helpers"); + +describe("emacs", () => { + const ctx = new TestContext("./test/jest/empty"); + + beforeAll(async () => await ctx.runEask("clean all")); + afterAll(() => ctx.cleanUp); + + test("eask emacs --version", async () => { + await ctx.runEask("emacs --version"); + }); + + test("eask emacs --batch --eval", async () => { + await ctx.runEask( + 'emacs --batch --eval "(require (quote ert))" --eval "(ert-deftest mytest () (should-not (display-graphic-p)))" -f ert-run-tests-batch', + ); + }); +}); +``` + +In Jest, you group related tests using `describe`. Tests in the same `describe` block can share setup/teardown code, +can be disabled as a group and are grouped under the same heading in output. + +`describe` blocks can be nested within other `describe` blocks. +It's a good idea to add a nested `describe` when tests run in different directories, or to match a "given, when, then" style of testing. + +For each test directory you should create a new `TestContext` object. +All `runEask` commands will use the `TestContext`'s working directory. + +Jest's tests are in `test` blocks. Note that `it` is an alias for `test`. +Tests can be selectively disabled in code, like so: +- `test.only(name, fn)` runs only that test in the file +- `test.skip(name, fn)` skips running the test but still prints its name +- `test.failing(name, fn)` invert the meaning of the test: it *should* fail. + +The `expect` API matches values in different ways and usually prints a diff as part of the failure report. +See Jest's [expect()](https://jestjs.io/docs/expect) API for more info. + +Uncaught errors thrown in a `test` block will fail it and report the error. +That's why many tests don't have an `expect` call, they simply check that the command succeeds. + +Output from `runEask` is wrapped in a helper class `CommandOutput` which provides some transformation methods. +For example, if you have `const out = await ctx.runEask("analyze");`, then +- `out.combined()` concatenates both stdout and stderr as a string, +- `out.raw()` returns a plain object with just `stdout` and `stderr` as properties, +- `out.sanitized()` replaces all absolute paths that match the context's path + +Since the class wraps the output of Node's `exec()` method you can still access `stdout` and `stderr`: +``` javascript +const { stderr, stdout } = await ctx.runEask("analyze"); +``` + +Some commands create files or directories which should be removed after the test runs. +For example, `eask generate ignore elisp` creates a `.gitignore` file. +You can use the context's `removeFiles` method to remove files and directories relative +to the context's path: +``` javascript + describe("Generating", () => { + beforeAll(async () => await ctx.removeFiles(".gitignore")); + afterAll(async () => await ctx.removeFiles(".gitignore")); + + it("eask generate ignore elisp", async () => { + await ctx.runEask("generate ignore elisp"); + }); + }); +``` +Note that `removeFiles()` will recursively remove directories, but does not accept patterns. +So, to remove all files in `./test` just call `ctx.remove("test")`. +You can pass multiple files or directory names in single call: `ctx.remove("test", ".gitignore")`. + +Use `TestContext.cleanUp()` to immediately abort any still-running commands that were called in that context. +Use this if Jest reports "open handles were detected" after a test run. +Note that `cleanUp` sends a signal to *all* processes started using the context's `runEask` command. +If used in an `afterEach` hook (i.e. after every test) it may result in failures. + +### Snapshots + +[Snapshot tests](https://jestjs.io/docs/snapshot-testing) match the output of a test against a saved copy of the expected output. +For example +``` javascript +test("eask analyze", async () => { + const res = await ctx.runEask("analyze"); + expect(res.raw()).toMatchSnapshot(); +}); +``` + +The first time you run this Jest will create a new snapshot saved in an adjacent `__snapshot__` directory. + +You should check this file in to version control as it forms a critical part of the test. +If the snapshot changes, you can update the snapshot by running Jest with option `-u`, for example, +`npm run test -- -u` will update all changed snapshots. + +Any type of output can be used for a snapshot test. You could snapshot the contents of a file after changing it +``` javascript +test("eask analyze", async () => { + await ctx.runEask("foo"); + const file = ctx.fileContents("Easkfile"); // file as a string + expect(file).toMatchSnapshot(); +}); +``` + +Often snapshots will include data that varies with time or environment, for example timestamps or file paths. +The snapshot of `eask analyze` contains absolute file paths that will be different on every machine. + +Output from `runEask` is wrapped in a helper class `CommandOutput` which provides some transformation methods. +The simplest just removes the absolute file paths: +``` javascript +it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res.sanitized() // a CommandOutput object with absolute paths replaced by "~" + .raw(); // an object { stderr, stdout } suitable for snapshotting + expect(resClean).toMatchSnapshot(); +}); +``` + +You can include custom replacement functions. Here, numbers will be replaced by `"x"`. +Then strings `"x:x"` will be replaced by `"y"`. +``` javascript +it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res + .sanitized( + (x) => x.replace(/[0-9]+/g, "x"), + (x) => x.replaceAll("x:x", "y"), + ) + .raw(); + expect(resClean).toMatchSnapshot(); +}); +``` + +It's important to use the `g` regex flag so all occurrences of the match are replaced, or you could use `replaceAll`. +User provided functions run in addition to the default sanitize function and run in the order they were given. + +### Timeouts + +There are two timeout settings, one for Jest and one for Node's `exec()`. +All timeout values are in milliseconds. + +Since the `exec()` timeout immediately terminates the running command and reports output, it is much better to +use that instead of Jest's timeout. + +To change a timeout for a single command +``` javascript +ctx.runEask("analyze", { timeout: 10000}) +``` + +To change the global timeout for a single run, use the env var +``` shell +env TIMEOUT=30000 npm run test +``` + +To change the global timeout permanently, set the default in `./helpers.js`. + +If you change either global timeout, **make sure the global Jest timeout is greater** by setting it in `package.json` + +``` json +"jest": { + "rootDir": "./test/jest", + "testTimeout": 40000 +} +``` + +### Patterns + +Here are some common patterns for testing commands. +Each of these assumes that `ctx` is a `TestContext` object. + +**Check a command succeeds:** +``` javascript +test("eask analyze", async () => { + await ctx.runEask("analyze"); +}); +``` + +Uncaught errors thrown in a `test` block will fail the test and report the error. +Failed commands will include stderr and stdout. + +**Check a command fails:** +``` javascript +test("eask analyze", async () => { + await expect(ctx.runEask("analyze")).rejects.toThrow(); +}); +``` + +**Check a command fails with a specific code:** +``` javascript +test("eask link add should error", async () => { + // the error object should have property code = 1 + await expect(ctx.runEask("link add")).rejects.toMatchObject({ + code: 1, + }); +}); +``` + +**Check a command produces some output:** +``` javascript +test("eask analyze", async () => { + const out = await ctx.runEask("analyze"); + expect(out.stderr).toMatch("success"); // should apppear as a substring + // If you want to check both `stderr` and `stdout`, just concatenate them + expect(out.stdout + "/n" + out.stderr).toMatch("success"); + // Same thing using helper methods + expect(out.combined()).toMatch("success"); +}); +``` + +**Check command output against a snapshot:** + +Simple output matching + +``` javascript +test("eask analyze", async () => { + const res = await ctx.runEask("analyze"); + expect(res).toMatchSnapshot(); +}); +``` + +Update all changed snapshots: +`npm run test -- -u` + +Remove absolute file paths from output: +``` javascript +it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res.sanitized() // a CommandOutput object with absolute paths replaced by "~" + .raw(); // an object { stderr, stdout } suitable for snapshotting + expect(resClean).toMatchSnapshot(); +}); +``` + +Apply custom transformations for sanitizing output: +``` javascript +it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res + .sanitized( + (x) => x.replace(/[0-9]+/g, "x"), + (x) => x.replace(/x:x/g, "y"), + ) + .raw(); + expect(resClean).toMatchSnapshot(); +}); +``` + +User provided functions run in addition to the default sanitize function and run in the order they were given. + +**Commands which modify the user's environment:** + +For example, commands which use `-c` or `-g` options. + +``` javascript +const { testUnsafe } = require('./helpers'); + +// this will only run if ALLOW_UNSAFE is != 0 +testUnsafe("global install", async () => { + // this installs in ~/.eask and changes ~/Eask + await ctx.runEask("install -g foo"); +}); +``` + +### Common Problems + +- When using `runEask()`, pass only the Eask *arguments*, not the `eask` command itself. +- Always `await` any expressions that trigger commands. +- When using `expect(...).rejects` it should be awaited so that the promise rejects before the test completes. +- The folder argument to `TestContext` should be relative to project root, if it doesn't exist you may get an error `ENOENT` +- If you get an error from Jest reporting open handles, then try using `afterAll(() => ctx.cleanUp())` +- There are two timeout values: one used for Jest (set in `package.json`), and one used for `node.exec`, set via env var in `./helpers.js`. + The `node.exec` timeout is set lower than the Jest one, so changing timeout values for tests or by `jest.setTimeout` usually won't + have an effect. Instead set the timeout on the command itself `runEask("eask emacs", { timeout: 100000 })` diff --git a/docs/content/Contributing/Testing/_index.en.md b/docs/content/Contributing/Testing/_index.en.md deleted file mode 100644 index 7ae4b8ec..00000000 --- a/docs/content/Contributing/Testing/_index.en.md +++ /dev/null @@ -1,330 +0,0 @@ ---- -title: 🔨 Testing -weight: 20 ---- - -{{< toc >}} - -This describes how to run tests locally, and how to write new tests for Eask. - -Local testing for Eask is done using the [Jest](https://jestjs.io) testing framework. -Jest is a mature and well supported testing framework written in Javascript. -Jest was chosen for much the [same reasons as Javascript](https://emacs-eask.github.io/FAQ/#-why-javascript) was chosen for this project. -In addition, Jest is easy to learn and has built in support for snapshot based testing. - -### Running Tests - -If you have not done so already, run `npm install --dev` - -Always run from the project root (i.e. same directory as `package.json`) - -- run all tests `npm run test` -- run a single test `npm run test path/to/test.js` -- run tests with full output `npm run test-debug` -- remove files created during test `npm run test-reset` - -Since `npm run test` just runs Jest, you can also pass Jest options to the -commands above. -For example -- run tests whose names (in `test()` blocks) match `npm run test -t 'eask lint .*'` -- re-run failed tests `npm run test -f` - -### Environment Vars - -| Name | Type | Default | Meaning | -|:---------------|:-------|---------|:--------------------------------------------------------------------------------------------------| -| `ALLOW_UNSAFE` | bool* | false | Run tests in `testUnsafe` blocks. These can **overwrite** your personal emacs config or settings. | -| `DEBUG` | bool* | false | Print full output from commands in test. | -| `EASK_COMMAND` | path | "eask" | Path to Eask. Usually either `eask` or `$PWD/bin/eask` to use local changes. | -| `TIMEOUT` | number | 25000 | Command timeout in ms. Note this is different than Jest's timeout, which should be greater. | - -(*) Node.js handles environment variables as strings. That means that `DEBUG=0`, `DEBUG=false` all _enable_ `DEBUG`. - The only setting which disables a boolean flag is null, for example `DEBUG=` - -### How to Write a Test - -**Folder structure** - -Tests should be in `test/js`. -Related tests should be in the same file with the suffix `.test.js` and are usually named after the -feature or command that they test, for example `link.test.js` tests the `eask link` command. - -If the test needs some specific project files, put them in a new folder within `test/js` -For example, files in `test/js/foo` would be expected to be for `foo.test.js`. - -The exception is `test/js/empty`, which is simply an empty folder. -If you use it, make sure to run `eask clean all` before your tests. - -**Test File structure** - -``` javascript -const { TestContext } = require("./helpers"); - -describe("emacs", () => { - const ctx = new TestContext("./test/jest/empty"); - - beforeAll(async () => await ctx.runEask("clean all")); - afterAll(() => ctx.cleanUp); - - test("eask emacs --version", async () => { - await ctx.runEask("emacs --version"); - }); - - test("eask emacs --batch --eval", async () => { - await ctx.runEask( - 'emacs --batch --eval "(require (quote ert))" --eval "(ert-deftest mytest () (should-not (display-graphic-p)))" -f ert-run-tests-batch', - ); - }); -}); -``` - -In Jest, you group related tests using `describe`. Tests in the same `describe` block can share setup/teardown code, -can be disabled as a group and are grouped under the same heading in output. - -`describe` blocks can be nested within other `describe` blocks. -It's a good idea to add a nested `describe` when tests run in different directories, or to match a "given, when, then" style of testing. - -For each test directory you should create a new `TestContext` object. -All `runEask` commands will use the `TestContext`'s working directory. - -Jest's tests are in `test` blocks. Note that `it` is an alias for `test`. -Tests can be selectively disabled in code, like so: -- `test.only(name, fn)` runs only that test in the file -- `test.skip(name, fn)` skips running the test but still prints its name -- `test.failing(name, fn)` invert the meaning of the test: it *should* fail. - -The `expect` API matches values in different ways and usually prints a diff as part of the failure report. -See Jest's [expect()](https://jestjs.io/docs/expect) API for more info. - -Uncaught errors thrown in a `test` block will fail it and report the error. -That's why many tests don't have an `expect` call, they simply check that the command succeeds. - -Output from `runEask` is wrapped in a helper class `CommandOutput` which provides some transformation methods. -For example, if you have `const out = await ctx.runEask("analyze");`, then -- `out.combined()` concatenates both stdout and stderr as a string, -- `out.raw()` returns a plain object with just `stdout` and `stderr` as properties, -- `out.sanitized()` replaces all absolute paths that match the context's path - -Since the class wraps the output of Node's `exec()` method you can still access `stdout` and `stderr`: -``` javascript -const { stderr, stdout } = await ctx.runEask("analyze"); -``` - -Some commands create files or directories which should be removed after the test runs. -For example, `eask generate ignore elisp` creates a `.gitignore` file. -You can use the context's `removeFiles` method to remove files and directories relative -to the context's path: -``` javascript - describe("Generating", () => { - beforeAll(async () => await ctx.removeFiles(".gitignore")); - afterAll(async () => await ctx.removeFiles(".gitignore")); - - it("eask generate ignore elisp", async () => { - await ctx.runEask("generate ignore elisp"); - }); - }); -``` -Note that `removeFiles()` will recursively remove directories, but does not accept patterns. -So, to remove all files in `./test` just call `ctx.remove("test")`. -You can pass multiple files or directory names in single call: `ctx.remove("test", ".gitignore")`. - -Use `TestContext.cleanUp()` to immediately abort any still-running commands that were called in that context. -Use this if Jest reports "open handles were detected" after a test run. -Note that `cleanUp` sends a signal to *all* processes started using the context's `runEask` command. -If used in an `afterEach` hook (i.e. after every test) it may result in failures. - -### Snapshots - -[Snapshot tests](https://jestjs.io/docs/snapshot-testing) match the output of a test against a saved copy of the expected output. -For example -``` javascript -test("eask analyze", async () => { - const res = await ctx.runEask("analyze"); - expect(res.raw()).toMatchSnapshot(); -}); -``` - -The first time you run this Jest will create a new snapshot saved in an adjacent `__snapshot__` directory. - -You should check this file in to version control as it forms a critical part of the test. -If the snapshot changes, you can update the snapshot by running Jest with option `-u`, for example, -`npm run test -- -u` will update all changed snapshots. - -Any type of output can be used for a snapshot test. You could snapshot the contents of a file after changing it -``` javascript -test("eask analyze", async () => { - await ctx.runEask("foo"); - const file = ctx.fileContents("Easkfile"); // file as a string - expect(file).toMatchSnapshot(); -}); -``` - -Often snapshots will include data that varies with time or environment, for example timestamps or file paths. -The snapshot of `eask analyze` contains absolute file paths that will be different on every machine. - -Output from `runEask` is wrapped in a helper class `CommandOutput` which provides some transformation methods. -The simplest just removes the absolute file paths: -``` javascript -it("matches snapshot", async () => { - const res = await ctx.runEask("analyze"); - const resClean = res.sanitized() // a CommandOutput object with absolute paths replaced by "~" - .raw(); // an object { stderr, stdout } suitable for snapshotting - expect(resClean).toMatchSnapshot(); -}); -``` - -You can include custom replacement functions. Here, numbers will be replaced by `"x"`. -Then strings `"x:x"` will be replaced by `"y"`. -``` javascript -it("matches snapshot", async () => { - const res = await ctx.runEask("analyze"); - const resClean = res - .sanitized( - (x) => x.replace(/[0-9]+/g, "x"), - (x) => x.replaceAll("x:x", "y"), - ) - .raw(); - expect(resClean).toMatchSnapshot(); -}); -``` - -It's important to use the `g` regex flag so all occurrences of the match are replaced, or you could use `replaceAll`. -User provided functions run in addition to the default sanitize function and run in the order they were given. - -### Timeouts - -There are two timeout settings, one for Jest and one for Node's `exec()`. -All timeout values are in milliseconds. - -Since the `exec()` timeout immediately terminates the running command and reports output, it is much better to -use that instead of Jest's timeout. - -To change a timeout for a single command -``` javascript -ctx.runEask("analyze", { timeout: 10000}) -``` - -To change the global timeout for a single run, use the env var -``` shell -env TIMEOUT=30000 npm run test -``` - -To change the global timeout permanently, set the default in `./helpers.js`. - -If you change either global timeout, **make sure the global Jest timeout is greater** by setting it in `package.json` - -``` json -"jest": { - "rootDir": "./test/jest", - "testTimeout": 40000 -} -``` - -### Patterns - -Here are some common patterns for testing commands. -Each of these assumes that `ctx` is a `TestContext` object. - -**Check a command succeeds:** -``` javascript -test("eask analyze", async () => { - await ctx.runEask("analyze"); -}); -``` - -Uncaught errors thrown in a `test` block will fail the test and report the error. -Failed commands will include stderr and stdout. - -**Check a command fails:** -``` javascript -test("eask analyze", async () => { - await expect(ctx.runEask("analyze")).rejects.toThrow(); -}); -``` - -**Check a command fails with a specific code:** -``` javascript -test("eask link add should error", async () => { - // the error object should have property code = 1 - await expect(ctx.runEask("link add")).rejects.toMatchObject({ - code: 1, - }); -}); -``` - -**Check a command produces some output:** -``` javascript -test("eask analyze", async () => { - const out = await ctx.runEask("analyze"); - expect(out.stderr).toMatch("success"); // should apppear as a substring - // If you want to check both `stderr` and `stdout`, just concatenate them - expect(out.stdout + "/n" + out.stderr).toMatch("success"); - // Same thing using helper methods - expect(out.combined()).toMatch("success"); -}); -``` - -**Check command output against a snapshot:** - -Simple output matching - -``` javascript -test("eask analyze", async () => { - const res = await ctx.runEask("analyze"); - expect(res).toMatchSnapshot(); -}); -``` - -Update all changed snapshots: -`npm run test -- -u` - -Remove absolute file paths from output: -``` javascript -it("matches snapshot", async () => { - const res = await ctx.runEask("analyze"); - const resClean = res.sanitized() // a CommandOutput object with absolute paths replaced by "~" - .raw(); // an object { stderr, stdout } suitable for snapshotting - expect(resClean).toMatchSnapshot(); -}); -``` - -Apply custom transformations for sanitizing output: -``` javascript -it("matches snapshot", async () => { - const res = await ctx.runEask("analyze"); - const resClean = res - .sanitized( - (x) => x.replace(/[0-9]+/g, "x"), - (x) => x.replace(/x:x/g, "y"), - ) - .raw(); - expect(resClean).toMatchSnapshot(); -}); -``` - -User provided functions run in addition to the default sanitize function and run in the order they were given. - -**Commands which modify the user's environment:** - -For example, commands which use `-c` or `-g` options. - -``` javascript -const { testUnsafe } = require('./helpers'); - -// this will only run if ALLOW_UNSAFE is != 0 -testUnsafe("global install", async () => { - // this installs in ~/.eask and changes ~/Eask - await ctx.runEask("install -g foo"); -}); -``` - -### Common Problems - -- When using `runEask()`, pass only the Eask *arguments*, not the `eask` command itself. -- Always `await` any expressions that trigger commands. -- When using `expect(...).rejects` it should be awaited so that the promise rejects before the test completes. -- The folder argument to `TestContext` should be relative to project root, if it doesn't exist you may get an error `ENOENT` -- If you get an error from Jest reporting open handles, then try using `afterAll(() => ctx.cleanUp())` -- There are two timeout values: one used for Jest (set in `package.json`), and one used for `node.exec`, set via env var in `./helpers.js`. - The `node.exec` timeout is set lower than the Jest one, so changing timeout values for tests or by `jest.setTimeout` usually won't - have an effect. Instead set the timeout on the command itself `runEask("eask emacs", { timeout: 100000 })` From a5e7c0db003f78bbe866adfb0232073c6ac1bdcf Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Fri, 28 Mar 2025 15:55:21 -0700 Subject: [PATCH 66/70] Rename buttercup.test.js and outdated.test.js consistently --- .github/workflows/outdated_upgrade.yml | 2 +- .github/workflows/test_buttercup.yml | 2 +- test/jest/{outdated.test.js => outdated-upgrade.test.js} | 2 +- test/jest/{outdated_upgrade => outdated-upgrade}/.gitignore | 0 test/jest/{outdated_upgrade => outdated-upgrade}/Eask | 0 .../jest/{outdated_upgrade => outdated-upgrade}/make-outdate.el | 0 test/jest/{buttercup.test.js => test-buttercup.test.js} | 0 7 files changed, 3 insertions(+), 3 deletions(-) rename test/jest/{outdated.test.js => outdated-upgrade.test.js} (89%) rename test/jest/{outdated_upgrade => outdated-upgrade}/.gitignore (100%) rename test/jest/{outdated_upgrade => outdated-upgrade}/Eask (100%) rename test/jest/{outdated_upgrade => outdated-upgrade}/make-outdate.el (100%) rename test/jest/{buttercup.test.js => test-buttercup.test.js} (100%) diff --git a/.github/workflows/outdated_upgrade.yml b/.github/workflows/outdated_upgrade.yml index 1aa533f6..ce5360cc 100644 --- a/.github/workflows/outdated_upgrade.yml +++ b/.github/workflows/outdated_upgrade.yml @@ -52,4 +52,4 @@ jobs: - name: Testing... run: | - npm run test-unsafe test/jest/outdated.test.js + npm run test-unsafe test/jest/outdated-upgrade.test.js diff --git a/.github/workflows/test_buttercup.yml b/.github/workflows/test_buttercup.yml index 683343d1..cb78bc39 100644 --- a/.github/workflows/test_buttercup.yml +++ b/.github/workflows/test_buttercup.yml @@ -52,4 +52,4 @@ jobs: - name: Testing... run: | - npm run test-unsafe test/jest/buttercup.test.js + npm run test-unsafe test/jest/test-buttercup.test.js diff --git a/test/jest/outdated.test.js b/test/jest/outdated-upgrade.test.js similarity index 89% rename from test/jest/outdated.test.js rename to test/jest/outdated-upgrade.test.js index 39dc934b..660545ed 100644 --- a/test/jest/outdated.test.js +++ b/test/jest/outdated-upgrade.test.js @@ -1,7 +1,7 @@ const { TestContext } = require("./helpers"); describe("outdated and upgrade", () => { - const ctx = new TestContext("./test/jest/outdated_upgrade"); + const ctx = new TestContext("./test/jest/outdated-upgrade"); beforeAll(async () => { await ctx.runEask("install-deps"); diff --git a/test/jest/outdated_upgrade/.gitignore b/test/jest/outdated-upgrade/.gitignore similarity index 100% rename from test/jest/outdated_upgrade/.gitignore rename to test/jest/outdated-upgrade/.gitignore diff --git a/test/jest/outdated_upgrade/Eask b/test/jest/outdated-upgrade/Eask similarity index 100% rename from test/jest/outdated_upgrade/Eask rename to test/jest/outdated-upgrade/Eask diff --git a/test/jest/outdated_upgrade/make-outdate.el b/test/jest/outdated-upgrade/make-outdate.el similarity index 100% rename from test/jest/outdated_upgrade/make-outdate.el rename to test/jest/outdated-upgrade/make-outdate.el diff --git a/test/jest/buttercup.test.js b/test/jest/test-buttercup.test.js similarity index 100% rename from test/jest/buttercup.test.js rename to test/jest/test-buttercup.test.js From f5a94e517edc7076b677b41f972a2f262027daf8 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Fri, 28 Mar 2025 15:56:55 -0700 Subject: [PATCH 67/70] delete unused test project --- test/jest/mini.pkg.1/Eask | 37 -------------------- test/jest/mini.pkg.1/RADME.md | 1 - test/jest/mini.pkg.1/files/mini.pkg.1-1.el | 32 ------------------ test/jest/mini.pkg.1/files/mini.pkg.1-2.el | 31 ----------------- test/jest/mini.pkg.1/mini.pkg.1.el | 39 ---------------------- 5 files changed, 140 deletions(-) delete mode 100644 test/jest/mini.pkg.1/Eask delete mode 100644 test/jest/mini.pkg.1/RADME.md delete mode 100644 test/jest/mini.pkg.1/files/mini.pkg.1-1.el delete mode 100644 test/jest/mini.pkg.1/files/mini.pkg.1-2.el delete mode 100644 test/jest/mini.pkg.1/mini.pkg.1.el diff --git a/test/jest/mini.pkg.1/Eask b/test/jest/mini.pkg.1/Eask deleted file mode 100644 index 480eef12..00000000 --- a/test/jest/mini.pkg.1/Eask +++ /dev/null @@ -1,37 +0,0 @@ -(package "mini.pkg.1" - "0.0.1" - "Minimal test package") - -(website-url "https://github.com/emacs-eask/cli/tree/master/test/fixtures/mini.pkg.1") -(keywords "test" "local") - -(package-file "mini.pkg.1.el") - -(files "files/*.el") - -(script "test" "echo \"Have a nice day!~ ;)\"") -(script "extra" "echo :") -(script "info" "eask info") - -(eask-defcommand mini-test-1 "Test command 1." (message "Test 1")) -(eask-defcommand mini-test-2 "Test command 2." (message "Test 2")) -(eask-defcommand mini-test-3 - "Test command 3." - (message "Test 3: %s" eask-rest)) - -(source 'gnu) -(source 'melpa) -(source 'jcs-elpa) - -(depends-on "emacs" "26.1") -(depends-on "f") -(depends-on "s") -(depends-on "fringe-helper") -(depends-on "watch-cursor" - :repo "jcs-elpa/watch-cursor" :fetcher 'github) -(depends-on "organize-imports-java" - :repo "jcs-elpa/organize-imports-java" - :fetcher 'github - :files '(:defaults "sdk" "default")) - -(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432 diff --git a/test/jest/mini.pkg.1/RADME.md b/test/jest/mini.pkg.1/RADME.md deleted file mode 100644 index 441cfd06..00000000 --- a/test/jest/mini.pkg.1/RADME.md +++ /dev/null @@ -1 +0,0 @@ -Minimal Emacs package to simulate development environment; only for testing purposes! diff --git a/test/jest/mini.pkg.1/files/mini.pkg.1-1.el b/test/jest/mini.pkg.1/files/mini.pkg.1-1.el deleted file mode 100644 index 1c7e7c73..00000000 --- a/test/jest/mini.pkg.1/files/mini.pkg.1-1.el +++ /dev/null @@ -1,32 +0,0 @@ -;;; mini.pkg.1-1.el --- Extern file 1 -*- lexical-binding: t; -*- - -;; This file is NOT part of GNU Emacs. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; -;; files/mini.pkg.1-1.el -;; - -;;; Code: - - -(defun mini.pkg.1-1 () - "Test function 1." - (interactive) - ) - -(provide 'mini.pkg.1-1) -;;; mini.pkg.1-1.el ends here diff --git a/test/jest/mini.pkg.1/files/mini.pkg.1-2.el b/test/jest/mini.pkg.1/files/mini.pkg.1-2.el deleted file mode 100644 index 09d7eb8c..00000000 --- a/test/jest/mini.pkg.1/files/mini.pkg.1-2.el +++ /dev/null @@ -1,31 +0,0 @@ -;;; mini.pkg.1-2.el --- Extern file 2 -*- lexical-binding: t; -*- - -;; This file is NOT part of GNU Emacs. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; -;; files/mini.pkg.1-2.el -;; - -;;; Code: - -(defun mini.pkg.1-2 () - "Test function 2." - (interactive) - ) - -(provide 'mini.pkg.1-2) -;;; mini.pkg.1-2.el ends here diff --git a/test/jest/mini.pkg.1/mini.pkg.1.el b/test/jest/mini.pkg.1/mini.pkg.1.el deleted file mode 100644 index 1db1a166..00000000 --- a/test/jest/mini.pkg.1/mini.pkg.1.el +++ /dev/null @@ -1,39 +0,0 @@ -;;; mini.pkg.1.el --- Minimal test package -*- lexical-binding: t; -*- - -;; Copyright (C) 2022-2025 the Eask authors. -;; Created date 2022-03-29 01:52:58 - -;; Author: Shen, Jen-Chieh -;; URL: https://github.com/emacs-eask/cli/tree/master/test/fixtures/mini.pkg.1 -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3") (s "1.12.0") (fringe-helper "1.0.1")) -;; Keywords: test local - -;; This file is NOT part of GNU Emacs. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; -;; Minimal Emacs package to simulate development environment; only for testing -;; purposes! -;; - -;;; Code: - -(require 's) -(require 'fringe-helper) - -(provide 'mini.pkg.1) -;;; mini.pkg.1.el ends here From 73debff678110a3b5e0689ccbb9472a21a8fb2f5 Mon Sep 17 00:00:00 2001 From: JenChieh Date: Fri, 28 Mar 2025 16:06:37 -0700 Subject: [PATCH 68/70] style: Format it --- .../Contributing/Developing-Eask/_index.en.md | 56 +++++++++++++------ 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/docs/content/Contributing/Developing-Eask/_index.en.md b/docs/content/Contributing/Developing-Eask/_index.en.md index d15c9e3a..f2bdc735 100644 --- a/docs/content/Contributing/Developing-Eask/_index.en.md +++ b/docs/content/Contributing/Developing-Eask/_index.en.md @@ -11,8 +11,7 @@ To make changes to Eask, you should have: 1. [Node.js][] for the development environment. 2. [npm][] for the package manager. -3. [yargs][] for CLI parser. -4. [Emacs][], 26.1 or above! +3. [Emacs][], 26.1 or above! ## 📝 Building @@ -31,14 +30,14 @@ It should print out the location of the `eask` executable. You should be able to identify the Eask executable's location, even you have multiple Eask versions installed! -## 📈 Testing +## 🧪 Testing -Local testing for Eask is done using the [Jest](https://jestjs.io) testing framework. +Local testing for Eask is done using the [Jest][] testing framework. Jest is a mature and well supported testing framework written in Javascript. -Jest was chosen for much the [same reasons as Javascript](https://emacs-eask.github.io/FAQ/#-why-javascript) was chosen for this project. +Jest was chosen for much the [same reasons as Javascript][Why JS?] was chosen for this project. In addition, Jest is easy to learn and has built in support for snapshot based testing. -### Running Tests +### ⚗️ Running Tests If you have not done so already, run `npm install --dev` @@ -50,12 +49,12 @@ Always run from the project root (i.e. same directory as `package.json`) - remove files created during test `npm run test-reset` Since `npm run test` just runs Jest, you can also pass Jest options to the -commands above. -For example +commands above. For example: + - run tests whose names (in `test()` blocks) match `npm run test -t 'eask lint .*'` - re-run failed tests `npm run test -f` -### Environment Vars +### 🌍 Environment Vars | Name | Type | Default | Meaning | |:---------------|:-------|---------|:--------------------------------------------------------------------------------------------------| @@ -64,10 +63,12 @@ For example | `EASK_COMMAND` | path | "eask" | Path to Eask. Usually either `eask` or `$PWD/bin/eask` to use local changes. | | `TIMEOUT` | number | 25000 | Command timeout in ms. Note this is different than Jest's timeout, which should be greater. | -(*) Node.js handles environment variables as strings. That means that `DEBUG=0`, `DEBUG=false` all _enable_ `DEBUG`. - The only setting which disables a boolean flag is null, for example `DEBUG=` +{{< hint info >}} +💡 Node.js handles environment variables as strings. That means that `DEBUG=0`, `DEBUG=false` all _enable_ `DEBUG`. +The only setting which disables a boolean flag is null, for example `DEBUG=`. +{{< /hint >}} -### How to Write a Test +### 🔬 How to Write a Test **Folder structure** @@ -115,6 +116,7 @@ All `runEask` commands will use the `TestContext`'s working directory. Jest's tests are in `test` blocks. Note that `it` is an alias for `test`. Tests can be selectively disabled in code, like so: + - `test.only(name, fn)` runs only that test in the file - `test.skip(name, fn)` skips running the test but still prints its name - `test.failing(name, fn)` invert the meaning of the test: it *should* fail. @@ -127,11 +129,13 @@ That's why many tests don't have an `expect` call, they simply check that the co Output from `runEask` is wrapped in a helper class `CommandOutput` which provides some transformation methods. For example, if you have `const out = await ctx.runEask("analyze");`, then + - `out.combined()` concatenates both stdout and stderr as a string, - `out.raw()` returns a plain object with just `stdout` and `stderr` as properties, - `out.sanitized()` replaces all absolute paths that match the context's path Since the class wraps the output of Node's `exec()` method you can still access `stdout` and `stderr`: + ``` javascript const { stderr, stdout } = await ctx.runEask("analyze"); ``` @@ -140,6 +144,7 @@ Some commands create files or directories which should be removed after the test For example, `eask generate ignore elisp` creates a `.gitignore` file. You can use the context's `removeFiles` method to remove files and directories relative to the context's path: + ``` javascript describe("Generating", () => { beforeAll(async () => await ctx.removeFiles(".gitignore")); @@ -150,6 +155,7 @@ to the context's path: }); }); ``` + Note that `removeFiles()` will recursively remove directories, but does not accept patterns. So, to remove all files in `./test` just call `ctx.remove("test")`. You can pass multiple files or directory names in single call: `ctx.remove("test", ".gitignore")`. @@ -159,10 +165,11 @@ Use this if Jest reports "open handles were detected" after a test run. Note that `cleanUp` sends a signal to *all* processes started using the context's `runEask` command. If used in an `afterEach` hook (i.e. after every test) it may result in failures. -### Snapshots +### 🪧 Snapshots [Snapshot tests](https://jestjs.io/docs/snapshot-testing) match the output of a test against a saved copy of the expected output. -For example +For example: + ``` javascript test("eask analyze", async () => { const res = await ctx.runEask("analyze"); @@ -177,6 +184,7 @@ If the snapshot changes, you can update the snapshot by running Jest with option `npm run test -- -u` will update all changed snapshots. Any type of output can be used for a snapshot test. You could snapshot the contents of a file after changing it + ``` javascript test("eask analyze", async () => { await ctx.runEask("foo"); @@ -190,6 +198,7 @@ The snapshot of `eask analyze` contains absolute file paths that will be differe Output from `runEask` is wrapped in a helper class `CommandOutput` which provides some transformation methods. The simplest just removes the absolute file paths: + ``` javascript it("matches snapshot", async () => { const res = await ctx.runEask("analyze"); @@ -201,6 +210,7 @@ it("matches snapshot", async () => { You can include custom replacement functions. Here, numbers will be replaced by `"x"`. Then strings `"x:x"` will be replaced by `"y"`. + ``` javascript it("matches snapshot", async () => { const res = await ctx.runEask("analyze"); @@ -217,7 +227,7 @@ it("matches snapshot", async () => { It's important to use the `g` regex flag so all occurrences of the match are replaced, or you could use `replaceAll`. User provided functions run in addition to the default sanitize function and run in the order they were given. -### Timeouts +### ⏱️ Timeouts There are two timeout settings, one for Jest and one for Node's `exec()`. All timeout values are in milliseconds. @@ -226,11 +236,13 @@ Since the `exec()` timeout immediately terminates the running command and report use that instead of Jest's timeout. To change a timeout for a single command + ``` javascript ctx.runEask("analyze", { timeout: 10000}) ``` To change the global timeout for a single run, use the env var + ``` shell env TIMEOUT=30000 npm run test ``` @@ -246,12 +258,13 @@ If you change either global timeout, **make sure the global Jest timeout is grea } ``` -### Patterns +### 📜 Patterns Here are some common patterns for testing commands. Each of these assumes that `ctx` is a `TestContext` object. **Check a command succeeds:** + ``` javascript test("eask analyze", async () => { await ctx.runEask("analyze"); @@ -262,6 +275,7 @@ Uncaught errors thrown in a `test` block will fail the test and report the error Failed commands will include stderr and stdout. **Check a command fails:** + ``` javascript test("eask analyze", async () => { await expect(ctx.runEask("analyze")).rejects.toThrow(); @@ -269,6 +283,7 @@ test("eask analyze", async () => { ``` **Check a command fails with a specific code:** + ``` javascript test("eask link add should error", async () => { // the error object should have property code = 1 @@ -279,6 +294,7 @@ test("eask link add should error", async () => { ``` **Check a command produces some output:** + ``` javascript test("eask analyze", async () => { const out = await ctx.runEask("analyze"); @@ -305,6 +321,7 @@ Update all changed snapshots: `npm run test -- -u` Remove absolute file paths from output: + ``` javascript it("matches snapshot", async () => { const res = await ctx.runEask("analyze"); @@ -315,6 +332,7 @@ it("matches snapshot", async () => { ``` Apply custom transformations for sanitizing output: + ``` javascript it("matches snapshot", async () => { const res = await ctx.runEask("analyze"); @@ -344,7 +362,7 @@ testUnsafe("global install", async () => { }); ``` -### Common Problems +### 🩺 Common Problems - When using `runEask()`, pass only the Eask *arguments*, not the `eask` command itself. - Always `await` any expressions that trigger commands. @@ -355,9 +373,13 @@ testUnsafe("global install", async () => { The `node.exec` timeout is set lower than the Jest one, so changing timeout values for tests or by `jest.setTimeout` usually won't have an effect. Instead set the timeout on the command itself `runEask("eask emacs", { timeout: 100000 })` + [Node.js]: https://nodejs.org/en/ [npm]: https://www.npmjs.com/ [yargs]: https://github.com/yargs/yargs [Emacs]: https://www.gnu.org/software/emacs/ + +[Jest]: https://jestjs.io +[Why JS?]: https://emacs-eask.github.io/FAQ/#-why-javascript From 97b80740e8ed2f6c6e6b044f101ea919594975cf Mon Sep 17 00:00:00 2001 From: JenChieh Date: Fri, 28 Mar 2025 16:29:15 -0700 Subject: [PATCH 69/70] docs: Add zh-TW translation --- .../Contributing/Developing-Eask/_index.en.md | 19 +- .../Developing-Eask/_index.zh-tw.md | 342 +++++++++++++++++- 2 files changed, 344 insertions(+), 17 deletions(-) diff --git a/docs/content/Contributing/Developing-Eask/_index.en.md b/docs/content/Contributing/Developing-Eask/_index.en.md index f2bdc735..33d28341 100644 --- a/docs/content/Contributing/Developing-Eask/_index.en.md +++ b/docs/content/Contributing/Developing-Eask/_index.en.md @@ -56,12 +56,12 @@ commands above. For example: ### 🌍 Environment Vars -| Name | Type | Default | Meaning | -|:---------------|:-------|---------|:--------------------------------------------------------------------------------------------------| -| `ALLOW_UNSAFE` | bool* | false | Run tests in `testUnsafe` blocks. These can **overwrite** your personal emacs config or settings. | -| `DEBUG` | bool* | false | Print full output from commands in test. | -| `EASK_COMMAND` | path | "eask" | Path to Eask. Usually either `eask` or `$PWD/bin/eask` to use local changes. | -| `TIMEOUT` | number | 25000 | Command timeout in ms. Note this is different than Jest's timeout, which should be greater. | +| Name | Type | Default | Meaning | +|:---------------|:--------|:--------|:--------------------------------------------------------------------------------------------------| +| `ALLOW_UNSAFE` | `bool*` | false | Run tests in `testUnsafe` blocks. These can **overwrite** your personal emacs config or settings. | +| `DEBUG` | `bool*` | false | Print full output from commands in test. | +| `EASK_COMMAND` | path | "eask" | Path to Eask. Usually either `eask` or `$PWD/bin/eask` to use local changes. | +| `TIMEOUT` | number | 25000 | Command timeout in ms. Note this is different than Jest's timeout, which should be greater. | {{< hint info >}} 💡 Node.js handles environment variables as strings. That means that `DEBUG=0`, `DEBUG=false` all _enable_ `DEBUG`. @@ -317,8 +317,7 @@ test("eask analyze", async () => { }); ``` -Update all changed snapshots: -`npm run test -- -u` +Update all changed snapshots: `npm run test -- -u` Remove absolute file paths from output: @@ -370,8 +369,8 @@ testUnsafe("global install", async () => { - The folder argument to `TestContext` should be relative to project root, if it doesn't exist you may get an error `ENOENT` - If you get an error from Jest reporting open handles, then try using `afterAll(() => ctx.cleanUp())` - There are two timeout values: one used for Jest (set in `package.json`), and one used for `node.exec`, set via env var in `./helpers.js`. - The `node.exec` timeout is set lower than the Jest one, so changing timeout values for tests or by `jest.setTimeout` usually won't - have an effect. Instead set the timeout on the command itself `runEask("eask emacs", { timeout: 100000 })` +The `node.exec` timeout is set lower than the Jest one, so changing timeout values for tests or by `jest.setTimeout` usually won't +have an effect. Instead set the timeout on the command itself `runEask("eask emacs", { timeout: 100000 })` diff --git a/docs/content/Contributing/Developing-Eask/_index.zh-tw.md b/docs/content/Contributing/Developing-Eask/_index.zh-tw.md index deb8d9b7..21b35337 100644 --- a/docs/content/Contributing/Developing-Eask/_index.zh-tw.md +++ b/docs/content/Contributing/Developing-Eask/_index.zh-tw.md @@ -11,8 +11,7 @@ weight: 20 1. [Node.js][] 開發環境。 2. [npm][] 包管理器。 -3. [yargs][] 用於 CLI 解析器。 -4. [Emacs][], 26.1 以上! +3. [Emacs][], 26.1 以上! ### 📝 建構 @@ -27,13 +26,339 @@ eask locate 它應該會列印出 `eask` 可執行檔的位置。即使您已安裝多個 Eask 版本,也應該可以辨識 Eask 可執行檔的位置! -### 📈 測試 +### 🧪 測試 -Eask 不提供本地測試,我們所有的測試都是使用 GitHub 完成的動作。 請 fork 我們的存儲庫 -並將您的更改推送到您的 fork。 GitHub 行動應該為你拿起測試! +Eask 的本地測試使用 [Jest][] 測試框架完成。Jest 是用 Javascript 寫成的成熟且支援良好的測試框架。 +選擇 Jest 的原因與本專案[選擇 Javascript 的原因大致相同][Why JS?]。此外,Jest 容易學習,而且內建了對快照測試的支援。 -確保您的存儲庫(分叉)中啟用了 GitHub Actions。 必須 **設置** -> **操作** -> **常規** --> **操作權限**; 確保您已經檢查了正確的選項。 +### ⚗️ 執行測試 + +如果尚未執行,請執行 `npm install --dev` 。 + +永遠從專案根目錄執行 (即與 `package.json` 相同的目錄) + +- 執行所有測試 `npm run test` +- 執行單次測試 `npm run test path/to/test.js` +- 以完整輸出執行測試 `npm run test-debug` +- 移除測試時建立的檔案 `npm run test-reset` + +由於 `npm run test` 只會執行 Jest,您也可以將 Jest 選項傳給上面的指令。例如 + +- 執行名稱 (在 `test()` 區塊中) 符合`npm run test -t 'eask lint .*'` 的測試 +- 重新執行失敗的測試 `npm run test -f` + +### 🌍 環境變數 + +| Name | Type | Default | Meaning | +|:---------------|:--------|:--------|:---------------------------------------------------------------------| +| `ALLOW_UNSAFE` | `bool*` | false | 在 `testUnsafe` 區塊中執行測試。這些區塊可能**覆寫**您個人的 emacs 配置或設定。 | +| `DEBUG` | `bool*` | false | 列印測試中指令的完整輸出。 | +| `EASK_COMMAND` | path | "eask" | Eask 的路徑。通常是 `eask` 或 `$PWD/bin/eask` 來使用本機變更。 | +| `TIMEOUT` | number | 25000 | 命令超時,以毫秒為單位。請注意這與 Jest 的逾時時間不同,Jest 的逾時時間應該更長。 | + +{{< hint info >}} +💡 Node.js 將環境變數當成字串來處理。這表示 `DEBUG=0`、`DEBUG=false` 都 _enable_ `DEBUG`。 +唯一禁用布林旗標的設定是 null,例如 `DEBUG=`。 +{{< /hint >}} + +### 🔬 如何撰寫測試 + +**資料夾結構** + +測試應該放在 `test/js` 中。 +相關的測試應該在同一個檔案中,後綴為 `.test.js`,通常以測試的功能或指令命名,例如 `link.test.js` 測試 `eask link` 指令。 + +如果測試需要一些特定的專案檔案,請將它們放在 `test/js` 中的新資料夾。 +例如,在 `test/js/foo` 中的檔案預計會用於 `foo.test.js`。 + +例外的是 `test/js/empty`,它只是一個空的資料夾。 +如果您使用它,請務必在測試前執行 `eask clean all`。 + +** 測試檔案結構** + +``` javascript +const { TestContext } = require("./helpers"); + +describe("emacs", () => { + const ctx = new TestContext("./test/jest/empty"); + + beforeAll(async () => await ctx.runEask("clean all")); + afterAll(() => ctx.cleanUp); + + test("eask emacs --version", async () => { + await ctx.runEask("emacs --version"); + }); + + test("eask emacs --batch --eval", async () => { + await ctx.runEask( + 'emacs --batch --eval "(require (quote ert))" --eval "(ert-deftest mytest () (should-not (display-graphic-p)))" -f ert-run-tests-batch', + ); + }); +}); +``` + +在 Jest 中,您可以使用 `describe` 將相關的測試分組。在相同的 `describe` 區塊中的測試可以共用設定/停用程式碼,可以作為一個群組停用,並在輸出中被歸類在相同的標題下。 + +`describe` 區塊可以嵌套在其他的 `describe` 區塊中。 +當測試在不同目錄中執行時,或配合 "given, when, then" 的測試風格時,加入巢狀的 `describe` 是個好主意。 + +您應該為每個測試目錄建立新的 `TestContext` 物件。 +所有的 `runEask` 指令都會使用 `TestContext` 的工作目錄。 + +Jest 的測試在 `test` 區塊中。請注意 `it` 是 `test` 的別名。 +測試可以在程式碼中選擇性地停用,就像這樣: + +- `test.only(name,fn)` 只執行檔案中的測試 +- `test.skip(name,fn)` 跳過執行測試,但仍會列印其名稱 +- `test.failing(name, fn)` 反轉測試的意義:它*應該*失敗。 + +`expect` API 以不同的方式匹配值,通常會列印差異作為失敗報告的一部分。 +更多資訊請參閱 Jest 的 [expect()](https://jestjs.io/docs/expect) API。 + +在 `test` 區塊中拋出的未捕獲錯誤會使它失敗並報告錯誤。 +這就是為什麼許多測試沒有 `expect` 呼叫,它們只是檢查指令是否成功。 + +來自 `runEask` 的輸出會包裝在提供一些轉換方法的輔助類 `CommandOutput` 中。 +例如,如果您有 `const out = await ctx.runEask("analyze");`,那麼 + +- `out.combined()` 將 stdout 和 stderr 匯整為一個字串、 +- `out.raw()` 返回一個只有`stdout`和`stderr`屬性的純物件、 +- `out.sanitized()` 會取代所有符合上下文路徑的絕對路徑。 + +由於這個類別包覆了 Node 的 `exec()` 方法的輸出,你仍然可以存取 `stdout` 和 `stderr`: + +``` javascript +const { stderr, stdout } = await ctx.runEask("analyze"); +``` + +有些指令會建立檔案或目錄,這些檔案或目錄應該在測試執行後移除。 +例如,`eask generate ignore elisp` 會建立一個 `.gitignore` 檔案。 +您可以使用 context 的 `removeFiles` 方法來移除相對於 context 路徑的檔案和目錄: + +``` javascript + describe("Generating", () => { + beforeAll(async () => await ctx.removeFiles(".gitignore")); + afterAll(async () => await ctx.removeFiles(".gitignore")); + + it("eask generate ignore elisp", async () => { + await ctx.runEask("generate ignore elisp"); + }); + }); +``` + +請注意,`removeFiles()` 會遞迴移除目錄,但不接受模式。 +因此,要移除 `./test` 中的所有檔案,只需呼叫 `ctx.remove("test")`。 +您可以在一次呼叫中傳入多個檔案或目錄名稱: `ctx.remove("test", ".gitignore")`. + +使用 `TestContext.cleanUp()` 立即中止在該上下文中呼叫的任何仍在執行的指令。 +如果 Jest 在測試執行後報告"偵測到開啟的句柄",請使用此功能。 +請注意,`cleanUp` 會傳送一個信號給所有使用上下文的 `runEask` 指令啟動的進程。 +如果在 `afterEach` 鈎結中使用 (即每次測試後),可能會導致失敗。 + +### 🪧 快照 + +[快照測試](https://jestjs.io/docs/snapshot-testing) 將測試的輸出與預期輸出的儲存副本進行比對。 +例如: + +``` javascript +test("eask analyze", async () => { + const res = await ctx.runEask("analyze"); + expect(res.raw()).toMatchSnapshot(); +}); +``` + +第一次執行時,Jest 會建立一個新的快照,儲存在鄰近的 `__snapshot__` 目錄中。 + +您應該將此檔案加入版本控制,因為它是測試的關鍵部分。 +如果快照變更,您可以使用選項 `-u` 執行 Jest 來更新快照,例如 `npm run test -- -u` 會更新所有變更的快照。 + +任何類型的輸出都可以用於快照測試。您可以在變更檔案後快照檔案內容 + +``` javascript +test("eask analyze", async () => { + await ctx.runEask("foo"); + const file = ctx.fileContents("Easkfile"); // file as a string + expect(file).toMatchSnapshot(); +}); +``` + +通常快照會包含會隨時間或環境改變的資料,例如時間戳記或檔案路徑。 +`eask analyze` 的快照包含絕對檔案路徑,這些路徑在每台機器上都會不同。 + +從 `runEask` 輸出的內容會包裝在提供一些轉換方法的輔助類 `CommandOutput` 中。 +最簡單的只是移除絕對檔案路徑: + +``` javascript +it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res.sanitized() // a CommandOutput object with absolute paths replaced by "~" + .raw(); // an object { stderr, stdout } suitable for snapshotting + expect(resClean).toMatchSnapshot(); +}); +``` + +您可以加入自訂的取代函數。在這裡,數字會被 `"x"` 取代。 +字串 `"x:x"` 將被 `"y"` 取代。 + +``` javascript +it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res + .sanitized( + (x) => x.replace(/[0-9]+/g, "x"), + (x) => x.replaceAll("x:x", "y"), + ) + .raw(); + expect(resClean).toMatchSnapshot(); +}); +``` + +請務必使用 `g` regex 標記,這樣所有匹配的出現都會被取代,或者您也可以使用 `replaceAll`。 +使用者提供的函數會在預設的 sanitize 函數之外執行,並且會依給定的順序執行。 + +### ⏱️ 超時 + +T這裡有兩個超時設定,一個用於 Jest,另一個用於 Node 的 `exec()`。 +所有逾時值的單位都是毫秒。 + +由於 `exec()` 超時會立即終止執行中的指令並報告輸出,因此使用它來代替 Jest 的超時會更好。 + +若要變更單一指令的逾時時間 + +``` javascript +ctx.runEask("analyze", { timeout: 10000}) +``` + +若要變更單次執行的全局逾時,請使用 env var + +``` shell +env TIMEOUT=30000 npm run test +``` + +若要永久變更全局超時,請在 `./helpers.js` 中設定預設值。 + +如果您變更任一全域逾時時間,**請在 `package.json` 中設定全域逾時時間,以確保全域 Jest 逾時時間較長**。 + +``` json +"jest": { + "rootDir": "./test/jest", + "testTimeout": 40000 +} +``` + +### 📜 樣式 + +以下是一些測試指令的常見模式。 +每種模式都假設 `ctx` 是一個 `TestContext` 物件。 + +**檢查指令是否成功:** + +``` javascript +test("eask analyze", async () => { + await ctx.runEask("analyze"); +}); +``` + +在 `test` 區塊中拋出的未捕獲錯誤將使測試失敗,並會報告錯誤。 +失敗的指令會包含 stderr 和 stdout。 + +**檢查命令失敗:** + +``` javascript +test("eask analyze", async () => { + await expect(ctx.runEask("analyze")).rejects.toThrow(); +}); +``` + +**檢查指令是否以特定代碼失敗:** + +``` javascript +test("eask link add should error", async () => { + // the error object should have property code = 1 + await expect(ctx.runEask("link add")).rejects.toMatchObject({ + code: 1, + }); +}); +``` + +** 檢查指令是否產生某些輸出:** + +``` javascript +test("eask analyze", async () => { + const out = await ctx.runEask("analyze"); + expect(out.stderr).toMatch("success"); // should apppear as a substring + // If you want to check both `stderr` and `stdout`, just concatenate them + expect(out.stdout + "/n" + out.stderr).toMatch("success"); + // Same thing using helper methods + expect(out.combined()).toMatch("success"); +}); +``` + +**根據快照檢查指令輸出:** + +簡單的輸出比對 + +``` javascript +test("eask analyze", async () => { + const res = await ctx.runEask("analyze"); + expect(res).toMatchSnapshot(); +}); +``` + +更新所有已變更的快照: `npm run test -- -u` + +移除輸出中的絕對檔案路徑: + +``` javascript +it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res.sanitized() // a CommandOutput object with absolute paths replaced by "~" + .raw(); // an object { stderr, stdout } suitable for snapshotting + expect(resClean).toMatchSnapshot(); +}); +``` + +套用自訂的轉換來消毒輸出: + +``` javascript +it("matches snapshot", async () => { + const res = await ctx.runEask("analyze"); + const resClean = res + .sanitized( + (x) => x.replace(/[0-9]+/g, "x"), + (x) => x.replace(/x:x/g, "y"), + ) + .raw(); + expect(resClean).toMatchSnapshot(); +}); +``` + +使用者提供的函數會在預設的 sanitize 函數之外執行,並且會按照所給予的順序執行。 + +** 修改使用者環境的指令:** + +例如,使用 `-c` 或 `-g` 選項的指令。 + +``` javascript +const { testUnsafe } = require('./helpers'); + +// this will only run if ALLOW_UNSAFE is != 0 +testUnsafe("global install", async () => { + // this installs in ~/.eask and changes ~/Eask + await ctx.runEask("install -g foo"); +}); +``` + +### 🩺 常見問題 + +- 使用 `runEask()` 時,只傳 Eask *arguments*,不傳 `eask` 指令本身。 +- 總是 `await` 任何觸發指令的表達式。 +- 當使用`expect(...).rejects`時,它應該被 awaited,以便承諾在測試完成前拒絕。 +- `TestContext` 的資料夾參數應該相對於專案根目錄,如果它不存在,您可能會得到一個錯誤`ENOENT`。 +- 如果您收到 Jest 回報打開句柄的錯誤,那麼請嘗試使用 `afterAll(() => ctx.cleanUp())` +- 有兩個逾時值:一個用於 Jest (在 `package.json` 中設定),另一個用於 `node.exec`,在 `./helpers.js` 中透過 env var 設定。 +`node.exec` 的逾時設定比 Jest 的低,所以改變測試的逾時值或 `jest.setTimeout` 通常不會有影響。 +取而代之,在指令本身設定超時 `runEask("eask emacs", { timeout: 100000 })`。 @@ -42,3 +367,6 @@ Eask 不提供本地測試,我們所有的測試都是使用 GitHub 完成的 [npm]: https://www.npmjs.com/ [yargs]: https://github.com/yargs/yargs [Emacs]: https://www.gnu.org/software/emacs/ + +[Jest]: https://jestjs.io +[Why JS?]: https://emacs-eask.github.io/zh-tw/FAQ/#-%E7%82%BA%E4%BB%80%E9%BA%BC%E9%81%B8%E6%93%87-javascript From e76a1b83d73ec53f4e9751f2f9f3ee9f7530323a Mon Sep 17 00:00:00 2001 From: JenChieh Date: Fri, 28 Mar 2025 16:38:42 -0700 Subject: [PATCH 70/70] docs: Translate comment as well --- .../Contributing/Developing-Eask/_index.en.md | 6 ++-- .../Developing-Eask/_index.zh-tw.md | 30 ++++++++++--------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/docs/content/Contributing/Developing-Eask/_index.en.md b/docs/content/Contributing/Developing-Eask/_index.en.md index 33d28341..ab3d70e1 100644 --- a/docs/content/Contributing/Developing-Eask/_index.en.md +++ b/docs/content/Contributing/Developing-Eask/_index.en.md @@ -16,7 +16,7 @@ To make changes to Eask, you should have: ## 📝 Building To build the development environment, you would have to install Eask using -the [build from source](https://emacs-eask.github.io/Getting-Started/Install-Eask/#-build-from-source) +the [build from source][Build from source] method. Make sure you have set up the environment PATH variable, so you can call `eask` from the terminal. @@ -375,10 +375,12 @@ have an effect. Instead set the timeout on the command itself `runEask("eask ema +[Build from source]: https://emacs-eask.github.io/Getting-Started/Install-Eask/#-build-from-source +[Why JS?]: https://emacs-eask.github.io/FAQ/#-why-javascript + [Node.js]: https://nodejs.org/en/ [npm]: https://www.npmjs.com/ [yargs]: https://github.com/yargs/yargs [Emacs]: https://www.gnu.org/software/emacs/ [Jest]: https://jestjs.io -[Why JS?]: https://emacs-eask.github.io/FAQ/#-why-javascript diff --git a/docs/content/Contributing/Developing-Eask/_index.zh-tw.md b/docs/content/Contributing/Developing-Eask/_index.zh-tw.md index 21b35337..6801db4a 100644 --- a/docs/content/Contributing/Developing-Eask/_index.zh-tw.md +++ b/docs/content/Contributing/Developing-Eask/_index.zh-tw.md @@ -15,7 +15,7 @@ weight: 20 ### 📝 建構 -要構建開發環境,您必須使用安裝 Eask [從源代碼建構](https://emacs-eask.github.io/Getting-Started/Install-Eask/#-build-from-source) +要構建開發環境,您必須使用安裝 Eask [從源代碼建構][Build from source] 的方法。 確保你已經設置了環境 `PATH` 變量,這樣你就可以調用來自終端的`eask`。 完成安裝後,嘗試: @@ -177,7 +177,7 @@ test("eask analyze", async () => { ``` javascript test("eask analyze", async () => { await ctx.runEask("foo"); - const file = ctx.fileContents("Easkfile"); // file as a string + const file = ctx.fileContents("Easkfile"); // 檔案為字串 expect(file).toMatchSnapshot(); }); ``` @@ -191,8 +191,8 @@ test("eask analyze", async () => { ``` javascript it("matches snapshot", async () => { const res = await ctx.runEask("analyze"); - const resClean = res.sanitized() // a CommandOutput object with absolute paths replaced by "~" - .raw(); // an object { stderr, stdout } suitable for snapshotting + const resClean = res.sanitized() // 以 "~" 取代絕對路徑的 CommandOutput 物件 + .raw(); // 適合快照的物件 { stderr、stdout } expect(resClean).toMatchSnapshot(); }); ``` @@ -274,7 +274,7 @@ test("eask analyze", async () => { ``` javascript test("eask link add should error", async () => { - // the error object should have property code = 1 + // 錯誤物件的屬性代碼應該是 1 await expect(ctx.runEask("link add")).rejects.toMatchObject({ code: 1, }); @@ -286,10 +286,10 @@ test("eask link add should error", async () => { ``` javascript test("eask analyze", async () => { const out = await ctx.runEask("analyze"); - expect(out.stderr).toMatch("success"); // should apppear as a substring - // If you want to check both `stderr` and `stdout`, just concatenate them + expect(out.stderr).toMatch("success"); // 應顯示為子字串 + // 如果您要同時檢查 `stderr` 和 `stdout`,只要將它們串連即可 expect(out.stdout + "/n" + out.stderr).toMatch("success"); - // Same thing using helper methods + // 使用輔助方法也是一樣 expect(out.combined()).toMatch("success"); }); ``` @@ -312,8 +312,8 @@ test("eask analyze", async () => { ``` javascript it("matches snapshot", async () => { const res = await ctx.runEask("analyze"); - const resClean = res.sanitized() // a CommandOutput object with absolute paths replaced by "~" - .raw(); // an object { stderr, stdout } suitable for snapshotting + const resClean = res.sanitized() // 以 "~" 取代絕對路徑的 CommandOutput 物件 + .raw(); // 適合快照的物件 { stderr、stdout } expect(resClean).toMatchSnapshot(); }); ``` @@ -342,9 +342,9 @@ it("matches snapshot", async () => { ``` javascript const { testUnsafe } = require('./helpers'); -// this will only run if ALLOW_UNSAFE is != 0 +// 只有當 ALLOW_UNSAFE 為 != 0 時,才會執行此指令。 testUnsafe("global install", async () => { - // this installs in ~/.eask and changes ~/Eask + // 這會安裝在 ~/.eask 中,並變更 ~/Eask await ctx.runEask("install -g foo"); }); ``` @@ -363,10 +363,12 @@ testUnsafe("global install", async () => { +[Build from source]: https://emacs-eask.github.io/zh-tw/Getting-Started/Install-Eask/#-%e5%be%9e%e5%8e%9f%e5%a7%8b%e7%a2%bc%e6%a7%8b%e5%bb%ba +[Why JS?]: https://emacs-eask.github.io/zh-tw/FAQ/#-%E7%82%BA%E4%BB%80%E9%BA%BC%E9%81%B8%E6%93%87-javascript + [Node.js]: https://nodejs.org/en/ [npm]: https://www.npmjs.com/ [yargs]: https://github.com/yargs/yargs [Emacs]: https://www.gnu.org/software/emacs/ -[Jest]: https://jestjs.io -[Why JS?]: https://emacs-eask.github.io/zh-tw/FAQ/#-%E7%82%BA%E4%BB%80%E9%BA%BC%E9%81%B8%E6%93%87-javascript +[Jest]: https://jestjs.io \ No newline at end of file