From 8031de7db942093a2ab3fc1e6ae42fc96bfc0786 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 17:59:35 +0200 Subject: [PATCH 1/9] chore(deps): update dependency eslint to v9 (#5504) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Vladimir Sheremet --- eslint.config.js | 2 + examples/typecheck/tsconfig.json | 3 +- package.json | 4 +- pnpm-lock.yaml | 786 ++++++++++++++++++------------- 4 files changed, 471 insertions(+), 324 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 2a7def112665a..8bab15c5cb951 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -10,6 +10,8 @@ export default antfu( '**/*.snap', '**/bench.json', '**/fixtures', + '**/assets/**', + '**/*.timestamp-*', 'test/core/src/self', 'test/wasm-modules/src/wasm-bindgen-no-cyclic', 'test/workspaces/results.json', diff --git a/examples/typecheck/tsconfig.json b/examples/typecheck/tsconfig.json index c27a772994571..2fa6cd6ac8937 100644 --- a/examples/typecheck/tsconfig.json +++ b/examples/typecheck/tsconfig.json @@ -7,7 +7,8 @@ "declaration": true, "declarationMap": true, "sourceMap": true, - "verbatimModuleSyntax": true + "verbatimModuleSyntax": true, + "skipLibCheck": true }, "include": ["src", "test"], "exclude": ["node_modules"] diff --git a/package.json b/package.json index 166d6c56c7997..7b2f0511afac2 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "test:browser:playwright": "pnpm -C test/browser run test:playwright" }, "devDependencies": { - "@antfu/eslint-config": "^2.6.4", + "@antfu/eslint-config": "^2.15.0", "@antfu/ni": "^0.21.12", "@playwright/test": "^1.41.0", "@rollup/plugin-commonjs": "^25.0.7", @@ -53,7 +53,7 @@ "@vitest/ui": "workspace:*", "bumpp": "^9.2.1", "esbuild": "^0.19.11", - "eslint": "^8.54.0", + "eslint": "^9.1.0", "fast-glob": "^3.3.2", "lint-staged": "^15.1.0", "magic-string": "^0.30.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d34055b9e61a8..04cc0f735f7dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,8 +31,8 @@ importers: .: devDependencies: '@antfu/eslint-config': - specifier: ^2.6.4 - version: 2.6.4(@vue/compiler-sfc@3.4.21)(eslint@8.54.0)(typescript@5.2.2)(vitest@packages+vitest) + specifier: ^2.15.0 + version: 2.15.0(@vue/compiler-sfc@3.4.21)(eslint@9.1.0)(typescript@5.2.2)(vitest@packages+vitest) '@antfu/ni': specifier: ^0.21.12 version: 0.21.12 @@ -73,8 +73,8 @@ importers: specifier: ^0.19.11 version: 0.19.11 eslint: - specifier: ^8.54.0 - version: 8.54.0 + specifier: ^9.1.0 + version: 9.1.0 fast-glob: specifier: ^3.3.2 version: 3.3.2 @@ -2332,87 +2332,91 @@ packages: '@jridgewell/gen-mapping': 0.3.2 '@jridgewell/trace-mapping': 0.3.18 - /@antfu/eslint-config@2.6.4(@vue/compiler-sfc@3.4.21)(eslint@8.54.0)(typescript@5.2.2)(vitest@packages+vitest): - resolution: {integrity: sha512-dMD/QC5KWS1OltdpKLhfZM7W7y7zils85opk8d4lyNr7yn0OFjZs7eMYtcC6DrrN2kQ1JrFvBM7uB0QdWn5PUQ==} + /@antfu/eslint-config@2.15.0(@vue/compiler-sfc@3.4.21)(eslint@9.1.0)(typescript@5.2.2)(vitest@packages+vitest): + resolution: {integrity: sha512-qoqw+0N8bqz0vBIigGJamaIf1LdzXcmCDuleygJAF3EtACLieKyIMvpOdc2TU9AnuPbMBFCkN40340UWRChELw==} hasBin: true peerDependencies: + '@eslint-react/eslint-plugin': ^1.5.8 '@unocss/eslint-plugin': '>=0.50.0' + astro-eslint-parser: ^0.16.3 eslint: '>=8.40.0' + eslint-plugin-astro: ^0.31.4 eslint-plugin-format: '>=0.1.0' - eslint-plugin-react: ^7.33.2 eslint-plugin-react-hooks: ^4.6.0 eslint-plugin-react-refresh: ^0.4.4 - eslint-plugin-svelte: ^2.34.1 + eslint-plugin-solid: ^0.13.2 + eslint-plugin-svelte: '>=2.35.1' + prettier-plugin-astro: ^0.13.0 + prettier-plugin-slidev: ^1.0.5 svelte-eslint-parser: ^0.33.1 peerDependenciesMeta: + '@eslint-react/eslint-plugin': + optional: true '@unocss/eslint-plugin': optional: true - eslint-plugin-format: + astro-eslint-parser: optional: true - eslint-plugin-react: + eslint-plugin-astro: + optional: true + eslint-plugin-format: optional: true eslint-plugin-react-hooks: optional: true eslint-plugin-react-refresh: optional: true + eslint-plugin-solid: + optional: true eslint-plugin-svelte: optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-slidev: + optional: true svelte-eslint-parser: optional: true dependencies: - '@antfu/eslint-define-config': 1.23.0-2 - '@antfu/install-pkg': 0.3.1 - '@eslint-types/jsdoc': 46.8.2-1 - '@eslint-types/typescript-eslint': 6.19.1 - '@eslint-types/unicorn': 50.0.1 - '@stylistic/eslint-plugin': 1.6.0(eslint@8.54.0)(typescript@5.2.2) - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.54.0)(typescript@5.2.2) - '@typescript-eslint/parser': 6.21.0(eslint@8.54.0)(typescript@5.2.2) - eslint: 8.54.0 - eslint-config-flat-gitignore: 0.1.2 - eslint-merge-processors: 0.1.0(eslint@8.54.0) - eslint-plugin-antfu: 2.1.2(eslint@8.54.0) - eslint-plugin-eslint-comments: 3.2.0(eslint@8.54.0) - eslint-plugin-i: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.54.0) - eslint-plugin-jsdoc: 48.0.6(eslint@8.54.0) - eslint-plugin-jsonc: 2.13.0(eslint@8.54.0) - eslint-plugin-markdown: 3.0.1(eslint@8.54.0) - eslint-plugin-n: 16.6.2(eslint@8.54.0) + '@antfu/install-pkg': 0.3.2 + '@clack/prompts': 0.7.0 + '@stylistic/eslint-plugin': 1.7.2(eslint@9.1.0)(typescript@5.2.2) + '@typescript-eslint/eslint-plugin': 7.7.0(@typescript-eslint/parser@7.7.0)(eslint@9.1.0)(typescript@5.2.2) + '@typescript-eslint/parser': 7.7.0(eslint@9.1.0)(typescript@5.2.2) + eslint: 9.1.0 + eslint-config-flat-gitignore: 0.1.5 + eslint-flat-config-utils: 0.2.3 + eslint-merge-processors: 0.1.0(eslint@9.1.0) + eslint-plugin-antfu: 2.1.2(eslint@9.1.0) + eslint-plugin-eslint-comments: 3.2.0(eslint@9.1.0) + eslint-plugin-import-x: 0.5.0(eslint@9.1.0)(typescript@5.2.2) + eslint-plugin-jsdoc: 48.2.3(eslint@9.1.0) + eslint-plugin-jsonc: 2.15.1(eslint@9.1.0) + eslint-plugin-markdown: 4.0.1(eslint@9.1.0) + eslint-plugin-n: 17.2.1(eslint@9.1.0) eslint-plugin-no-only-tests: 3.1.0 - eslint-plugin-perfectionist: 2.5.0(eslint@8.54.0)(typescript@5.2.2)(vue-eslint-parser@9.4.2) - eslint-plugin-toml: 0.9.2(eslint@8.54.0) - eslint-plugin-unicorn: 50.0.1(eslint@8.54.0) - eslint-plugin-unused-imports: 3.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.54.0) - eslint-plugin-vitest: 0.3.22(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.54.0)(typescript@5.2.2)(vitest@packages+vitest) - eslint-plugin-vue: 9.21.1(eslint@8.54.0) - eslint-plugin-yml: 1.12.2(eslint@8.54.0) - eslint-processor-vue-blocks: 0.1.1(@vue/compiler-sfc@3.4.21)(eslint@8.54.0) - globals: 13.24.0 + eslint-plugin-perfectionist: 2.9.0(eslint@9.1.0)(typescript@5.2.2)(vue-eslint-parser@9.4.2) + eslint-plugin-toml: 0.11.0(eslint@9.1.0) + eslint-plugin-unicorn: 52.0.0(eslint@9.1.0) + eslint-plugin-unused-imports: 3.1.0(@typescript-eslint/eslint-plugin@7.7.0)(eslint@9.1.0) + eslint-plugin-vitest: 0.5.3(@typescript-eslint/eslint-plugin@7.7.0)(eslint@9.1.0)(typescript@5.2.2)(vitest@packages+vitest) + eslint-plugin-vue: 9.25.0(eslint@9.1.0) + eslint-plugin-yml: 1.14.0(eslint@9.1.0) + eslint-processor-vue-blocks: 0.1.2(@vue/compiler-sfc@3.4.21)(eslint@9.1.0) + globals: 15.0.0 jsonc-eslint-parser: 2.4.0 local-pkg: 0.5.0 parse-gitignore: 2.0.0 picocolors: 1.0.0 - prompts: 2.4.2 toml-eslint-parser: 0.9.3 - vue-eslint-parser: 9.4.2(eslint@8.54.0) + vue-eslint-parser: 9.4.2(eslint@9.1.0) yaml-eslint-parser: 1.2.2 yargs: 17.7.2 transitivePeerDependencies: - '@vue/compiler-sfc' - - astro-eslint-parser - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - supports-color - svelte - typescript - vitest dev: true - /@antfu/eslint-define-config@1.23.0-2: - resolution: {integrity: sha512-LvxY21+ZhpuBf/aHeBUtGQhSEfad4PkNKXKvDOSvukaM3XVTfBhwmHX2EKwAsdq5DlfjbT3qqYyMiueBIO5iDQ==} - engines: {node: '>=18.0.0', npm: '>=9.0.0', pnpm: '>= 8.6.0'} - dev: true - /@antfu/install-pkg@0.1.1: resolution: {integrity: sha512-LyB/8+bSfa0DFGC06zpCEfs89/XoWZwws5ygEa5D+Xsm3OfI+aXQ86VgVG7Acyef+rSZ5HE7J8rrxzrQeM3PjQ==} dependencies: @@ -2426,6 +2430,12 @@ packages: execa: 8.0.1 dev: true + /@antfu/install-pkg@0.3.2: + resolution: {integrity: sha512-FFYqME8+UHlPnRlX/vn+8cTD4Wo/nG/lzRxpABs3XANBmdJdNImVz3QvjNAE/W3PSCNbG387FOz8o5WelnWOlg==} + dependencies: + execa: 8.0.1 + dev: true + /@antfu/ni@0.21.12: resolution: {integrity: sha512-2aDL3WUv8hMJb2L3r/PIQWsTLyq7RQr3v9xD16fiz6O8ys1xEyLhhTOv8gxtZvJiTzjTF5pHoArvRdesGL1DMQ==} hasBin: true @@ -5989,6 +5999,23 @@ packages: resolution: {integrity: sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw==} dev: true + /@clack/core@0.3.4: + resolution: {integrity: sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==} + dependencies: + picocolors: 1.0.0 + sisteransi: 1.0.5 + dev: true + + /@clack/prompts@0.7.0: + resolution: {integrity: sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==} + dependencies: + '@clack/core': 0.3.4 + picocolors: 1.0.0 + sisteransi: 1.0.5 + dev: true + bundledDependencies: + - is-unicode-supported + /@cnakazawa/watch@1.0.4: resolution: {integrity: sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==} engines: {node: '>=0.1.95'} @@ -6948,13 +6975,13 @@ packages: requiresBuild: true optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.54.0): + /@eslint-community/eslint-utils@4.4.0(eslint@9.1.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.54.0 + eslint: 9.1.0 eslint-visitor-keys: 3.4.3 dev: true @@ -6963,18 +6990,6 @@ packages: engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true - /@eslint-types/jsdoc@46.8.2-1: - resolution: {integrity: sha512-FwD7V0xX0jyaqj8Ul5ZY+TAAPohDfVqtbuXJNHb+OIv1aTIqZi5+Zn3F2UwQ5O3BnQd2mTduyK0+HjGx3/AMFg==} - dev: true - - /@eslint-types/typescript-eslint@6.19.1: - resolution: {integrity: sha512-X0farz1+psE6Qfx6+ISQQ/J3ZetKlUeuTIN9Zt/agx4UXrgK6daH/n9ba776JxysK6YJCRaEHng/bcQQUm+BsA==} - dev: true - - /@eslint-types/unicorn@50.0.1: - resolution: {integrity: sha512-nuJuipTNcg9f+oxZ+3QZw4tuDLmir4RJOPfM/oujgToiy1s+tePDZhwg5jUGc3q8OzTtPbVpsFSYX7QApjO3EA==} - dev: true - /@eslint/eslintrc@1.4.1: resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -6992,14 +7007,14 @@ packages: - supports-color dev: true - /@eslint/eslintrc@2.1.3: - resolution: {integrity: sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==} + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 debug: 4.3.4(supports-color@8.1.1) espree: 9.6.1 - globals: 13.23.0 + globals: 13.24.0 ignore: 5.2.4 import-fresh: 3.3.0 js-yaml: 4.1.0 @@ -7009,14 +7024,14 @@ packages: - supports-color dev: true - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@eslint/eslintrc@3.0.2: + resolution: {integrity: sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: ajv: 6.12.6 debug: 4.3.4(supports-color@8.1.1) - espree: 9.6.1 - globals: 13.24.0 + espree: 10.0.1 + globals: 14.0.0 ignore: 5.2.4 import-fresh: 3.3.0 js-yaml: 4.1.0 @@ -7026,9 +7041,9 @@ packages: - supports-color dev: true - /@eslint/js@8.54.0: - resolution: {integrity: sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@eslint/js@9.1.1: + resolution: {integrity: sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: true /@faker-js/faker@8.2.0: @@ -7086,11 +7101,11 @@ packages: graphql: 16.8.1 dev: false - /@humanwhocodes/config-array@0.11.13: - resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} + /@humanwhocodes/config-array@0.13.0: + resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} dependencies: - '@humanwhocodes/object-schema': 2.0.1 + '@humanwhocodes/object-schema': 2.0.3 debug: 4.3.4(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: @@ -7117,8 +7132,13 @@ packages: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true - /@humanwhocodes/object-schema@2.0.1: - resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + /@humanwhocodes/object-schema@2.0.3: + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + dev: true + + /@humanwhocodes/retry@0.2.3: + resolution: {integrity: sha512-X38nUbachlb01YMlvPFojKoiXq+LzZvuSce70KPMPdeM1Rj03k4dR7lDslhbqXn3Ang4EU3+EAmwEAsbrjHW3g==} + engines: {node: '>=18.18'} dev: true /@iconify-json/carbon@1.1.28: @@ -10257,68 +10277,73 @@ packages: resolve-from: 5.0.0 dev: true - /@stylistic/eslint-plugin-js@1.6.0(eslint@8.54.0): - resolution: {integrity: sha512-qlBAu08fy4d5BEF+c31E5y0OvEOVZo3SfOOs2Qrb4/CwAaXrAch++axBWedzgR3n0XqkuXjr6dbexqrdOm92ag==} + /@stylistic/eslint-plugin-js@1.7.2(eslint@9.1.0): + resolution: {integrity: sha512-ZYX7C5p7zlHbACwFLU+lISVh6tdcRP/++PWegh2Sy0UgMT5kU0XkPa2tKWEtJYzZmPhJxu9LxbnWcnE/tTwSDQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: '>=8.40.0' dependencies: + '@types/eslint': 8.56.10 acorn: 8.11.3 escape-string-regexp: 4.0.0 - eslint: 8.54.0 + eslint: 9.1.0 eslint-visitor-keys: 3.4.3 - espree: 10.0.0 + espree: 9.6.1 dev: true - /@stylistic/eslint-plugin-jsx@1.6.0(eslint@8.54.0): - resolution: {integrity: sha512-MlRpiuNpanQrszotBlar77GDf71HjemJNNQBvLnsk/MHxo6fxbIcAyLSNSVQJhP14ah6PvpPFcExRK4Hj7MGeg==} + /@stylistic/eslint-plugin-jsx@1.7.2(eslint@9.1.0): + resolution: {integrity: sha512-lNZR5PR0HLJPs+kY0y8fy6KroKlYqA5PwsYWpVYWzqZWiL5jgAeUo4s9yLFYjJjzildJ5MsTVMy/xP81Qz6GXg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: '>=8.40.0' dependencies: - '@stylistic/eslint-plugin-js': 1.6.0(eslint@8.54.0) - eslint: 8.54.0 + '@stylistic/eslint-plugin-js': 1.7.2(eslint@9.1.0) + '@types/eslint': 8.56.10 + eslint: 9.1.0 estraverse: 5.3.0 - picomatch: 3.0.1 + picomatch: 4.0.2 dev: true - /@stylistic/eslint-plugin-plus@1.6.0(eslint@8.54.0)(typescript@5.2.2): - resolution: {integrity: sha512-XfLBBkKIERzMYGEX1A5RCe/gVe9pTdGuHC2xDzlEIs2npudMHxm304K7l2CqlAWGyJ/yP6wwrsSEHozQUIo/Og==} + /@stylistic/eslint-plugin-plus@1.7.2(eslint@9.1.0)(typescript@5.2.2): + resolution: {integrity: sha512-luUfRVbBVtt0+/FNt8/76BANJEzb/nHWasHD7UUjyMrch2U9xUKpObrkTCzqBuisKek+uFupwGjqXqDP07+fQw==} peerDependencies: eslint: '*' dependencies: - '@typescript-eslint/utils': 6.21.0(eslint@8.54.0)(typescript@5.2.2) - eslint: 8.54.0 + '@types/eslint': 8.56.10 + '@typescript-eslint/utils': 6.21.0(eslint@9.1.0)(typescript@5.2.2) + eslint: 9.1.0 transitivePeerDependencies: - supports-color - typescript dev: true - /@stylistic/eslint-plugin-ts@1.6.0(eslint@8.54.0)(typescript@5.2.2): - resolution: {integrity: sha512-qM9Vw8TfZeGmN8oreWwUIdEdCs/py9/X88O4ksJv0V/kDmaupVKL8Uu06IlphN2crN6SPU8ljv9rcGXZoxwvmA==} + /@stylistic/eslint-plugin-ts@1.7.2(eslint@9.1.0)(typescript@5.2.2): + resolution: {integrity: sha512-szX89YPocwCe4T0eT3alj7MwEzDHt5+B+kb/vQfSSLIjI9CGgoWrgj50zU8PtaDctTh4ZieFBzU/lRmkSUo0RQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: '>=8.40.0' dependencies: - '@stylistic/eslint-plugin-js': 1.6.0(eslint@8.54.0) - '@typescript-eslint/utils': 6.21.0(eslint@8.54.0)(typescript@5.2.2) - eslint: 8.54.0 + '@stylistic/eslint-plugin-js': 1.7.2(eslint@9.1.0) + '@types/eslint': 8.56.10 + '@typescript-eslint/utils': 6.21.0(eslint@9.1.0)(typescript@5.2.2) + eslint: 9.1.0 transitivePeerDependencies: - supports-color - typescript dev: true - /@stylistic/eslint-plugin@1.6.0(eslint@8.54.0)(typescript@5.2.2): - resolution: {integrity: sha512-Bdz9mFIvOkpM03QLoTSg7rTTYj+u3kokWIQ+nI5UFE+FkRQSVgvL41cwkdCebud/L4dMcItuBPA25h6XOuHFPA==} + /@stylistic/eslint-plugin@1.7.2(eslint@9.1.0)(typescript@5.2.2): + resolution: {integrity: sha512-TesaPR4AOCeD4unwu9gZCdTe8SsUpykriICuwXV8GFBgESuVbfVp+S8g6xTWe9ntVR803bNMtnr2UhxHW0iFqg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: '>=8.40.0' dependencies: - '@stylistic/eslint-plugin-js': 1.6.0(eslint@8.54.0) - '@stylistic/eslint-plugin-jsx': 1.6.0(eslint@8.54.0) - '@stylistic/eslint-plugin-plus': 1.6.0(eslint@8.54.0)(typescript@5.2.2) - '@stylistic/eslint-plugin-ts': 1.6.0(eslint@8.54.0)(typescript@5.2.2) - eslint: 8.54.0 + '@stylistic/eslint-plugin-js': 1.7.2(eslint@9.1.0) + '@stylistic/eslint-plugin-jsx': 1.7.2(eslint@9.1.0) + '@stylistic/eslint-plugin-plus': 1.7.2(eslint@9.1.0)(typescript@5.2.2) + '@stylistic/eslint-plugin-ts': 1.7.2(eslint@9.1.0)(typescript@5.2.2) + '@types/eslint': 8.56.10 + eslint: 9.1.0 transitivePeerDependencies: - supports-color - typescript @@ -10916,6 +10941,13 @@ packages: '@types/json-schema': 7.0.14 dev: true + /@types/eslint@8.56.10: + resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==} + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.14 + dev: true + /@types/estree@0.0.39: resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} dev: true @@ -11089,6 +11121,10 @@ packages: resolution: {integrity: sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==} dev: true + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true + /@types/jsonfile@6.1.4: resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} requiresBuild: true @@ -11353,6 +11389,10 @@ packages: resolution: {integrity: sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==} dev: true + /@types/semver@7.5.8: + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + dev: true + /@types/send@0.17.3: resolution: {integrity: sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==} dependencies: @@ -11524,51 +11564,51 @@ packages: dev: true optional: true - /@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.54.0)(typescript@5.2.2): - resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} - engines: {node: ^16.0.0 || >=18.0.0} + /@typescript-eslint/eslint-plugin@7.7.0(@typescript-eslint/parser@7.7.0)(eslint@9.1.0)(typescript@5.2.2): + resolution: {integrity: sha512-GJWR0YnfrKnsRoluVO3PRb9r5aMZriiMMM/RHj5nnTrBy1/wIgk76XCtCKcnXGjpZQJQRFtGV9/0JJ6n30uwpQ==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: - '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.21.0(eslint@8.54.0)(typescript@5.2.2) - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@8.54.0)(typescript@5.2.2) - '@typescript-eslint/utils': 6.21.0(eslint@8.54.0)(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.21.0 + '@typescript-eslint/parser': 7.7.0(eslint@9.1.0)(typescript@5.2.2) + '@typescript-eslint/scope-manager': 7.7.0 + '@typescript-eslint/type-utils': 7.7.0(eslint@9.1.0)(typescript@5.2.2) + '@typescript-eslint/utils': 7.7.0(eslint@9.1.0)(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 7.7.0 debug: 4.3.4(supports-color@8.1.1) - eslint: 8.54.0 + eslint: 9.1.0 graphemer: 1.4.0 - ignore: 5.2.4 + ignore: 5.3.1 natural-compare: 1.4.0 semver: 7.6.0 - ts-api-utils: 1.0.3(typescript@5.2.2) + ts-api-utils: 1.3.0(typescript@5.2.2) typescript: 5.2.2 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@6.21.0(eslint@8.54.0)(typescript@5.2.2): - resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} - engines: {node: ^16.0.0 || >=18.0.0} + /@typescript-eslint/parser@7.7.0(eslint@9.1.0)(typescript@5.2.2): + resolution: {integrity: sha512-fNcDm3wSwVM8QYL4HKVBggdIPAy9Q41vcvC/GtDobw3c4ndVT3K6cqudUmjHPw8EAp4ufax0o58/xvWaP2FmTg==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 + eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.21.0 + '@typescript-eslint/scope-manager': 7.7.0 + '@typescript-eslint/types': 7.7.0 + '@typescript-eslint/typescript-estree': 7.7.0(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 7.7.0 debug: 4.3.4(supports-color@8.1.1) - eslint: 8.54.0 + eslint: 9.1.0 typescript: 5.2.2 transitivePeerDependencies: - supports-color @@ -11582,21 +11622,29 @@ packages: '@typescript-eslint/visitor-keys': 6.21.0 dev: true - /@typescript-eslint/type-utils@6.21.0(eslint@8.54.0)(typescript@5.2.2): - resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} - engines: {node: ^16.0.0 || >=18.0.0} + /@typescript-eslint/scope-manager@7.7.0: + resolution: {integrity: sha512-/8INDn0YLInbe9Wt7dK4cXLDYp0fNHP5xKLHvZl3mOT5X17rK/YShXaiNmorl+/U4VKCVIjJnx4Ri5b0y+HClw==} + engines: {node: ^18.18.0 || >=20.0.0} + dependencies: + '@typescript-eslint/types': 7.7.0 + '@typescript-eslint/visitor-keys': 7.7.0 + dev: true + + /@typescript-eslint/type-utils@7.7.0(eslint@9.1.0)(typescript@5.2.2): + resolution: {integrity: sha512-bOp3ejoRYrhAlnT/bozNQi3nio9tIgv3U5C0mVDdZC7cpcQEDZXvq8inrHYghLVwuNABRqrMW5tzAv88Vy77Sg==} + engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 + eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.2.2) - '@typescript-eslint/utils': 6.21.0(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 7.7.0(typescript@5.2.2) + '@typescript-eslint/utils': 7.7.0(eslint@9.1.0)(typescript@5.2.2) debug: 4.3.4(supports-color@8.1.1) - eslint: 8.54.0 - ts-api-utils: 1.0.3(typescript@5.2.2) + eslint: 9.1.0 + ts-api-utils: 1.3.0(typescript@5.2.2) typescript: 5.2.2 transitivePeerDependencies: - supports-color @@ -11607,6 +11655,11 @@ packages: engines: {node: ^16.0.0 || >=18.0.0} dev: true + /@typescript-eslint/types@7.7.0: + resolution: {integrity: sha512-G01YPZ1Bd2hn+KPpIbrAhEWOn5lQBrjxkzHkWvP6NucMXFtfXoevK82hzQdpfuQYuhkvFDeQYbzXCjR1z9Z03w==} + engines: {node: ^18.18.0 || >=20.0.0} + dev: true + /@typescript-eslint/typescript-estree@6.21.0(typescript@5.2.2): resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} engines: {node: ^16.0.0 || >=18.0.0} @@ -11629,19 +11682,60 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@6.21.0(eslint@8.54.0)(typescript@5.2.2): + /@typescript-eslint/typescript-estree@7.7.0(typescript@5.2.2): + resolution: {integrity: sha512-8p71HQPE6CbxIBy2kWHqM1KGrC07pk6RJn40n0DSc6bMOBBREZxSDJ+BmRzc8B5OdaMh1ty3mkuWRg4sCFiDQQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 7.7.0 + '@typescript-eslint/visitor-keys': 7.7.0 + debug: 4.3.4(supports-color@8.1.1) + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.4 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@6.21.0(eslint@9.1.0)(typescript@5.2.2): resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.54.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.1.0) '@types/json-schema': 7.0.14 '@types/semver': 7.5.5 '@typescript-eslint/scope-manager': 6.21.0 '@typescript-eslint/types': 6.21.0 '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.2.2) - eslint: 8.54.0 + eslint: 9.1.0 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/utils@7.7.0(eslint@9.1.0)(typescript@5.2.2): + resolution: {integrity: sha512-LKGAXMPQs8U/zMRFXDZOzmMKgFv3COlxUQ+2NMPhbqgVm6R1w+nU1i4836Pmxu9jZAuIeyySNrN/6Rc657ggig==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 || ^9.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.1.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 7.7.0 + '@typescript-eslint/types': 7.7.0 + '@typescript-eslint/typescript-estree': 7.7.0(typescript@5.2.2) + eslint: 9.1.0 semver: 7.6.0 transitivePeerDependencies: - supports-color @@ -11656,6 +11750,14 @@ packages: eslint-visitor-keys: 3.4.3 dev: true + /@typescript-eslint/visitor-keys@7.7.0: + resolution: {integrity: sha512-h0WHOj8MhdhY8YWkzIF30R379y0NqyOHExI9N9KCzvmu05EgG4FumeYa3ccfKUSphyWkWQE1ybVrgz/Pbam6YA==} + engines: {node: ^18.18.0 || >=20.0.0} + dependencies: + '@typescript-eslint/types': 7.7.0 + eslint-visitor-keys: 3.4.3 + dev: true + /@typescript/vfs@1.5.0: resolution: {integrity: sha512-AJS307bPgbsZZ9ggCT3wwpg3VbTKMFNHfaY/uF0ahSkYYrPF2dSSKDNIDIQAHm9qJqbLvCsSJH7yN4Vs/CsMMg==} dependencies: @@ -13080,16 +13182,16 @@ packages: /acorn-globals@7.0.1: resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} dependencies: - acorn: 8.11.2 + acorn: 8.11.3 acorn-walk: 8.3.2 dev: true - /acorn-import-assertions@1.8.0(acorn@8.11.2): + /acorn-import-assertions@1.8.0(acorn@8.11.3): resolution: {integrity: sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==} peerDependencies: acorn: ^8 dependencies: - acorn: 8.11.2 + acorn: 8.11.3 dev: true /acorn-import-assertions@1.9.0(acorn@8.11.3): @@ -13108,14 +13210,6 @@ packages: acorn: 7.4.1 dev: true - /acorn-jsx@5.3.2(acorn@8.11.2): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.11.2 - dev: true - /acorn-jsx@5.3.2(acorn@8.11.3): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -14457,12 +14551,6 @@ packages: resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} dev: true - /builtins@5.0.1: - resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} - dependencies: - semver: 7.6.0 - dev: true - /bumpp@9.2.1: resolution: {integrity: sha512-mq6/e8+bnIsOMy1VceTLC49WucMIZqd2nYn0e7Et5LhTO3yYQ8OWJsTl/B+uJDs5eywZmJ4Yt1WTEd2HCI35pw==} engines: {node: '>=10'} @@ -15403,12 +15491,6 @@ packages: semver: 7.0.0 dev: true - /core-js-compat@3.35.1: - resolution: {integrity: sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==} - dependencies: - browserslist: 4.23.0 - dev: true - /core-js-compat@3.36.1: resolution: {integrity: sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==} dependencies: @@ -17232,31 +17314,39 @@ packages: source-map: 0.6.1 dev: true - /eslint-compat-utils@0.1.2(eslint@8.54.0): + /eslint-compat-utils@0.1.2(eslint@9.1.0): resolution: {integrity: sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==} engines: {node: '>=12'} peerDependencies: eslint: '>=6.0.0' dependencies: - eslint: 8.54.0 + eslint: 9.1.0 dev: true - /eslint-compat-utils@0.4.1(eslint@8.54.0): - resolution: {integrity: sha512-5N7ZaJG5pZxUeNNJfUchurLVrunD1xJvyg5kYOIVF8kg1f3ajTikmAu/5fZ9w100omNPOoMjngRszh/Q/uFGMg==} + /eslint-compat-utils@0.5.0(eslint@9.1.0): + resolution: {integrity: sha512-dc6Y8tzEcSYZMHa+CMPLi/hyo1FzNeonbhJL7Ol0ccuKQkwopJcJBA9YL/xmMTLU1eKigXo9vj9nALElWYSowg==} engines: {node: '>=12'} peerDependencies: eslint: '>=6.0.0' dependencies: - eslint: 8.54.0 + eslint: 9.1.0 semver: 7.6.0 dev: true - /eslint-config-flat-gitignore@0.1.2: - resolution: {integrity: sha512-PcBsqtd5QHEZH4ROvpnRN4EP0qcHh9voCCHgtyHxnJZHGspJREcZn7oPqRG/GfWt9m3C0fkC2l5CuBtMig2wXQ==} + /eslint-config-flat-gitignore@0.1.5: + resolution: {integrity: sha512-hEZLwuZjDBGDERA49c2q7vxc8sCGv8EdBp6PQYzGOMcHIgrfG9YOM6s/4jx24zhD+wnK9AI8mgN5RxSss5nClQ==} dependencies: + find-up: 7.0.0 parse-gitignore: 2.0.0 dev: true + /eslint-flat-config-utils@0.2.3: + resolution: {integrity: sha512-tfrMNXZfuN4q7sFi1Cr//BN3qdI7c8fLJhbshlp8l9PZIqZ7eVeeyd2Regtu/P9kjOlv18lRlBALzsZaF7ByUg==} + dependencies: + '@types/eslint': 8.56.10 + pathe: 1.1.2 + dev: true + /eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} dependencies: @@ -17267,98 +17357,67 @@ packages: - supports-color dev: true - /eslint-merge-processors@0.1.0(eslint@8.54.0): + /eslint-merge-processors@0.1.0(eslint@9.1.0): resolution: {integrity: sha512-IvRXXtEajLeyssvW4wJcZ2etxkR9mUf4zpNwgI+m/Uac9RfXHskuJefkHUcawVzePnd6xp24enp5jfgdHzjRdQ==} peerDependencies: eslint: '*' dependencies: - eslint: 8.54.0 - dev: true - - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint@8.54.0): - resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.54.0)(typescript@5.2.2) - debug: 3.2.7(supports-color@8.1.1) - eslint: 8.54.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color + eslint: 9.1.0 dev: true - /eslint-plugin-antfu@2.1.2(eslint@8.54.0): + /eslint-plugin-antfu@2.1.2(eslint@9.1.0): resolution: {integrity: sha512-s7ZTOM3uq0iqpp6gF0UEotnvup7f2PHBUftCytLZX0+6C9j9KadKZQh6bVVngAyFgsmeD9+gcBopOYLClb2oDg==} peerDependencies: eslint: '*' dependencies: - eslint: 8.54.0 + eslint: 9.1.0 dev: true - /eslint-plugin-es-x@7.5.0(eslint@8.54.0): + /eslint-plugin-es-x@7.5.0(eslint@9.1.0): resolution: {integrity: sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: eslint: '>=8' dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.54.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.1.0) '@eslint-community/regexpp': 4.10.0 - eslint: 8.54.0 - eslint-compat-utils: 0.1.2(eslint@8.54.0) + eslint: 9.1.0 + eslint-compat-utils: 0.1.2(eslint@9.1.0) dev: true - /eslint-plugin-eslint-comments@3.2.0(eslint@8.54.0): + /eslint-plugin-eslint-comments@3.2.0(eslint@9.1.0): resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} engines: {node: '>=6.5.0'} peerDependencies: eslint: '>=4.19.1' dependencies: escape-string-regexp: 1.0.5 - eslint: 8.54.0 + eslint: 9.1.0 ignore: 5.2.4 dev: true - /eslint-plugin-i@2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.54.0): - resolution: {integrity: sha512-ORizX37MelIWLbMyqI7hi8VJMf7A0CskMmYkB+lkCX3aF4pkGV7kwx5bSEb4qx7Yce2rAf9s34HqDRPjGRZPNQ==} - engines: {node: '>=12'} + /eslint-plugin-import-x@0.5.0(eslint@9.1.0)(typescript@5.2.2): + resolution: {integrity: sha512-C7R8Z4IzxmsoOPMtSzwuOBW5FH6iRlxHR6iTks+MzVlrk3r3TUxokkWTx3ypdj9nGOEP+CG/5e6ebZzHbxgbbQ==} + engines: {node: '>=16'} peerDependencies: - eslint: ^7.2.0 || ^8 + eslint: ^8.56.0 || ^9.0.0-0 dependencies: + '@typescript-eslint/utils': 7.7.0(eslint@9.1.0)(typescript@5.2.2) debug: 4.3.4(supports-color@8.1.1) doctrine: 3.0.0 - eslint: 8.54.0 + eslint: 9.1.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint@8.54.0) get-tsconfig: 4.7.3 is-glob: 4.0.3 - minimatch: 3.1.2 + minimatch: 9.0.3 semver: 7.6.0 transitivePeerDependencies: - - '@typescript-eslint/parser' - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - supports-color + - typescript dev: true - /eslint-plugin-jsdoc@48.0.6(eslint@8.54.0): - resolution: {integrity: sha512-LgwXOX6TWxxFYcbdVe+BJ94Kl/pgjSPYHLzqEdAMXTA1BH9WDx7iJ+9/iDajPF64LtzWX8C1mCfpbMZjJGhAOw==} + /eslint-plugin-jsdoc@48.2.3(eslint@9.1.0): + resolution: {integrity: sha512-r9DMAmFs66VNvNqRLLjHejdnJtILrt3xGi+Qx0op0oRfFGVpOR1Hb3BC++MacseHx93d8SKYPhyrC9BS7Os2QA==} engines: {node: '>=18'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 @@ -17368,7 +17427,7 @@ packages: comment-parser: 1.4.1 debug: 4.3.4(supports-color@8.1.1) escape-string-regexp: 4.0.0 - eslint: 8.54.0 + eslint: 9.1.0 esquery: 1.5.0 is-builtin-module: 3.2.1 semver: 7.6.0 @@ -17377,15 +17436,15 @@ packages: - supports-color dev: true - /eslint-plugin-jsonc@2.13.0(eslint@8.54.0): - resolution: {integrity: sha512-2wWdJfpO/UbZzPDABuUVvlUQjfMJa2p2iQfYt/oWxOMpXCcjuiMUSaA02gtY/Dbu82vpaSqc+O7Xq6ECHwtIxA==} + /eslint-plugin-jsonc@2.15.1(eslint@9.1.0): + resolution: {integrity: sha512-PVFrqIJa8BbM/e828RSn0SwB/Z5ye+2LDuy2XqG6AymNgPsfApRRcznsbxP7VrjdLEU4Nb+g9n/d6opyp0jp9A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=6.0.0' dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.54.0) - eslint: 8.54.0 - eslint-compat-utils: 0.4.1(eslint@8.54.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.1.0) + eslint: 9.1.0 + eslint-compat-utils: 0.5.0(eslint@9.1.0) espree: 9.6.1 graphemer: 1.4.0 jsonc-eslint-parser: 2.4.0 @@ -17393,35 +17452,32 @@ packages: synckit: 0.6.2 dev: true - /eslint-plugin-markdown@3.0.1(eslint@8.54.0): - resolution: {integrity: sha512-8rqoc148DWdGdmYF6WSQFT3uQ6PO7zXYgeBpHAOAakX/zpq+NvFYbDA/H7PYzHajwtmaOzAwfxyl++x0g1/N9A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /eslint-plugin-markdown@4.0.1(eslint@9.1.0): + resolution: {integrity: sha512-5/MnGvYU0i8MbHH5cg8S+Vl3DL+bqRNYshk1xUO86DilNBaxtTkhH+5FD0/yO03AmlI6+lfNFdk2yOw72EPzpA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + eslint: '>=8' dependencies: - eslint: 8.54.0 + eslint: 9.1.0 mdast-util-from-markdown: 0.8.5 transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-n@16.6.2(eslint@8.54.0): - resolution: {integrity: sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==} - engines: {node: '>=16.0.0'} + /eslint-plugin-n@17.2.1(eslint@9.1.0): + resolution: {integrity: sha512-uW1+df2bo06kR7ix6nB614RUlvjRPrYxlaX832O6e1MCJp4V7YozEdvMgCYuvn4ltnjPu1FVYhQ2KRrmTNoJfg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: '>=7.0.0' + eslint: '>=8.23.0' dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.54.0) - builtins: 5.0.1 - eslint: 8.54.0 - eslint-plugin-es-x: 7.5.0(eslint@8.54.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.1.0) + enhanced-resolve: 5.15.0 + eslint: 9.1.0 + eslint-plugin-es-x: 7.5.0(eslint@9.1.0) get-tsconfig: 4.7.3 - globals: 13.24.0 + globals: 14.0.0 ignore: 5.2.4 - is-builtin-module: 3.2.1 - is-core-module: 2.13.0 - minimatch: 3.1.2 - resolve: 1.22.8 + minimatch: 9.0.3 semver: 7.6.0 dev: true @@ -17430,8 +17486,8 @@ packages: engines: {node: '>=5.0.0'} dev: true - /eslint-plugin-perfectionist@2.5.0(eslint@8.54.0)(typescript@5.2.2)(vue-eslint-parser@9.4.2): - resolution: {integrity: sha512-F6XXcq4mKKUe/SREoMGQqzgw6cgCgf3pFzkFfQVIGtqD1yXVpQjnhTepzhBeZfxZwgMzR9HO4yH4CUhIQ2WBcQ==} + /eslint-plugin-perfectionist@2.9.0(eslint@9.1.0)(typescript@5.2.2)(vue-eslint-parser@9.4.2): + resolution: {integrity: sha512-ipFtDrqtF99qVVo+FE1fo6aHyLLp7hg6PNGfzY5KxQjcl0XCbyEFvjtR1NfkHDTN9rdFeEDxg59LLOv3VOAHAw==} peerDependencies: astro-eslint-parser: ^0.16.0 eslint: '>=8.0.0' @@ -17448,44 +17504,44 @@ packages: vue-eslint-parser: optional: true dependencies: - '@typescript-eslint/utils': 6.21.0(eslint@8.54.0)(typescript@5.2.2) - eslint: 8.54.0 + '@typescript-eslint/utils': 6.21.0(eslint@9.1.0)(typescript@5.2.2) + eslint: 9.1.0 minimatch: 9.0.3 natural-compare-lite: 1.4.0 - vue-eslint-parser: 9.4.2(eslint@8.54.0) + vue-eslint-parser: 9.4.2(eslint@9.1.0) transitivePeerDependencies: - supports-color - typescript dev: true - /eslint-plugin-toml@0.9.2(eslint@8.54.0): - resolution: {integrity: sha512-ri0xf63PYf3pIq/WY9BIwrqxZmGTIwSkAO0bHddI0ajUwN4KGz6W8vOvdXFHOpRdRfzxlmXze/vfsY/aTEXESg==} + /eslint-plugin-toml@0.11.0(eslint@9.1.0): + resolution: {integrity: sha512-sau+YvPU4fWTjB+qtBt3n8WS87aoDCs+BVbSUAemGaIsRNbvR9uEk+Tt892iLHTGvp/DPWYoCX4/8DoyAbB+sQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=6.0.0' dependencies: debug: 4.3.4(supports-color@8.1.1) - eslint: 8.54.0 - eslint-compat-utils: 0.4.1(eslint@8.54.0) + eslint: 9.1.0 + eslint-compat-utils: 0.5.0(eslint@9.1.0) lodash: 4.17.21 toml-eslint-parser: 0.9.3 transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-unicorn@50.0.1(eslint@8.54.0): - resolution: {integrity: sha512-KxenCZxqSYW0GWHH18okDlOQcpezcitm5aOSz6EnobyJ6BIByiPDviQRjJIUAjG/tMN11958MxaQ+qCoU6lfDA==} + /eslint-plugin-unicorn@52.0.0(eslint@9.1.0): + resolution: {integrity: sha512-1Yzm7/m+0R4djH0tjDjfVei/ju2w3AzUGjG6q8JnuNIL5xIwsflyCooW5sfBvQp2pMYQFSWWCFONsjCax1EHng==} engines: {node: '>=16'} peerDependencies: eslint: '>=8.56.0' dependencies: '@babel/helper-validator-identifier': 7.22.20 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.54.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.1.0) '@eslint/eslintrc': 2.1.4 ci-info: 4.0.0 clean-regexp: 1.0.0 - core-js-compat: 3.35.1 - eslint: 8.54.0 + core-js-compat: 3.36.1 + eslint: 9.1.0 esquery: 1.5.0 indent-string: 4.0.0 is-builtin-module: 3.2.1 @@ -17500,27 +17556,27 @@ packages: - supports-color dev: true - /eslint-plugin-unused-imports@3.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.54.0): - resolution: {integrity: sha512-sduiswLJfZHeeBJ+MQaG+xYzSWdRXoSw61DpU13mzWumCkR0ufD0HmO4kdNokjrkluMHpj/7PJeN35pgbhW3kw==} + /eslint-plugin-unused-imports@3.1.0(@typescript-eslint/eslint-plugin@7.7.0)(eslint@9.1.0): + resolution: {integrity: sha512-9l1YFCzXKkw1qtAru1RWUtG2EVDZY0a0eChKXcL+EZ5jitG7qxdctu4RnvhOJHv4xfmUf7h+JJPINlVpGhZMrw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - '@typescript-eslint/eslint-plugin': ^6.0.0 - eslint: ^8.0.0 + '@typescript-eslint/eslint-plugin': 6 - 7 + eslint: '8' peerDependenciesMeta: '@typescript-eslint/eslint-plugin': optional: true dependencies: - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.54.0)(typescript@5.2.2) - eslint: 8.54.0 + '@typescript-eslint/eslint-plugin': 7.7.0(@typescript-eslint/parser@7.7.0)(eslint@9.1.0)(typescript@5.2.2) + eslint: 9.1.0 eslint-rule-composer: 0.3.0 dev: true - /eslint-plugin-vitest@0.3.22(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.54.0)(typescript@5.2.2)(vitest@packages+vitest): - resolution: {integrity: sha512-atkFGQ7aVgcuSeSMDqnyevIyUpfBPMnosksgEPrKE7Y8xQlqG/5z2IQ6UDau05zXaaFv7Iz8uzqvIuKshjZ0Zw==} + /eslint-plugin-vitest@0.5.3(@typescript-eslint/eslint-plugin@7.7.0)(eslint@9.1.0)(typescript@5.2.2)(vitest@packages+vitest): + resolution: {integrity: sha512-D0iu6ppP6FmNSZP4cdhEXqyI+fuW6JwwWdECRrNymd1jiVgUmDgSvtryytonNxHQQWhGNmZM3V/qvpXttH1rRQ==} engines: {node: ^18.0.0 || >= 20.0.0} peerDependencies: '@typescript-eslint/eslint-plugin': '*' - eslint: '>=8.0.0' + eslint: ^8.57.0 || ^9.0.0 vitest: workspace:* peerDependenciesMeta: '@typescript-eslint/eslint-plugin': @@ -17528,42 +17584,43 @@ packages: vitest: optional: true dependencies: - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.54.0)(typescript@5.2.2) - '@typescript-eslint/utils': 6.21.0(eslint@8.54.0)(typescript@5.2.2) - eslint: 8.54.0 + '@typescript-eslint/eslint-plugin': 7.7.0(@typescript-eslint/parser@7.7.0)(eslint@9.1.0)(typescript@5.2.2) + '@typescript-eslint/utils': 7.7.0(eslint@9.1.0)(typescript@5.2.2) + eslint: 9.1.0 vitest: link:packages/vitest transitivePeerDependencies: - supports-color - typescript dev: true - /eslint-plugin-vue@9.21.1(eslint@8.54.0): - resolution: {integrity: sha512-XVtI7z39yOVBFJyi8Ljbn7kY9yHzznKXL02qQYn+ta63Iy4A9JFBw6o4OSB9hyD2++tVT+su9kQqetUyCCwhjw==} + /eslint-plugin-vue@9.25.0(eslint@9.1.0): + resolution: {integrity: sha512-tDWlx14bVe6Bs+Nnh3IGrD+hb11kf2nukfm6jLsmJIhmiRQ1SUaksvwY9U5MvPB0pcrg0QK0xapQkfITs3RKOA==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: - eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.54.0) - eslint: 8.54.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.1.0) + eslint: 9.1.0 + globals: 13.24.0 natural-compare: 1.4.0 nth-check: 2.1.1 - postcss-selector-parser: 6.0.13 + postcss-selector-parser: 6.0.16 semver: 7.6.0 - vue-eslint-parser: 9.4.2(eslint@8.54.0) + vue-eslint-parser: 9.4.2(eslint@9.1.0) xml-name-validator: 4.0.0 transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-yml@1.12.2(eslint@8.54.0): - resolution: {integrity: sha512-hvS9p08FhPT7i/ynwl7/Wt7ke7Rf4P2D6fT8lZlL43peZDTsHtH2A0SIFQ7Kt7+mJ6if6P+FX3iJhMkdnxQwpg==} + /eslint-plugin-yml@1.14.0(eslint@9.1.0): + resolution: {integrity: sha512-ESUpgYPOcAYQO9czugcX5OqRvn/ydDVwGCPXY4YjPqc09rHaUVUA6IE6HLQys4rXk/S+qx3EwTd1wHCwam/OWQ==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=6.0.0' dependencies: debug: 4.3.4(supports-color@8.1.1) - eslint: 8.54.0 - eslint-compat-utils: 0.4.1(eslint@8.54.0) + eslint: 9.1.0 + eslint-compat-utils: 0.5.0(eslint@9.1.0) lodash: 4.17.21 natural-compare: 1.4.0 yaml-eslint-parser: 1.2.2 @@ -17571,14 +17628,14 @@ packages: - supports-color dev: true - /eslint-processor-vue-blocks@0.1.1(@vue/compiler-sfc@3.4.21)(eslint@8.54.0): - resolution: {integrity: sha512-9+dU5lU881log570oBwpelaJmOfOzSniben7IWEDRYQPPWwlvaV7NhOtsTuUWDqpYT+dtKKWPsgz4OkOi+aZnA==} + /eslint-processor-vue-blocks@0.1.2(@vue/compiler-sfc@3.4.21)(eslint@9.1.0): + resolution: {integrity: sha512-PfpJ4uKHnqeL/fXUnzYkOax3aIenlwewXRX8jFinA1a2yCFnLgMuiH3xvCgvHHUlV2xJWQHbCTdiJWGwb3NqpQ==} peerDependencies: '@vue/compiler-sfc': ^3.3.0 - eslint: ^8.50.0 + eslint: ^8.50.0 || ^9.0.0 dependencies: '@vue/compiler-sfc': 3.4.21 - eslint: 8.54.0 + eslint: 9.1.0 dev: true /eslint-rule-composer@0.3.0: @@ -17610,6 +17667,14 @@ packages: estraverse: 5.3.0 dev: true + /eslint-scope@8.0.1: + resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + /eslint-utils@3.0.0(eslint@8.4.1): resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} @@ -17630,6 +17695,11 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /eslint-visitor-keys@4.0.0: + resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dev: true + /eslint@8.4.1: resolution: {integrity: sha512-TxU/p7LB1KxQ6+7aztTnO7K0i+h0tDi81YRY9VzB6Id71kNz+fFYnf5HD5UOQmxkzcoa0TlVZf9dpMtUv0GpWg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -17654,7 +17724,7 @@ packages: file-entry-cache: 6.0.1 functional-red-black-tree: 1.0.1 glob-parent: 6.0.2 - globals: 13.23.0 + globals: 13.24.0 ignore: 4.0.6 import-fresh: 3.3.0 imurmurhash: 0.1.4 @@ -17677,41 +17747,37 @@ packages: - supports-color dev: true - /eslint@8.54.0: - resolution: {integrity: sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /eslint@9.1.0: + resolution: {integrity: sha512-1TCBecGFQtItia2o39P7Z4BK1X7ByNPxAiWJvwiyTGcOwYnTiiASgMpNA6a+beu8cFPhEDWvPf6mIlYUJv6sgA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.54.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.1.0) '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.3 - '@eslint/js': 8.54.0 - '@humanwhocodes/config-array': 0.11.13 + '@eslint/eslintrc': 3.0.2 + '@eslint/js': 9.1.1 + '@humanwhocodes/config-array': 0.13.0 '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.2.3 '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 debug: 4.3.4(supports-color@8.1.1) - doctrine: 3.0.0 escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 + eslint-scope: 8.0.1 + eslint-visitor-keys: 4.0.0 + espree: 10.0.1 esquery: 1.5.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 + file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.23.0 - graphemer: 1.4.0 ignore: 5.2.4 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 - js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 levn: 0.4.1 lodash.merge: 4.6.2 @@ -17728,21 +17794,21 @@ packages: resolution: {integrity: sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==} dev: true - /espree@10.0.0: - resolution: {integrity: sha512-gdlKrfXQWv/3vubKqeQIiBUoWeknNQVEDpKD7OD3bC53g5EKISTuhcIoA1H1e+zqIuosdKrKuTDMmj8eFfhOnA==} + /espree@10.0.1: + resolution: {integrity: sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: acorn: 8.11.3 acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 + eslint-visitor-keys: 4.0.0 dev: true /espree@9.2.0: resolution: {integrity: sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.11.2 - acorn-jsx: 5.3.2(acorn@8.11.2) + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) eslint-visitor-keys: 3.4.3 dev: true @@ -17750,8 +17816,8 @@ packages: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.11.2 - acorn-jsx: 5.3.2(acorn@8.11.2) + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) eslint-visitor-keys: 3.4.3 dev: true @@ -18282,6 +18348,13 @@ packages: flat-cache: 3.0.4 dev: true + /file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + dependencies: + flat-cache: 4.0.1 + dev: true + /file-loader@6.2.0(webpack@4.46.0): resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} engines: {node: '>= 10.13.0'} @@ -18421,6 +18494,15 @@ packages: path-exists: 5.0.0 dev: true + /find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + dev: true + /flat-cache@3.0.4: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -18429,6 +18511,14 @@ packages: rimraf: 3.0.2 dev: true + /flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + dependencies: + flatted: 3.2.9 + keyv: 4.5.4 + dev: true + /flat@5.0.2: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true @@ -19093,13 +19183,6 @@ packages: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - /globals@13.23.0: - resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - /globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} @@ -19107,6 +19190,16 @@ packages: type-fest: 0.20.2 dev: true + /globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + dev: true + + /globals@15.0.0: + resolution: {integrity: sha512-m/C/yR4mjO6pXDTm9/R/SpYTAIyaUB4EOzcaaMEl7mds7Mshct9GfejiJNQGjHHbdMPey13Kpu4TMbYi9ex1pw==} + engines: {node: '>=18'} + dev: true + /globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} engines: {node: '>= 0.4'} @@ -19866,6 +19959,11 @@ packages: engines: {node: '>= 4'} dev: true + /ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + dev: true + /image-size@0.5.5: resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} engines: {node: '>=0.10.0'} @@ -21701,6 +21799,12 @@ packages: json-buffer: 3.0.1 dev: true + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + /kind-of@3.2.2: resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} engines: {node: '>=0.10.0'} @@ -22034,6 +22138,13 @@ packages: p-locate: 6.0.0 dev: true + /locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-locate: 6.0.0 + dev: true + /lodash.clonedeep@4.5.0: resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} dev: true @@ -22944,6 +23055,13 @@ packages: brace-expansion: 2.0.1 dev: true + /minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: true @@ -24182,6 +24300,10 @@ packages: /pathe@1.1.1: resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} + /pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + dev: true + /pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} dev: false @@ -24228,9 +24350,9 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - /picomatch@3.0.1: - resolution: {integrity: sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==} - engines: {node: '>=10'} + /picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} dev: true /pidtree@0.6.0: @@ -24451,6 +24573,14 @@ packages: util-deprecate: 1.0.2 dev: true + /postcss-selector-parser@6.0.16: + resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + /postcss-value-parser@3.3.1: resolution: {integrity: sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==} dev: false @@ -27577,7 +27707,7 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: - acorn: 8.11.2 + acorn: 8.11.3 commander: 2.20.3 source-map: 0.6.1 source-map-support: 0.5.21 @@ -27589,7 +27719,7 @@ packages: hasBin: true dependencies: '@jridgewell/source-map': 0.3.2 - acorn: 8.11.2 + acorn: 8.11.3 commander: 2.20.3 source-map-support: 0.5.21 dev: true @@ -27871,6 +28001,15 @@ packages: typescript: 5.2.2 dev: true + /ts-api-utils@1.3.0(typescript@5.2.2): + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.2.2 + dev: true + /ts-dedent@2.2.0: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} @@ -28199,6 +28338,11 @@ packages: engines: {node: '>=4'} dev: true + /unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + dev: true + /unified@9.2.0: resolution: {integrity: sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==} dependencies: @@ -29126,14 +29270,14 @@ packages: dependencies: vue: 3.4.21(typescript@5.2.2) - /vue-eslint-parser@9.4.2(eslint@8.54.0): + /vue-eslint-parser@9.4.2(eslint@9.1.0): resolution: {integrity: sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=6.0.0' dependencies: debug: 4.3.4(supports-color@8.1.1) - eslint: 8.54.0 + eslint: 9.1.0 eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 espree: 9.6.1 @@ -29610,8 +29754,8 @@ packages: '@webassemblyjs/ast': 1.11.1 '@webassemblyjs/wasm-edit': 1.11.1 '@webassemblyjs/wasm-parser': 1.11.1 - acorn: 8.11.2 - acorn-import-assertions: 1.8.0(acorn@8.11.2) + acorn: 8.11.3 + acorn-import-assertions: 1.8.0(acorn@8.11.3) browserslist: 4.21.10 chrome-trace-event: 1.0.3 enhanced-resolve: 5.10.0 From 2f0eee8e83d82f887a3f0cbe44e5aa774411e654 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Tue, 23 Apr 2024 13:47:31 +0900 Subject: [PATCH 2/9] chore: run `docs:examples` to add nestjs link (#5594) --- examples/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/README.md b/examples/README.md index 07a53801e566c..cff8964296ab3 100644 --- a/examples/README.md +++ b/examples/README.md @@ -7,6 +7,7 @@ | `lit` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/lit) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/lit?initialPath=__vitest__/) | | `marko` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/marko) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/marko?initialPath=__vitest__/) | | `mocks` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/mocks) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/mocks?initialPath=__vitest__/) | +| `nestjs` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/nestjs) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/nestjs?initialPath=__vitest__/) | | `nextjs` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/nextjs) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/nextjs?initialPath=__vitest__/) | | `playwright` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/playwright) | | | `preact-testing-lib` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/preact-testing-lib) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/preact-testing-lib?initialPath=__vitest__/) | From 4da8804559196635a9bddd2f4a5dd6dbbd13cb2f Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 23 Apr 2024 10:01:21 +0200 Subject: [PATCH 3/9] fix(vitest): stubEnv casts boolean on PROD/SSR/DEV (#5590) --- packages/vitest/src/integrations/vi.ts | 11 ++++++++--- test/core/test/stubs.test.ts | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/packages/vitest/src/integrations/vi.ts b/packages/vitest/src/integrations/vi.ts index f37dbd3a0c919..478bcff9ff708 100644 --- a/packages/vitest/src/integrations/vi.ts +++ b/packages/vitest/src/integrations/vi.ts @@ -292,7 +292,7 @@ export interface VitestUtils { * Changes the value of `import.meta.env` and `process.env`. * You can return it back to original value with `vi.unstubAllEnvs`, or by enabling `unstubEnvs` config option. */ - stubEnv: (name: string, value: string) => VitestUtils + stubEnv: (name: T, value: T extends 'PROD' | 'DEV' | 'SSR' ? boolean : string) => VitestUtils /** * Reset the value to original value that was available before first `vi.stubGlobal` was called. @@ -358,6 +358,8 @@ function createVitest(): VitestUtils { const _stubsGlobal = new Map() const _stubsEnv = new Map() + const _envBooleans = ['PROD', 'DEV', 'SSR'] + const getImporter = () => { const stackTrace = createSimpleStackTrace({ stackTraceLimit: 4 }) const importerStack = stackTrace.split('\n')[4] @@ -550,10 +552,13 @@ function createVitest(): VitestUtils { return utils }, - stubEnv(name: string, value: string) { + stubEnv(name: string, value: string | boolean) { if (!_stubsEnv.has(name)) _stubsEnv.set(name, process.env[name]) - process.env[name] = value + if (_envBooleans.includes(name)) + process.env[name] = value ? '1' : '' + else + process.env[name] = String(value) return utils }, diff --git a/test/core/test/stubs.test.ts b/test/core/test/stubs.test.ts index 9ee8c3a966693..47e5005e952dc 100644 --- a/test/core/test/stubs.test.ts +++ b/test/core/test/stubs.test.ts @@ -104,4 +104,25 @@ describe('stubbing envs', () => { expect(import.meta.env.VITE_TEST_UPDATE_ENV).toBe('development') expect(process.env.VITE_TEST_UPDATE_ENV).toBe('development') }) + + it.each(['PROD', 'DEV', 'SSR'] as const)('requires boolean for env.%s', (name) => { + vi.stubEnv(name as 'PROD', false) + expect(import.meta.env[name]).toBe(false) + expect(process.env[name]).toBe('') + + vi.stubEnv(name as 'PROD', true) + expect(import.meta.env[name]).toBe(true) + expect(process.env[name]).toBe('1') + + // @ts-expect-error PROD, DEV, SSR expect a boolean + vi.stubEnv(name as 'PROD', 'string') + // @ts-expect-error PROD, DEV, SSR expect a boolean + vi.stubEnv(name, 'string') + }) + + it('setting boolean casts the value to string', () => { + // @ts-expect-error value should be a string + vi.stubEnv('MY_TEST_ENV', true) + expect(import.meta.env.MY_TEST_ENV).toBe('true') + }) }) From 597e0c20d044f69ab0088de79208fa52bd66bbe2 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 23 Apr 2024 10:55:31 +0200 Subject: [PATCH 4/9] docs: generate CLI table automatically (#5588) --- docs/.vitepress/scripts/cli-generator.ts | 49 +++++++ docs/guide/cli-table.md | 121 ++++++++++++++++ docs/guide/cli.md | 53 +------ docs/package.json | 3 +- packages/vitest/src/node/cli/cac.ts | 8 +- packages/vitest/src/node/cli/cli-config.ts | 134 +++++++++--------- .../src/node/reporters/renderers/utils.ts | 2 +- 7 files changed, 245 insertions(+), 125 deletions(-) create mode 100644 docs/.vitepress/scripts/cli-generator.ts create mode 100644 docs/guide/cli-table.md diff --git a/docs/.vitepress/scripts/cli-generator.ts b/docs/.vitepress/scripts/cli-generator.ts new file mode 100644 index 0000000000000..a805a92438209 --- /dev/null +++ b/docs/.vitepress/scripts/cli-generator.ts @@ -0,0 +1,49 @@ +import { writeFileSync } from 'node:fs' +import { dirname, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' +import type { CLIOption, CLIOptions } from '../../../packages/vitest/src/node/cli/cli-config' +import { cliOptionsConfig } from '../../../packages/vitest/src/node/cli/cli-config' + +const docsDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..') +const cliTablePath = resolve(docsDir, './guide/cli-table.md') + +const nonNullable = (value: T): value is NonNullable => value !== null && value !== undefined + +function resolveOptions(options: CLIOptions, parentName?: string) { + return Object.entries(options).flatMap( + ([subcommandName, subcommandConfig]) => resolveCommand( + parentName ? `${parentName}.${subcommandName}` : subcommandName, + subcommandConfig, + ), + ).filter(nonNullable) +} + +function resolveCommand(name: string, config: CLIOption | null): any { + if (!config) + return null + + let title = '`' + if (config.shorthand) + title += `-${config.shorthand}, ` + title += `--${config.alias || name}` + if ('argument' in config) + title += ` ${config.argument}` + title += '`' + if ('subcommands' in config && config.subcommands) + return resolveOptions(config.subcommands) + + return { + title, + description: config.description, + } +} + +const options = resolveOptions(cliOptionsConfig) + +const template = ` +| Options | | +| ------------- | ------------- | +${options.map(({ title, description }) => `| ${title} | ${description} |`).join('\n')} +`.trimStart() + +writeFileSync(cliTablePath, template, 'utf-8') diff --git a/docs/guide/cli-table.md b/docs/guide/cli-table.md new file mode 100644 index 0000000000000..187f687b76755 --- /dev/null +++ b/docs/guide/cli-table.md @@ -0,0 +1,121 @@ +| Options | | +| ------------- | ------------- | +| `-r, --root ` | Root path | +| `-c, --config ` | Path to config file | +| `-u, --update` | Update snapshot | +| `-w, --watch` | Enable watch mode | +| `-t, --testNamePattern ` | Run tests with full names matching the specified regexp pattern | +| `--dir ` | Base directory to scan for the test files | +| `--ui` | Enable UI | +| `--open` | Open UI automatically (default: `!process.env.CI`) | +| `--port [port]` | Specify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on. If true will be set to `51204` | +| `--host [host]` | Specify which IP addresses the server should listen on. Set this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses | +| `--strictPort` | Set to true to exit if port is already in use, instead of automatically trying the next available port | +| `--silent` | Silent console output from tests | +| `--hideSkippedTests` | Hide logs for skipped tests | +| `--reporter ` | Specify reporters | +| `--outputFile ` | Write test results to a file when supporter reporter is also specified, use cac's dot notation for individual outputs of multiple reporters (example: --outputFile.tap=./tap.txt) | +| `--all` | Whether to include all files, including the untested ones into report | +| `--provider ` | Select the tool for coverage collection, available values are: "v8", "istanbul" and "custom" | +| `--enabled` | Enables coverage collection. Can be overridden using the `--coverage` CLI option (default: `false`) | +| `--include ` | Files included in coverage as glob patterns. May be specified more than once when using multiple patterns (default: `**`) | +| `--exclude ` | Files to be excluded in coverage. May be specified more than once when using multiple extensions (default: Visit [`coverage.exclude`](https://vitest.dev/config/#coverage-exclude)) | +| `--extension ` | Extension to be included in coverage. May be specified more than once when using multiple extensions (default: `[".js", ".cjs", ".mjs", ".ts", ".mts", ".cts", ".tsx", ".jsx", ".vue", ".svelte"]`) | +| `--clean` | Clean coverage results before running tests (default: true) | +| `--cleanOnRerun` | Clean coverage report on watch rerun (default: true) | +| `--reportsDirectory ` | Directory to write coverage report to (default: ./coverage) | +| `--reporter ` | Coverage reporters to use. Visit [`coverage.reporter`](https://vitest.dev/config/#coverage-reporter) for more information (default: `["text", "html", "clover", "json"]`) | +| `--reportOnFailure` | Generate coverage report even when tests fail (default: false) | +| `--allowExternal` | Collect coverage of files outside the project root (default: false) | +| `--skipFull` | Do not show files with 100% statement, branch, and function coverage (default: false) | +| `--100` | Shortcut to set all coverage thresholds to 100 (default: `false`) | +| `--perFile` | Check thresholds per file. See `--coverage.thresholds.lines`, `--coverage.thresholds.functions`, `--coverage.thresholds.branches` and `--coverage.thresholds.statements` for the actual thresholds (default: `false`) | +| `--autoUpdate` | Update threshold values: "lines", "functions", "branches" and "statements" to configuration file when current coverage is above the configured thresholds (default: `false`) | +| `--lines ` | Threshold for lines. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers | +| `--functions ` | Threshold for functions. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers | +| `--branches ` | Threshold for branches. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers | +| `--statements ` | Threshold for statements. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers | +| `--ignoreClassMethods ` | Array of class method names to ignore for coverage. Visit [istanbuljs](https://github.com/istanbuljs/nyc#ignoring-methods) for more information. This option is only available for the istanbul providers (default: `[]`) | +| `--processingConcurrency ` | Concurrency limit used when processing the coverage results. (default min between 20 and the number of CPUs) | +| `--customProviderModule ` | Specifies the module name or path for the custom coverage provider module. Visit [Custom Coverage Provider](https://vitest.dev/guide/coverage#custom-coverage-provider) for more information. This option is only available for custom providers | +| `--statements ` | High and low watermarks for statements in the format of `,` | +| `--lines ` | High and low watermarks for lines in the format of `,` | +| `--branches ` | High and low watermarks for branches in the format of `,` | +| `--functions ` | High and low watermarks for functions in the format of `,` | +| `--mode ` | Override Vite mode (default: `test` or `benchmark`) | +| `--workspace ` | Path to a workspace configuration file | +| `--isolate` | Run every test file in isolation. To disable isolation, use `--no-isolate` (default: `true`) | +| `--globals` | Inject apis globally | +| `--dom` | Mock browser API with happy-dom | +| `--enabled` | Run tests in the browser. Equivalent to `--browser.enabled` (default: `false`) | +| `--name ` | Run all tests in a specific browser. Some browsers are only available for specific providers (see `--browser.provider`). Visit [`browser.name`](https://vitest.dev/config/#browser-name) for more information | +| `--headless` | Run the browser in headless mode (i.e. without opening the GUI (Graphical User Interface)). If you are running Vitest in CI, it will be enabled by default (default: `process.env.CI`) | +| `--port [port]` | Specify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on. If true will be set to `63315` | +| `--host [host]` | Specify which IP addresses the server should listen on. Set this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses | +| `--strictPort` | Set to true to exit if port is already in use, instead of automatically trying the next available port | +| `--provider ` | Provider used to run browser tests. Some browsers are only available for specific providers. Can be "webdriverio", "playwright", or the path to a custom provider. Visit [`browser.provider`](https://vitest.dev/config/#browser-provider) for more information (default: `"webdriverio"`) | +| `--providerOptions ` | Options that are passed down to a browser provider. Visit [`browser.providerOptions`](https://vitest.dev/config/#browser-provideroptions) for more information | +| `--slowHijackESM` | Let Vitest use its own module resolution on the browser to enable APIs such as vi.mock and vi.spyOn. Visit [`browser.slowHijackESM`](https://vitest.dev/config/#browser-slowhijackesm) for more information (default: `false`) | +| `--isolate` | Run every browser test file in isolation. To disable isolation, use `--browser.isolate=false` (default: `true`) | +| `--fileParallelism` | Should all test files run in parallel. Use `--browser.file-parallelism=false` to disable (default: same as `--file-parallelism`) | +| `--pool ` | Specify pool, if not running in the browser (default: `threads`) | +| `--isolate` | Isolate tests in threads pool (default: `true`) | +| `--singleThread` | Run tests inside a single thread (default: `false`) | +| `--maxThreads ` | Maximum number of threads to run tests in | +| `--minThreads ` | Minimum number of threads to run tests in | +| `--useAtomics` | Use Atomics to synchronize threads. This can improve performance in some cases, but might cause segfault in older Node versions (default: `false`) | +| `--isolate` | Isolate tests in threads pool (default: `true`) | +| `--singleThread` | Run tests inside a single thread (default: `false`) | +| `--maxThreads ` | Maximum number of threads to run tests in | +| `--minThreads ` | Minimum number of threads to run tests in | +| `--useAtomics` | Use Atomics to synchronize threads. This can improve performance in some cases, but might cause segfault in older Node versions (default: `false`) | +| `--memoryLimit ` | Memory limit for VM threads pool. If you see memory leaks, try to tinker this value. | +| `--isolate` | Isolate tests in threads pool (default: `true`) | +| `--singleFork` | Run tests inside a single child_process (default: `false`) | +| `--maxForks ` | Maximum number of processes to run tests in | +| `--minForks ` | Minimum number of processes to run tests in | +| `--isolate` | Isolate tests in threads pool (default: `true`) | +| `--singleFork` | Run tests inside a single child_process (default: `false`) | +| `--maxForks ` | Maximum number of processes to run tests in | +| `--minForks ` | Minimum number of processes to run tests in | +| `--memoryLimit ` | Memory limit for VM forks pool. If you see memory leaks, try to tinker this value. | +| `--fileParallelism` | Should all test files run in parallel. Use `--no-file-parallelism` to disable (default: `true`) | +| `--maxWorkers ` | Maximum number of workers to run tests in | +| `--minWorkers ` | Minimum number of workers to run tests in | +| `--environment ` | Specify runner environment, if not running in the browser (default: `node`) | +| `--passWithNoTests` | Pass when no tests are found | +| `--logHeapUsage` | Show the size of heap for each test when running in node | +| `--allowOnly` | Allow tests and suites that are marked as only (default: `!process.env.CI`) | +| `--dangerouslyIgnoreUnhandledErrors` | Ignore any unhandled errors that occur | +| `--shard ` | Test suite shard to execute in a format of `/` | +| `--changed [since]` | Run tests that are affected by the changed files (default: `false`) | +| `--files` | Run files in a random order. Long running tests will not start earlier if you enable this option. (default: `false`) | +| `--tests` | Run tests in a random oder (default: `false`) | +| `--concurrent` | Make tests run in parallel (default: `false`) | +| `--seed ` | Set the randomization seed. This option will have no effect if --sequence.shuffle is falsy. Visit ["Random Seed" page](https://en.wikipedia.org/wiki/Random_seed) for more information | +| `--hooks ` | Changes the order in which hooks are executed. Accepted values are: "stack", "list" and "parallel". Visit [`sequence.hooks`](https://vitest.dev/config/#sequence-hooks) for more information (default: `"parallel"`) | +| `--setupFiles ` | Changes the order in which setup files are executed. Accepted values are: "list" and "parallel". If set to "list", will run setup files in the order they are defined. If set to "parallel", will run setup files in parallel (default: `"parallel"`) | +| `--inspect [[host:]port]` | Enable Node.js inspector (default: `127.0.0.1:9229`) | +| `--inspectBrk [[host:]port]` | Enable Node.js inspector and break before the test starts | +| `--testTimeout ` | Default timeout of a test in milliseconds (default: `5000`) | +| `--hookTimeout ` | Default hook timeout in milliseconds (default: `10000`) | +| `--bail ` | Stop test execution when given number of tests have failed (default: `0`) | +| `--retry ` | Retry the test specific number of times if it fails (default: `0`) | +| `--diff ` | Path to a diff config that will be used to generate diff interface | +| `--exclude ` | Additional file globs to be excluded from test | +| `--expandSnapshotDiff` | Show full diff when snapshot fails | +| `--disableConsoleIntercept` | Disable automatic interception of console logging (default: `false`) | +| `--enabled` | Enable typechecking alongside tests (default: `false`) | +| `--only` | Run only typecheck tests. This automatically enables typecheck (default: `false`) | +| `--checker ` | Specify the typechecker to use. Available values are: "tcs" and "vue-tsc" and a path to an executable (default: `"tsc"`) | +| `--allowJs` | Allow JavaScript files to be typechecked. By default takes the value from tsconfig.json | +| `--ignoreSourceErrors` | Ignore type errors from source files | +| `--tsconfig ` | Path to a custom tsconfig file | +| `--project ` | The name of the project to run if you are using Vitest workspace feature. This can be repeated for multiple projects: `--project=1 --project=2`. You can also filter projects using wildcards like `--project=packages*` | +| `--slowTestThreshold ` | Threshold in milliseconds for a test to be considered slow (default: `300`) | +| `--teardownTimeout ` | Default timeout of a teardown function in milliseconds (default: `10000`) | +| `--maxConcurrency ` | Maximum number of concurrent tests in a suite (default: `5`) | +| `--run` | Disable watch mode | +| `--segfaultRetry ` | Retry the test suite if it crashes due to a segfault (default: `true`) | +| `--no-color` | Removes colors from the console output | +| `--clearScreen` | Clear terminal screen when re-running tests during watch mode (default: `true`) | diff --git a/docs/guide/cli.md b/docs/guide/cli.md index ef2bf603403e4..9043dd2d2a498 100644 --- a/docs/guide/cli.md +++ b/docs/guide/cli.md @@ -57,58 +57,7 @@ Run only [benchmark](https://vitest.dev/guide/features.html#benchmarking-experim ## Options -| Options | | -| ------------- | ------------- | -| `-v, --version` | Display version number | -| `-r, --root ` | Define the project root | -| `-c, --config ` | Path to config file | -| `-u, --update` | Update snapshots | -| `-w, --watch` | Smart & instant watch mode | -| `-t, --testNamePattern ` | Run tests with full names matching the pattern | -| `--dir `| Base directory to scan for the test files | -| `--ui` | Enable UI | -| `--open` | Open the UI automatically if enabled (default: `true`) | -| `--api [api]` | Serve API, available options: `--api.port `, `--api.host [host]` and `--api.strictPort` | -| `--pool ` | Specify pool, if not running in the browser (default: `threads`) | -| `--poolOptions ` | Specify pool options | -| `--poolOptions.threads.isolate` | Isolate tests in threads pool (default: `true`) | -| `--poolOptions.forks.isolate` | Isolate tests in forks pool (default: `true`) | -| `--fileParallelism` | Should all test files run in parallel. Use --no-file-parallelism to disable (default: true) | -| `--maxWorkers ` | Maximum number of workers to run tests in | -| `--minWorkers ` | Minimum number of workers to run tests in | -| `--silent` | Silent console output from tests | -| `--reporter ` | Select reporter: `default`, `verbose`, `dot`, `junit`, `json`, or a path to a custom reporter | -| `--outputFile ` | Write test results to a file when the `--reporter=json` or `--reporter=junit` option is also specified
Via [cac's dot notation] you can specify individual outputs for multiple reporters | -| `--coverage` | Enable coverage report | -| `--run` | Do not watch | -| `--isolate` | Run every test file in isolation. To disable isolation, use --no-isolate (default: `true`) | -| `--mode ` | Override Vite mode (default: `test`) | -| `--workspace ` | Path to a workspace configuration file | -| `--globals` | Inject APIs globally | -| `--dom` | Mock browser API with happy-dom | -| `--browser [options]` | Run tests in [the browser](/guide/browser) (default: `false`) | -| `--environment ` | Runner environment (default: `node`) | -| `--passWithNoTests` | Pass when no tests found | -| `--logHeapUsage` | Show the size of heap for each test | -| `--allowOnly` | Allow tests and suites that are marked as `only` (default: false in CI, true otherwise) | -| `--dangerouslyIgnoreUnhandledErrors` | Ignore any unhandled errors that occur | -| `--changed [since]` | Run tests that are affected by the changed files (default: false). See [docs](#changed) | -| `--shard ` | Execute tests in a specified shard | -| `--sequence` | Define in what order to run tests. Use [cac's dot notation] to specify options (for example, use `--sequence.shuffle` to run tests in random order or `--sequence.shuffle --sequence.seed SEED_ID` to run a specific order) | -| `--no-color` | Removes colors from the console output | -| `--inspect [[host:]port]` | Enable Node.js inspector (default: 127.0.0.1:9229) | -| `--inspect-brk [[host:]port]` | Enables Node.js inspector and break before the test starts | -| `--bail ` | Stop test execution when given number of tests have failed | -| `--retry ` | Retry the test specific number of times if it fails | -| `--exclude ` | Additional file globs to be excluded from test | -| `--expand-snapshot-diff` | Show full diff when snapshot fails | -| `--disable-console-intercept` | Disable automatic interception of console logging (default: `false`) | -| `--clearScreen` | Clear terminal screen when re-running tests during watch mode (default: `true`) | -| `--typecheck [options]` | Custom options for typecheck pool. If passed without options, enables typechecking | -| `--typecheck.enabled` | Enable typechecking alongside tests (default: `false`) | -| `--typecheck.only` | Run only typecheck tests. This automatically enables typecheck (default: `false`) | -| `--project` | The name of the project to run if you are using Vitest workspace feature. This can be repeated for multiple projects: `--project=1 --project=2`. You can also filter projects using wildcards like `--project=packages*` | -| `-h, --help` | Display available CLI options | + ::: tip Vitest supports both camel case and kebab case for CLI arguments. For example, `--passWithNoTests` and `--pass-with-no-tests` will both work (`--no-color` and `--inspect-brk` are the exceptions). diff --git a/docs/package.json b/docs/package.json index d9fa28b170dc8..0ad8d97067dc4 100644 --- a/docs/package.json +++ b/docs/package.json @@ -4,7 +4,8 @@ "private": true, "scripts": { "dev": "vitepress --port 3333 --open", - "build": "nr prefetch && vitepress build", + "build": "nr cli-table && nr prefetch && vitepress build", + "cli-table": "tsx .vitepress/scripts/cli-generator.ts", "build-no-prefetch": "vitepress build", "serve": "vitepress serve", "preview-https": "pnpm run build && serve .vitepress/dist", diff --git a/packages/vitest/src/node/cli/cac.ts b/packages/vitest/src/node/cli/cac.ts index 8fd4587380aa3..3eb2227157b51 100644 --- a/packages/vitest/src/node/cli/cac.ts +++ b/packages/vitest/src/node/cli/cac.ts @@ -2,11 +2,9 @@ import { normalize } from 'pathe' import cac, { type CAC } from 'cac' import c from 'picocolors' import { version } from '../../../package.json' -import { toArray } from '../../utils' +import { toArray } from '../../utils/base' import type { Vitest, VitestRunMode } from '../../types' -import { divider } from '../reporters/renderers/utils' import type { CliOptions } from './cli-api' -import { startVitest } from './cli-api' import type { CLIOption } from './cli-config' import { cliOptionsConfig } from './cli-config' @@ -35,7 +33,7 @@ function addCommand(cli: CAC, name: string, option: CLIOption) { const hasSubcommands = 'subcommands' in option && option.subcommands if (option.description) { - let description = option.description + let description = option.description.replace(/\[.*\]\((.*)\)/, '$1').replace(/`/g, '') if (hasSubcommands) description += `. Use '--help --${commandName}' for more info.` @@ -242,12 +240,14 @@ async function start(mode: VitestRunMode, cliFilters: string[], options: CliOpti catch {} try { + const { startVitest } = await import('./cli-api') const ctx = await startVitest(mode, cliFilters.map(normalize), normalizeCliOptions(options)) if (!ctx?.shouldKeepServer()) await ctx?.exit() return ctx } catch (e) { + const { divider } = await import('../reporters/renderers/utils') console.error(`\n${c.red(divider(c.bold(c.inverse(' Unhandled Error '))))}`) console.error(e) console.error('\n\n') diff --git a/packages/vitest/src/node/cli/cli-config.ts b/packages/vitest/src/node/cli/cli-config.ts index 13e2c6aa8db94..b104399123b4d 100644 --- a/packages/vitest/src/node/cli/cli-config.ts +++ b/packages/vitest/src/node/cli/cli-config.ts @@ -21,7 +21,7 @@ export type CLIOption = { // require argument for non-boolean options (NonNullable extends boolean ? {} : { argument: string }) -type CLIOptions = { +export type CLIOptions = { [Key in keyof Config as NonNullable extends Function ? never : Key]-?: CLIOption | null } @@ -29,11 +29,11 @@ type VitestCLIOptions = CLIOptions const apiConfig: (port: number) => CLIOptions = (port: number) => ({ port: { - description: `Specify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on. If true will be set to ${port}`, + description: `Specify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on. If true will be set to \`${port}\``, argument: '[port]', }, host: { - description: 'Specify which IP addresses the server should listen on. Set this to 0.0.0.0 or true to listen on all addresses, including LAN and public addresses', + description: 'Specify which IP addresses the server should listen on. Set this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses', argument: '[host]', }, strictPort: { @@ -44,10 +44,10 @@ const apiConfig: (port: number) => CLIOptions = (port: number) => ({ const poolThreadsCommands: CLIOptions = { isolate: { - description: 'Isolate tests in threads pool (default: true)', + description: 'Isolate tests in threads pool (default: `true`)', }, singleThread: { - description: 'Run tests inside a single thread (default: false)', + description: 'Run tests inside a single thread (default: `false`)', }, maxThreads: { description: 'Maximum number of threads to run tests in', @@ -58,17 +58,17 @@ const poolThreadsCommands: CLIOptions = { argument: '', }, useAtomics: { - description: 'Use Atomics to synchronize threads. This can improve performance in some cases, but might cause segfault in older Node versions (default: false)', + description: 'Use Atomics to synchronize threads. This can improve performance in some cases, but might cause segfault in older Node versions (default: `false`)', }, execArgv: null, } const poolForksCommands: CLIOptions = { isolate: { - description: 'Isolate tests in threads pool (default: true)', + description: 'Isolate tests in threads pool (default: `true`)', }, singleFork: { - description: 'Run tests inside a single child_process (default: false)', + description: 'Run tests inside a single child_process (default: `false`)', }, maxForks: { description: 'Maximum number of processes to run tests in', @@ -128,7 +128,7 @@ export const cliOptionsConfig: VitestCLIOptions = { description: 'Enable UI', }, open: { - description: 'Open UI automatically (default: !process.env.CI)', + description: 'Open UI automatically (default: `!process.env.CI`)', }, api: { argument: '[port]', @@ -167,20 +167,20 @@ export const cliOptionsConfig: VitestCLIOptions = { argument: '', }, enabled: { - description: 'Enables coverage collection. Can be overridden using the --coverage CLI option (default: false)', + description: 'Enables coverage collection. Can be overridden using the `--coverage` CLI option (default: `false`)', }, include: { - description: 'Files included in coverage as glob patterns. May be specified more than once when using multiple patterns (default: **)', + description: 'Files included in coverage as glob patterns. May be specified more than once when using multiple patterns (default: `**`)', argument: '', array: true, }, exclude: { - description: 'Files to be excluded in coverage. May be specified more than once when using multiple extensions (default: Visit https://vitest.dev/config/#coverage-exclude)', + description: 'Files to be excluded in coverage. May be specified more than once when using multiple extensions (default: Visit [`coverage.exclude`](https://vitest.dev/config/#coverage-exclude))', argument: '', array: true, }, extension: { - description: 'Extension to be included in coverage. May be specified more than once when using multiple extensions (default: [".js", ".cjs", ".mjs", ".ts", ".mts", ".cts", ".tsx", ".jsx", ".vue", ".svelte"])', + description: 'Extension to be included in coverage. May be specified more than once when using multiple extensions (default: `[".js", ".cjs", ".mjs", ".ts", ".mts", ".cts", ".tsx", ".jsx", ".vue", ".svelte"]`)', argument: '', array: true, }, @@ -196,7 +196,7 @@ export const cliOptionsConfig: VitestCLIOptions = { normalize: true, }, reporter: { - description: 'Coverage reporters to use. Visit https://vitest.dev/config/#coverage-reporter for more information (default: ["text", "html", "clover", "json"])', + description: 'Coverage reporters to use. Visit [`coverage.reporter`](https://vitest.dev/config/#coverage-reporter) for more information (default: `["text", "html", "clover", "json"]`)', argument: '', subcommands: null, // don't support custom objects array: true, @@ -215,34 +215,34 @@ export const cliOptionsConfig: VitestCLIOptions = { argument: '', // no displayed subcommands: { perFile: { - description: 'Check thresholds per file. See --coverage.thresholds.lines, --coverage.thresholds.functions, --coverage.thresholds.branches and --coverage.thresholds.statements for the actual thresholds (default: false)', + description: 'Check thresholds per file. See `--coverage.thresholds.lines`, `--coverage.thresholds.functions`, `--coverage.thresholds.branches` and `--coverage.thresholds.statements` for the actual thresholds (default: `false`)', }, autoUpdate: { - description: 'Update threshold values: "lines", "functions", "branches" and "statements" to configuration file when current coverage is above the configured thresholds (default: false)', + description: 'Update threshold values: "lines", "functions", "branches" and "statements" to configuration file when current coverage is above the configured thresholds (default: `false`)', }, lines: { - description: 'Threshold for lines. Visit https://github.com/istanbuljs/nyc#coverage-thresholds for more information. This option is not available for custom providers', + description: 'Threshold for lines. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers', argument: '', }, functions: { - description: 'Threshold for functions. Visit https://github.com/istanbuljs/nyc#coverage-thresholds for more information. This option is not available for custom providers', + description: 'Threshold for functions. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers', argument: '', }, branches: { - description: 'Threshold for branches. Visit https://github.com/istanbuljs/nyc#coverage-thresholds for more information. This option is not available for custom providers', + description: 'Threshold for branches. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers', argument: '', }, statements: { - description: 'Threshold for statements. Visit https://github.com/istanbuljs/nyc#coverage-thresholds for more information. This option is not available for custom providers', + description: 'Threshold for statements. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers', argument: '', }, 100: { - description: 'Shortcut to set all coverage thresholds to 100 (default: false)', + description: 'Shortcut to set all coverage thresholds to 100 (default: `false`)', }, }, }, ignoreClassMethods: { - description: 'Array of class method names to ignore for coverage. Visit https://github.com/istanbuljs/nyc#ignoring-methods for more information. This option is only available for the istanbul providers (default: [])', + description: 'Array of class method names to ignore for coverage. Visit [istanbuljs](https://github.com/istanbuljs/nyc#ignoring-methods) for more information. This option is only available for the istanbul providers (default: `[]`)', argument: '', array: true, }, @@ -251,7 +251,7 @@ export const cliOptionsConfig: VitestCLIOptions = { argument: '', }, customProviderModule: { - description: 'Specifies the module name or path for the custom coverage provider module. Visit https://vitest.dev/guide/coverage.html#custom-coverage-provider for more information. This option is only available for custom providers', + description: 'Specifies the module name or path for the custom coverage provider module. Visit [Custom Coverage Provider](https://vitest.dev/guide/coverage#custom-coverage-provider) for more information. This option is only available for custom providers', argument: '', normalize: true, }, @@ -260,22 +260,22 @@ export const cliOptionsConfig: VitestCLIOptions = { argument: '', // no displayed subcommands: { statements: { - description: 'High and low watermarks for statements in the format of ,', + description: 'High and low watermarks for statements in the format of `,`', argument: '', transform: watermarkTransform, }, lines: { - description: 'High and low watermarks for lines in the format of ,', + description: 'High and low watermarks for lines in the format of `,`', argument: '', transform: watermarkTransform, }, branches: { - description: 'High and low watermarks for branches in the format of ,', + description: 'High and low watermarks for branches in the format of `,`', argument: '', transform: watermarkTransform, }, functions: { - description: 'High and low watermarks for functions in the format of ,', + description: 'High and low watermarks for functions in the format of `,`', argument: '', transform: watermarkTransform, }, @@ -284,7 +284,7 @@ export const cliOptionsConfig: VitestCLIOptions = { }, }, mode: { - description: 'Override Vite mode (default: test or benchmark)', + description: 'Override Vite mode (default: `test` or `benchmark`)', argument: '', }, workspace: { @@ -293,7 +293,7 @@ export const cliOptionsConfig: VitestCLIOptions = { normalize: true, }, isolate: { - description: 'Run every test file in isolation. To disable isolation, use --no-isolate (default: true)', + description: 'Run every test file in isolation. To disable isolation, use `--no-isolate` (default: `true`)', }, globals: { description: 'Inject apis globally', @@ -302,7 +302,7 @@ export const cliOptionsConfig: VitestCLIOptions = { description: 'Mock browser API with happy-dom', }, browser: { - description: 'Run tests in the browser. Equivalent to --browser.enabled (default: false)', + description: 'Run tests in the browser. Equivalent to `--browser.enabled` (default: `false`)', argument: '', transform(browser) { if (typeof browser === 'boolean') @@ -317,14 +317,14 @@ export const cliOptionsConfig: VitestCLIOptions = { }, subcommands: { enabled: { - description: 'Run tests in the browser. Equivalent to --browser.enabled (default: false)', + description: 'Run tests in the browser. Equivalent to `--browser.enabled` (default: `false`)', }, name: { - description: 'Run all tests in a specific browser. Some browsers are only available for specific providers (see --browser.provider). Visit https://vitest.dev/config/#browser-name for more information', + description: 'Run all tests in a specific browser. Some browsers are only available for specific providers (see `--browser.provider`). Visit [`browser.name`](https://vitest.dev/config/#browser-name) for more information', argument: '', }, headless: { - description: 'Run the browser in headless mode (i.e. without opening the GUI (Graphical User Interface)). If you are running Vitest in CI, it will be enabled by default (default: process.env.CI)', + description: 'Run the browser in headless mode (i.e. without opening the GUI (Graphical User Interface)). If you are running Vitest in CI, it will be enabled by default (default: `process.env.CI`)', }, api: { description: 'Specify options for the browser API server. Does not affect the --api option', @@ -332,28 +332,28 @@ export const cliOptionsConfig: VitestCLIOptions = { subcommands: apiConfig(defaultBrowserPort), }, provider: { - description: 'Provider used to run browser tests. Some browsers are only available for specific providers. Can be "webdriverio", "playwright", or the path to a custom provider. Visit https://vitest.dev/config/#browser-provider for more information (default: "webdriverio")', + description: 'Provider used to run browser tests. Some browsers are only available for specific providers. Can be "webdriverio", "playwright", or the path to a custom provider. Visit [`browser.provider`](https://vitest.dev/config/#browser-provider) for more information (default: `"webdriverio"`)', argument: '', subcommands: null, // don't support custom objects }, providerOptions: { - description: 'Options that are passed down to a browser provider. Visit https://vitest.dev/config/#browser-provideroptions-1-0-0 for more information', + description: 'Options that are passed down to a browser provider. Visit [`browser.providerOptions`](https://vitest.dev/config/#browser-provideroptions) for more information', argument: '', subcommands: null, // don't support custom objects }, slowHijackESM: { - description: 'Let Vitest use its own module resolution on the browser to enable APIs such as vi.mock and vi.spyOn. Visit https://vitest.dev/config/#browser-slowhijackesm for more information (default: false)', + description: 'Let Vitest use its own module resolution on the browser to enable APIs such as vi.mock and vi.spyOn. Visit [`browser.slowHijackESM`](https://vitest.dev/config/#browser-slowhijackesm) for more information (default: `false`)', }, isolate: { - description: 'Run every browser test file in isolation. To disable isolation, use --browser.isolate=false (default: true)', + description: 'Run every browser test file in isolation. To disable isolation, use `--browser.isolate=false` (default: `true`)', }, fileParallelism: { - description: 'Should all test files run in parallel. Use --browser.file-parallelism=false to disable (default: same as --file-parallelism)', + description: 'Should all test files run in parallel. Use `--browser.file-parallelism=false` to disable (default: same as `--file-parallelism`)', }, }, }, pool: { - description: 'Specify pool, if not running in the browser (default: threads)', + description: 'Specify pool, if not running in the browser (default: `threads`)', argument: '', subcommands: null, // don't support custom objects }, @@ -398,7 +398,7 @@ export const cliOptionsConfig: VitestCLIOptions = { }, }, fileParallelism: { - description: 'Should all test files run in parallel. Use --no-file-parallelism to disable (default: true)', + description: 'Should all test files run in parallel. Use `--no-file-parallelism` to disable (default: `true`)', }, maxWorkers: { description: 'Maximum number of workers to run tests in', @@ -409,7 +409,7 @@ export const cliOptionsConfig: VitestCLIOptions = { argument: '', }, environment: { - description: 'Specify runner environment, if not running in the browser (default: node)', + description: 'Specify runner environment, if not running in the browser (default: `node`)', argument: '', subcommands: null, // don't support custom objects }, @@ -420,17 +420,17 @@ export const cliOptionsConfig: VitestCLIOptions = { description: 'Show the size of heap for each test when running in node', }, allowOnly: { - description: 'Allow tests and suites that are marked as only (default: !process.env.CI)', + description: 'Allow tests and suites that are marked as only (default: `!process.env.CI`)', }, dangerouslyIgnoreUnhandledErrors: { description: 'Ignore any unhandled errors that occur', }, shard: { - description: 'Test suite shard to execute in a format of /', + description: 'Test suite shard to execute in a format of `/`', argument: '', }, changed: { - description: 'Run tests that are affected by the changed files (default: false)', + description: 'Run tests that are affected by the changed files (default: `false`)', argument: '[since]', }, sequence: { @@ -438,36 +438,36 @@ export const cliOptionsConfig: VitestCLIOptions = { argument: '', subcommands: { shuffle: { - description: 'Run files and tests in a random order. Enabling this option will impact Vitest\'s cache and have a performance impact. May be useful to find tests that accidentally depend on another run previously (default: false)', + description: 'Run files and tests in a random order. Enabling this option will impact Vitest\'s cache and have a performance impact. May be useful to find tests that accidentally depend on another run previously (default: `false`)', argument: '', subcommands: { files: { - description: 'Run files in a random order. Long running tests will not start earlier if you enable this option. (default: false)', + description: 'Run files in a random order. Long running tests will not start earlier if you enable this option. (default: `false`)', }, tests: { - description: 'Run tests in a random oder (default: false)', + description: 'Run tests in a random oder (default: `false`)', }, }, }, concurrent: { - description: 'Make tests run in parallel (default: false)', + description: 'Make tests run in parallel (default: `false`)', }, seed: { - description: 'Set the randomization seed. This option will have no effect if --sequence.shuffle is falsy. Visit https://en.wikipedia.org/wiki/Random_seed for more information', + description: 'Set the randomization seed. This option will have no effect if --sequence.shuffle is falsy. Visit ["Random Seed" page](https://en.wikipedia.org/wiki/Random_seed) for more information', argument: '', }, hooks: { - description: 'Changes the order in which hooks are executed. Accepted values are: "stack", "list" and "parallel". Visit https://vitest.dev/config/#sequence-hooks for more information (default: "parallel")', + description: 'Changes the order in which hooks are executed. Accepted values are: "stack", "list" and "parallel". Visit [`sequence.hooks`](https://vitest.dev/config/#sequence-hooks) for more information (default: `"parallel"`)', argument: '', }, setupFiles: { - description: 'Changes the order in which setup files are executed. Accepted values are: "list" and "parallel". If set to "list", will run setup files in the order they are defined. If set to "parallel", will run setup files in parallel (default: "parallel")', + description: 'Changes the order in which setup files are executed. Accepted values are: "list" and "parallel". If set to "list", will run setup files in the order they are defined. If set to "parallel", will run setup files in parallel (default: `"parallel"`)', argument: '', }, }, }, inspect: { - description: 'Enable Node.js inspector (default: 127.0.0.1:9229)', + description: 'Enable Node.js inspector (default: `127.0.0.1:9229`)', argument: '[[host:]port]', transform(portOrEnabled) { if (portOrEnabled === 0 || portOrEnabled === 'true' || portOrEnabled === 'yes') @@ -490,19 +490,19 @@ export const cliOptionsConfig: VitestCLIOptions = { }, inspector: null, testTimeout: { - description: 'Default timeout of a test in milliseconds (default: 5000)', + description: 'Default timeout of a test in milliseconds (default: `5000`)', argument: '', }, hookTimeout: { - description: 'Default hook timeout in milliseconds (default: 10000)', + description: 'Default hook timeout in milliseconds (default: `10000`)', argument: '', }, bail: { - description: 'Stop test execution when given number of tests have failed (default: 0)', + description: 'Stop test execution when given number of tests have failed (default: `0`)', argument: '', }, retry: { - description: 'Retry the test specific number of times if it fails (default: 0)', + description: 'Retry the test specific number of times if it fails (default: `0`)', argument: '', }, diff: { @@ -518,21 +518,21 @@ export const cliOptionsConfig: VitestCLIOptions = { description: 'Show full diff when snapshot fails', }, disableConsoleIntercept: { - description: 'Disable automatic interception of console logging (default: false)', + description: 'Disable automatic interception of console logging (default: `false`)', }, typecheck: { - description: 'Enable typechecking alongside tests (default: false)', + description: 'Enable typechecking alongside tests (default: `false`)', argument: '', // allow boolean transform: transformNestedBoolean, subcommands: { enabled: { - description: 'Enable typechecking alongside tests (default: false)', + description: 'Enable typechecking alongside tests (default: `false`)', }, only: { - description: 'Run only typecheck tests. This automatically enables typecheck (default: false)', + description: 'Run only typecheck tests. This automatically enables typecheck (default: `false`)', }, checker: { - description: 'Specify the typechecker to use. Available values are: "tcs" and "vue-tsc" and a path to an executable (default: "tsc")', + description: 'Specify the typechecker to use. Available values are: "tcs" and "vue-tsc" and a path to an executable (default: `"tsc"`)', argument: '', subcommands: null, }, @@ -552,16 +552,16 @@ export const cliOptionsConfig: VitestCLIOptions = { }, }, project: { - description: 'The name of the project to run if you are using Vitest workspace feature. This can be repeated for multiple projects: --project=1 --project=2. You can also filter projects using wildcards like --project=packages*', + description: 'The name of the project to run if you are using Vitest workspace feature. This can be repeated for multiple projects: `--project=1 --project=2`. You can also filter projects using wildcards like `--project=packages*`', argument: '', array: true, }, slowTestThreshold: { - description: 'Threshold in milliseconds for a test to be considered slow (default: 300)', + description: 'Threshold in milliseconds for a test to be considered slow (default: `300`)', argument: '', }, teardownTimeout: { - description: 'Default timeout of a teardown function in milliseconds (default: 10000)', + description: 'Default timeout of a teardown function in milliseconds (default: `10000`)', argument: '', }, cache: { @@ -581,7 +581,7 @@ export const cliOptionsConfig: VitestCLIOptions = { }, }, maxConcurrency: { - description: 'Maximum number of concurrent tests in a suite (default: 5)', + description: 'Maximum number of concurrent tests in a suite (default: `5`)', argument: '', }, @@ -590,7 +590,7 @@ export const cliOptionsConfig: VitestCLIOptions = { description: 'Disable watch mode', }, segfaultRetry: { - description: 'Retry the test suite if it crashes due to a segfault (default: true)', + description: 'Retry the test suite if it crashes due to a segfault (default: `true`)', argument: '', default: 0, }, @@ -599,7 +599,7 @@ export const cliOptionsConfig: VitestCLIOptions = { alias: 'no-color', }, clearScreen: { - description: 'Clear terminal screen when re-running tests during watch mode (default: true)', + description: 'Clear terminal screen when re-running tests during watch mode (default: `true`)', }, // disable CLI options diff --git a/packages/vitest/src/node/reporters/renderers/utils.ts b/packages/vitest/src/node/reporters/renderers/utils.ts index 9522ebfd5597a..26708622e5c7d 100644 --- a/packages/vitest/src/node/reporters/renderers/utils.ts +++ b/packages/vitest/src/node/reporters/renderers/utils.ts @@ -2,7 +2,7 @@ import { basename, dirname, isAbsolute, relative } from 'pathe' import c from 'picocolors' import stripAnsi from 'strip-ansi' import type { SnapshotSummary, Task } from '../../../types' -import { slash } from '../../../utils' +import { slash } from '../../../utils/base' import { F_CHECK, F_CROSS, F_DOT, F_DOWN, F_DOWN_RIGHT, F_LONG_DASH, F_POINTER } from '../../../utils/figures' import type { SuiteHooks } from './../../../types/tasks' From 2b3fc0f16dcbfba5ba49c3eb4d50d789bbef0093 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 23 Apr 2024 11:30:56 +0200 Subject: [PATCH 5/9] docs: fix cli-table generator --- docs/.vitepress/scripts/cli-generator.ts | 2 +- docs/guide/cli-table.md | 146 ++++++++++----------- packages/vitest/src/node/cli/cli-config.ts | 2 +- 3 files changed, 75 insertions(+), 75 deletions(-) diff --git a/docs/.vitepress/scripts/cli-generator.ts b/docs/.vitepress/scripts/cli-generator.ts index a805a92438209..f6ea9e8f8a166 100644 --- a/docs/.vitepress/scripts/cli-generator.ts +++ b/docs/.vitepress/scripts/cli-generator.ts @@ -30,7 +30,7 @@ function resolveCommand(name: string, config: CLIOption | null): any { title += ` ${config.argument}` title += '`' if ('subcommands' in config && config.subcommands) - return resolveOptions(config.subcommands) + return resolveOptions(config.subcommands, name) return { title, diff --git a/docs/guide/cli-table.md b/docs/guide/cli-table.md index 187f687b76755..3f5581b8e2ef9 100644 --- a/docs/guide/cli-table.md +++ b/docs/guide/cli-table.md @@ -8,77 +8,77 @@ | `--dir ` | Base directory to scan for the test files | | `--ui` | Enable UI | | `--open` | Open UI automatically (default: `!process.env.CI`) | -| `--port [port]` | Specify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on. If true will be set to `51204` | -| `--host [host]` | Specify which IP addresses the server should listen on. Set this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses | -| `--strictPort` | Set to true to exit if port is already in use, instead of automatically trying the next available port | +| `--api.port [port]` | Specify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on. If true will be set to `51204` | +| `--api.host [host]` | Specify which IP addresses the server should listen on. Set this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses | +| `--api.strictPort` | Set to true to exit if port is already in use, instead of automatically trying the next available port | | `--silent` | Silent console output from tests | | `--hideSkippedTests` | Hide logs for skipped tests | | `--reporter ` | Specify reporters | | `--outputFile ` | Write test results to a file when supporter reporter is also specified, use cac's dot notation for individual outputs of multiple reporters (example: --outputFile.tap=./tap.txt) | -| `--all` | Whether to include all files, including the untested ones into report | -| `--provider ` | Select the tool for coverage collection, available values are: "v8", "istanbul" and "custom" | -| `--enabled` | Enables coverage collection. Can be overridden using the `--coverage` CLI option (default: `false`) | -| `--include ` | Files included in coverage as glob patterns. May be specified more than once when using multiple patterns (default: `**`) | -| `--exclude ` | Files to be excluded in coverage. May be specified more than once when using multiple extensions (default: Visit [`coverage.exclude`](https://vitest.dev/config/#coverage-exclude)) | -| `--extension ` | Extension to be included in coverage. May be specified more than once when using multiple extensions (default: `[".js", ".cjs", ".mjs", ".ts", ".mts", ".cts", ".tsx", ".jsx", ".vue", ".svelte"]`) | -| `--clean` | Clean coverage results before running tests (default: true) | -| `--cleanOnRerun` | Clean coverage report on watch rerun (default: true) | -| `--reportsDirectory ` | Directory to write coverage report to (default: ./coverage) | -| `--reporter ` | Coverage reporters to use. Visit [`coverage.reporter`](https://vitest.dev/config/#coverage-reporter) for more information (default: `["text", "html", "clover", "json"]`) | -| `--reportOnFailure` | Generate coverage report even when tests fail (default: false) | -| `--allowExternal` | Collect coverage of files outside the project root (default: false) | -| `--skipFull` | Do not show files with 100% statement, branch, and function coverage (default: false) | -| `--100` | Shortcut to set all coverage thresholds to 100 (default: `false`) | -| `--perFile` | Check thresholds per file. See `--coverage.thresholds.lines`, `--coverage.thresholds.functions`, `--coverage.thresholds.branches` and `--coverage.thresholds.statements` for the actual thresholds (default: `false`) | -| `--autoUpdate` | Update threshold values: "lines", "functions", "branches" and "statements" to configuration file when current coverage is above the configured thresholds (default: `false`) | -| `--lines ` | Threshold for lines. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers | -| `--functions ` | Threshold for functions. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers | -| `--branches ` | Threshold for branches. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers | -| `--statements ` | Threshold for statements. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers | -| `--ignoreClassMethods ` | Array of class method names to ignore for coverage. Visit [istanbuljs](https://github.com/istanbuljs/nyc#ignoring-methods) for more information. This option is only available for the istanbul providers (default: `[]`) | -| `--processingConcurrency ` | Concurrency limit used when processing the coverage results. (default min between 20 and the number of CPUs) | -| `--customProviderModule ` | Specifies the module name or path for the custom coverage provider module. Visit [Custom Coverage Provider](https://vitest.dev/guide/coverage#custom-coverage-provider) for more information. This option is only available for custom providers | -| `--statements ` | High and low watermarks for statements in the format of `,` | -| `--lines ` | High and low watermarks for lines in the format of `,` | -| `--branches ` | High and low watermarks for branches in the format of `,` | -| `--functions ` | High and low watermarks for functions in the format of `,` | +| `--coverage.all` | Whether to include all files, including the untested ones into report | +| `--coverage.provider ` | Select the tool for coverage collection, available values are: "v8", "istanbul" and "custom" | +| `--coverage.enabled` | Enables coverage collection. Can be overridden using the `--coverage` CLI option (default: `false`) | +| `--coverage.include ` | Files included in coverage as glob patterns. May be specified more than once when using multiple patterns (default: `**`) | +| `--coverage.exclude ` | Files to be excluded in coverage. May be specified more than once when using multiple extensions (default: Visit [`coverage.exclude`](https://vitest.dev/config/#coverage-exclude)) | +| `--coverage.extension ` | Extension to be included in coverage. May be specified more than once when using multiple extensions (default: `[".js", ".cjs", ".mjs", ".ts", ".mts", ".cts", ".tsx", ".jsx", ".vue", ".svelte"]`) | +| `--coverage.clean` | Clean coverage results before running tests (default: true) | +| `--coverage.cleanOnRerun` | Clean coverage report on watch rerun (default: true) | +| `--coverage.reportsDirectory ` | Directory to write coverage report to (default: ./coverage) | +| `--coverage.reporter ` | Coverage reporters to use. Visit [`coverage.reporter`](https://vitest.dev/config/#coverage-reporter) for more information (default: `["text", "html", "clover", "json"]`) | +| `--coverage.reportOnFailure` | Generate coverage report even when tests fail (default: false) | +| `--coverage.allowExternal` | Collect coverage of files outside the project root (default: false) | +| `--coverage.skipFull` | Do not show files with 100% statement, branch, and function coverage (default: false) | +| `--coverage.thresholds.100` | Shortcut to set all coverage thresholds to 100 (default: `false`) | +| `--coverage.thresholds.perFile` | Check thresholds per file. See `--coverage.thresholds.lines`, `--coverage.thresholds.functions`, `--coverage.thresholds.branches` and `--coverage.thresholds.statements` for the actual thresholds (default: `false`) | +| `--coverage.thresholds.autoUpdate` | Update threshold values: "lines", "functions", "branches" and "statements" to configuration file when current coverage is above the configured thresholds (default: `false`) | +| `--coverage.thresholds.lines ` | Threshold for lines. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers | +| `--coverage.thresholds.functions ` | Threshold for functions. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers | +| `--coverage.thresholds.branches ` | Threshold for branches. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers | +| `--coverage.thresholds.statements ` | Threshold for statements. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers | +| `--coverage.ignoreClassMethods ` | Array of class method names to ignore for coverage. Visit [istanbuljs](https://github.com/istanbuljs/nyc#ignoring-methods) for more information. This option is only available for the istanbul providers (default: `[]`) | +| `--coverage.processingConcurrency ` | Concurrency limit used when processing the coverage results. (default min between 20 and the number of CPUs) | +| `--coverage.customProviderModule ` | Specifies the module name or path for the custom coverage provider module. Visit [Custom Coverage Provider](https://vitest.dev/guide/coverage#custom-coverage-provider) for more information. This option is only available for custom providers | +| `--coverage.watermarks.statements ` | High and low watermarks for statements in the format of `,` | +| `--coverage.watermarks.lines ` | High and low watermarks for lines in the format of `,` | +| `--coverage.watermarks.branches ` | High and low watermarks for branches in the format of `,` | +| `--coverage.watermarks.functions ` | High and low watermarks for functions in the format of `,` | | `--mode ` | Override Vite mode (default: `test` or `benchmark`) | | `--workspace ` | Path to a workspace configuration file | | `--isolate` | Run every test file in isolation. To disable isolation, use `--no-isolate` (default: `true`) | | `--globals` | Inject apis globally | | `--dom` | Mock browser API with happy-dom | -| `--enabled` | Run tests in the browser. Equivalent to `--browser.enabled` (default: `false`) | -| `--name ` | Run all tests in a specific browser. Some browsers are only available for specific providers (see `--browser.provider`). Visit [`browser.name`](https://vitest.dev/config/#browser-name) for more information | -| `--headless` | Run the browser in headless mode (i.e. without opening the GUI (Graphical User Interface)). If you are running Vitest in CI, it will be enabled by default (default: `process.env.CI`) | -| `--port [port]` | Specify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on. If true will be set to `63315` | -| `--host [host]` | Specify which IP addresses the server should listen on. Set this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses | -| `--strictPort` | Set to true to exit if port is already in use, instead of automatically trying the next available port | -| `--provider ` | Provider used to run browser tests. Some browsers are only available for specific providers. Can be "webdriverio", "playwright", or the path to a custom provider. Visit [`browser.provider`](https://vitest.dev/config/#browser-provider) for more information (default: `"webdriverio"`) | -| `--providerOptions ` | Options that are passed down to a browser provider. Visit [`browser.providerOptions`](https://vitest.dev/config/#browser-provideroptions) for more information | -| `--slowHijackESM` | Let Vitest use its own module resolution on the browser to enable APIs such as vi.mock and vi.spyOn. Visit [`browser.slowHijackESM`](https://vitest.dev/config/#browser-slowhijackesm) for more information (default: `false`) | -| `--isolate` | Run every browser test file in isolation. To disable isolation, use `--browser.isolate=false` (default: `true`) | -| `--fileParallelism` | Should all test files run in parallel. Use `--browser.file-parallelism=false` to disable (default: same as `--file-parallelism`) | +| `--browser.enabled` | Run tests in the browser. Equivalent to `--browser.enabled` (default: `false`) | +| `--browser.name ` | Run all tests in a specific browser. Some browsers are only available for specific providers (see `--browser.provider`). Visit [`browser.name`](https://vitest.dev/config/#browser-name) for more information | +| `--browser.headless` | Run the browser in headless mode (i.e. without opening the GUI (Graphical User Interface)). If you are running Vitest in CI, it will be enabled by default (default: `process.env.CI`) | +| `--browser.api.port [port]` | Specify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on. If true will be set to `63315` | +| `--browser.api.host [host]` | Specify which IP addresses the server should listen on. Set this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses | +| `--browser.api.strictPort` | Set to true to exit if port is already in use, instead of automatically trying the next available port | +| `--browser.provider ` | Provider used to run browser tests. Some browsers are only available for specific providers. Can be "webdriverio", "playwright", or the path to a custom provider. Visit [`browser.provider`](https://vitest.dev/config/#browser-provider) for more information (default: `"webdriverio"`) | +| `--browser.providerOptions ` | Options that are passed down to a browser provider. Visit [`browser.providerOptions`](https://vitest.dev/config/#browser-provideroptions) for more information | +| `--browser.slowHijackESM` | Let Vitest use its own module resolution on the browser to enable APIs such as vi.mock and vi.spyOn. Visit [`browser.slowHijackESM`](https://vitest.dev/config/#browser-slowhijackesm) for more information (default: `false`) | +| `--browser.isolate` | Run every browser test file in isolation. To disable isolation, use `--browser.isolate=false` (default: `true`) | +| `--browser.fileParallelism` | Should all test files run in parallel. Use `--browser.file-parallelism=false` to disable (default: same as `--file-parallelism`) | | `--pool ` | Specify pool, if not running in the browser (default: `threads`) | -| `--isolate` | Isolate tests in threads pool (default: `true`) | -| `--singleThread` | Run tests inside a single thread (default: `false`) | -| `--maxThreads ` | Maximum number of threads to run tests in | -| `--minThreads ` | Minimum number of threads to run tests in | -| `--useAtomics` | Use Atomics to synchronize threads. This can improve performance in some cases, but might cause segfault in older Node versions (default: `false`) | -| `--isolate` | Isolate tests in threads pool (default: `true`) | -| `--singleThread` | Run tests inside a single thread (default: `false`) | -| `--maxThreads ` | Maximum number of threads to run tests in | -| `--minThreads ` | Minimum number of threads to run tests in | -| `--useAtomics` | Use Atomics to synchronize threads. This can improve performance in some cases, but might cause segfault in older Node versions (default: `false`) | -| `--memoryLimit ` | Memory limit for VM threads pool. If you see memory leaks, try to tinker this value. | -| `--isolate` | Isolate tests in threads pool (default: `true`) | -| `--singleFork` | Run tests inside a single child_process (default: `false`) | -| `--maxForks ` | Maximum number of processes to run tests in | -| `--minForks ` | Minimum number of processes to run tests in | -| `--isolate` | Isolate tests in threads pool (default: `true`) | -| `--singleFork` | Run tests inside a single child_process (default: `false`) | -| `--maxForks ` | Maximum number of processes to run tests in | -| `--minForks ` | Minimum number of processes to run tests in | -| `--memoryLimit ` | Memory limit for VM forks pool. If you see memory leaks, try to tinker this value. | +| `--poolOptions.threads.isolate` | Isolate tests in threads pool (default: `true`) | +| `--poolOptions.threads.singleThread` | Run tests inside a single thread (default: `false`) | +| `--poolOptions.threads.maxThreads ` | Maximum number of threads to run tests in | +| `--poolOptions.threads.minThreads ` | Minimum number of threads to run tests in | +| `--poolOptions.threads.useAtomics` | Use Atomics to synchronize threads. This can improve performance in some cases, but might cause segfault in older Node versions (default: `false`) | +| `--poolOptions.vmThreads.isolate` | Isolate tests in threads pool (default: `true`) | +| `--poolOptions.vmThreads.singleThread` | Run tests inside a single thread (default: `false`) | +| `--poolOptions.vmThreads.maxThreads ` | Maximum number of threads to run tests in | +| `--poolOptions.vmThreads.minThreads ` | Minimum number of threads to run tests in | +| `--poolOptions.vmThreads.useAtomics` | Use Atomics to synchronize threads. This can improve performance in some cases, but might cause segfault in older Node versions (default: `false`) | +| `--poolOptions.vmThreads.memoryLimit ` | Memory limit for VM threads pool. If you see memory leaks, try to tinker this value. | +| `--poolOptions.forks.isolate` | Isolate tests in forks pool (default: `true`) | +| `--poolOptions.forks.singleFork` | Run tests inside a single child_process (default: `false`) | +| `--poolOptions.forks.maxForks ` | Maximum number of processes to run tests in | +| `--poolOptions.forks.minForks ` | Minimum number of processes to run tests in | +| `--poolOptions.vmForks.isolate` | Isolate tests in forks pool (default: `true`) | +| `--poolOptions.vmForks.singleFork` | Run tests inside a single child_process (default: `false`) | +| `--poolOptions.vmForks.maxForks ` | Maximum number of processes to run tests in | +| `--poolOptions.vmForks.minForks ` | Minimum number of processes to run tests in | +| `--poolOptions.vmForks.memoryLimit ` | Memory limit for VM forks pool. If you see memory leaks, try to tinker this value. | | `--fileParallelism` | Should all test files run in parallel. Use `--no-file-parallelism` to disable (default: `true`) | | `--maxWorkers ` | Maximum number of workers to run tests in | | `--minWorkers ` | Minimum number of workers to run tests in | @@ -89,12 +89,12 @@ | `--dangerouslyIgnoreUnhandledErrors` | Ignore any unhandled errors that occur | | `--shard ` | Test suite shard to execute in a format of `/` | | `--changed [since]` | Run tests that are affected by the changed files (default: `false`) | -| `--files` | Run files in a random order. Long running tests will not start earlier if you enable this option. (default: `false`) | -| `--tests` | Run tests in a random oder (default: `false`) | -| `--concurrent` | Make tests run in parallel (default: `false`) | -| `--seed ` | Set the randomization seed. This option will have no effect if --sequence.shuffle is falsy. Visit ["Random Seed" page](https://en.wikipedia.org/wiki/Random_seed) for more information | -| `--hooks ` | Changes the order in which hooks are executed. Accepted values are: "stack", "list" and "parallel". Visit [`sequence.hooks`](https://vitest.dev/config/#sequence-hooks) for more information (default: `"parallel"`) | -| `--setupFiles ` | Changes the order in which setup files are executed. Accepted values are: "list" and "parallel". If set to "list", will run setup files in the order they are defined. If set to "parallel", will run setup files in parallel (default: `"parallel"`) | +| `--sequence.shuffle.files` | Run files in a random order. Long running tests will not start earlier if you enable this option. (default: `false`) | +| `--sequence.shuffle.tests` | Run tests in a random oder (default: `false`) | +| `--sequence.concurrent` | Make tests run in parallel (default: `false`) | +| `--sequence.seed ` | Set the randomization seed. This option will have no effect if --sequence.shuffle is falsy. Visit ["Random Seed" page](https://en.wikipedia.org/wiki/Random_seed) for more information | +| `--sequence.hooks ` | Changes the order in which hooks are executed. Accepted values are: "stack", "list" and "parallel". Visit [`sequence.hooks`](https://vitest.dev/config/#sequence-hooks) for more information (default: `"parallel"`) | +| `--sequence.setupFiles ` | Changes the order in which setup files are executed. Accepted values are: "list" and "parallel". If set to "list", will run setup files in the order they are defined. If set to "parallel", will run setup files in parallel (default: `"parallel"`) | | `--inspect [[host:]port]` | Enable Node.js inspector (default: `127.0.0.1:9229`) | | `--inspectBrk [[host:]port]` | Enable Node.js inspector and break before the test starts | | `--testTimeout ` | Default timeout of a test in milliseconds (default: `5000`) | @@ -105,12 +105,12 @@ | `--exclude ` | Additional file globs to be excluded from test | | `--expandSnapshotDiff` | Show full diff when snapshot fails | | `--disableConsoleIntercept` | Disable automatic interception of console logging (default: `false`) | -| `--enabled` | Enable typechecking alongside tests (default: `false`) | -| `--only` | Run only typecheck tests. This automatically enables typecheck (default: `false`) | -| `--checker ` | Specify the typechecker to use. Available values are: "tcs" and "vue-tsc" and a path to an executable (default: `"tsc"`) | -| `--allowJs` | Allow JavaScript files to be typechecked. By default takes the value from tsconfig.json | -| `--ignoreSourceErrors` | Ignore type errors from source files | -| `--tsconfig ` | Path to a custom tsconfig file | +| `--typecheck.enabled` | Enable typechecking alongside tests (default: `false`) | +| `--typecheck.only` | Run only typecheck tests. This automatically enables typecheck (default: `false`) | +| `--typecheck.checker ` | Specify the typechecker to use. Available values are: "tcs" and "vue-tsc" and a path to an executable (default: `"tsc"`) | +| `--typecheck.allowJs` | Allow JavaScript files to be typechecked. By default takes the value from tsconfig.json | +| `--typecheck.ignoreSourceErrors` | Ignore type errors from source files | +| `--typecheck.tsconfig ` | Path to a custom tsconfig file | | `--project ` | The name of the project to run if you are using Vitest workspace feature. This can be repeated for multiple projects: `--project=1 --project=2`. You can also filter projects using wildcards like `--project=packages*` | | `--slowTestThreshold ` | Threshold in milliseconds for a test to be considered slow (default: `300`) | | `--teardownTimeout ` | Default timeout of a teardown function in milliseconds (default: `10000`) | diff --git a/packages/vitest/src/node/cli/cli-config.ts b/packages/vitest/src/node/cli/cli-config.ts index b104399123b4d..e89164f05b7ea 100644 --- a/packages/vitest/src/node/cli/cli-config.ts +++ b/packages/vitest/src/node/cli/cli-config.ts @@ -65,7 +65,7 @@ const poolThreadsCommands: CLIOptions = { const poolForksCommands: CLIOptions = { isolate: { - description: 'Isolate tests in threads pool (default: `true`)', + description: 'Isolate tests in forks pool (default: `true`)', }, singleFork: { description: 'Run tests inside a single child_process (default: `false`)', From e0ae82921aaa74e75f24537327805fe583fd7831 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 23 Apr 2024 11:31:31 +0200 Subject: [PATCH 6/9] docs: fix hydration mismatch (#5596) --- docs/guide/index.md | 2 +- docs/vite.config.ts | 20 -------------------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/docs/guide/index.md b/docs/guide/index.md index 36530fd8a5b6e..24d3e455a33e0 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -221,7 +221,7 @@ Learn more about [IDE Integrations](/guide/ide) ## Examples -[@@include](../../../examples/README.md) + ## Projects using Vitest diff --git a/docs/vite.config.ts b/docs/vite.config.ts index 2bd868822bb09..606ceb5c8a9b1 100644 --- a/docs/vite.config.ts +++ b/docs/vite.config.ts @@ -1,10 +1,8 @@ -import fs from 'node:fs' import type { Plugin } from 'vite' import { defineConfig } from 'vite' import Components from 'unplugin-vue-components/vite' import Unocss from 'unocss/vite' import { presetAttributify, presetIcons, presetUno } from 'unocss' -import { resolve } from 'pathe' export default defineConfig({ optimizeDeps: { @@ -37,23 +35,5 @@ export default defineConfig({ }), ], }), - IncludesPlugin(), ], }) - -function IncludesPlugin(): Plugin { - return { - name: 'include-plugin', - enforce: 'pre', - transform(code, id) { - let changed = false - code = code.replace(/\[@@include\]\((.*?)\)/, (_, url) => { - changed = true - const full = resolve(id, url) - return fs.readFileSync(full, 'utf-8') - }) - if (changed) - return code - }, - } -} From b213571009b154c1f31d08aa6f630a0ec719f376 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Tue, 23 Apr 2024 19:00:05 +0900 Subject: [PATCH 7/9] fix(browser): dispose tester iframe on done (#5595) --- packages/browser/src/client/main.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/browser/src/client/main.ts b/packages/browser/src/client/main.ts index 8415846c62fb7..216c7bef57ab0 100644 --- a/packages/browser/src/client/main.ts +++ b/packages/browser/src/client/main.ts @@ -69,6 +69,10 @@ client.ws.addEventListener('open', async () => { const filenames = e.data.filenames filenames.forEach(filename => runningFiles.delete(filename)) + const iframeId = filenames.length > 1 ? ID_ALL : filenames[0] + iframes.get(iframeId)?.remove() + iframes.delete(iframeId) + if (!runningFiles.size) await done() break From 23bd3cd2eb19db46dbed6ff5f4f225f072cec14a Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Tue, 23 Apr 2024 19:01:36 +0900 Subject: [PATCH 8/9] chore: fix test fixture package (#5597) --- pnpm-lock.yaml | 20 +++++--------------- test/vite-node/deps/dep2/package.json | 4 ++-- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 04cc0f735f7dc..9b625bcd5b4ed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2083,7 +2083,7 @@ importers: version: file:test/vite-node/deps/dep1 '@vitest/test-dep2': specifier: file:./deps/dep2 - version: file:test/vite-node/deps/dep2(@vitest/test-dep1@undefined) + version: file:test/vite-node/deps/dep2 execa: specifier: ^6.1.0 version: 6.1.0 @@ -10923,7 +10923,7 @@ packages: /@types/eslint-scope@3.7.6: resolution: {integrity: sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==} dependencies: - '@types/eslint': 8.44.6 + '@types/eslint': 8.56.10 '@types/estree': 1.0.5 dev: true @@ -10934,13 +10934,6 @@ packages: '@types/json-schema': 7.0.14 dev: true - /@types/eslint@8.44.6: - resolution: {integrity: sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==} - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.14 - dev: true - /@types/eslint@8.56.10: resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==} dependencies: @@ -11727,7 +11720,7 @@ packages: resolution: {integrity: sha512-LKGAXMPQs8U/zMRFXDZOzmMKgFv3COlxUQ+2NMPhbqgVm6R1w+nU1i4836Pmxu9jZAuIeyySNrN/6Rc657ggig==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: - eslint: ^8.56.0 || ^9.0.0 + eslint: ^8.56.0 dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.1.0) '@types/json-schema': 7.0.15 @@ -26239,7 +26232,7 @@ packages: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/json-schema': 7.0.14 + '@types/json-schema': 7.0.15 ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) dev: true @@ -30499,12 +30492,9 @@ packages: name: '@vitest/test-dep1' dev: true - file:test/vite-node/deps/dep2(@vitest/test-dep1@undefined): + file:test/vite-node/deps/dep2: resolution: {directory: test/vite-node/deps/dep2, type: directory} - id: file:test/vite-node/deps/dep2 name: '@vitest/test-dep2' - peerDependencies: - '@vitest/test-dep1': '*' dependencies: '@vitest/test-dep1': file:test/vite-node/deps/dep1 dev: true diff --git a/test/vite-node/deps/dep2/package.json b/test/vite-node/deps/dep2/package.json index 81049572392fa..41201919a7186 100644 --- a/test/vite-node/deps/dep2/package.json +++ b/test/vite-node/deps/dep2/package.json @@ -2,7 +2,7 @@ "name": "@vitest/test-dep2", "type": "module", "exports": "./index.js", - "peerDependencies": { - "@vitest/test-dep1": "*" + "dependencies": { + "@vitest/test-dep1": "file:../dep1" } } From 780b187f22d06d09a23a640605da01b349a4354c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Tue, 23 Apr 2024 16:09:20 +0300 Subject: [PATCH 9/9] feat(api): `startVitest()` to accept `stdout` and `stdin` (#5493) --- eslint.config.js | 2 + packages/vitest/rollup.config.js | 1 + packages/vitest/src/node/cli/cli-api.ts | 6 +- packages/vitest/src/node/config.ts | 12 +- packages/vitest/src/node/core.ts | 8 +- packages/vitest/src/node/logger.ts | 12 +- packages/vitest/src/node/reporters/base.ts | 6 +- .../src/node/reporters/github-actions.ts | 3 +- .../node/reporters/renderers/dotRenderer.ts | 5 +- packages/vitest/src/node/stdin.ts | 23 +-- packages/vitest/src/node/watch-filter.ts | 52 +++-- packages/vitest/src/node/workspace.ts | 1 + test/config/test/cache.test.ts | 24 +-- test/config/test/console.test.ts | 11 +- test/config/test/flags.test.ts | 4 +- test/config/test/resolution.test.ts | 29 +-- test/config/test/shuffle-options.test.ts | 12 +- test/core/test/cli-test.test.ts | 2 +- test/inspect/test/inspect.test.ts | 4 +- test/public-api/tests/runner.spec.ts | 4 +- test/reporters/tests/default.test.ts | 16 +- .../pool-custom-fixtures/pool/custom-pool.ts | 8 +- test/run/test/tty.test.ts | 9 +- test/test-utils/cli.ts | 95 +++++++++ test/test-utils/index.ts | 187 +++++------------- test/typescript/test/runner.test.ts | 64 +++--- test/vite-node/test/cli.test.ts | 6 +- test/vite-node/test/hmr.test.ts | 2 +- test/vite-node/test/self-export.test.ts | 8 +- test/watch/test/file-watching.test.ts | 51 +++-- test/watch/test/related.test.ts | 10 +- test/watch/test/stdin.test.ts | 39 ++-- test/watch/test/stdout.test.ts | 7 +- test/watch/test/workspaces.test.ts | 2 +- 34 files changed, 375 insertions(+), 350 deletions(-) create mode 100644 test/test-utils/cli.ts diff --git a/eslint.config.js b/eslint.config.js index 8bab15c5cb951..394db5c50f861 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -13,8 +13,10 @@ export default antfu( '**/assets/**', '**/*.timestamp-*', 'test/core/src/self', + 'test/cache/cache/.vitest-base/results.json', 'test/wasm-modules/src/wasm-bindgen-no-cyclic', 'test/workspaces/results.json', + 'test/workspaces-browser/results.json', 'test/reporters/fixtures/with-syntax-error.test.js', 'test/network-imports/public/slash@3.0.0.js', 'test/coverage-test/src/transpiled.js', diff --git a/packages/vitest/rollup.config.js b/packages/vitest/rollup.config.js index c5542c49a1532..8030ae847fd88 100644 --- a/packages/vitest/rollup.config.js +++ b/packages/vitest/rollup.config.js @@ -65,6 +65,7 @@ const external = [ 'worker_threads', 'node:worker_threads', 'node:fs', + 'node:stream', 'node:vm', 'inspector', 'vite-node/source-map', diff --git a/packages/vitest/src/node/cli/cli-api.ts b/packages/vitest/src/node/cli/cli-api.ts index 991f54d59f445..739321a30b9ba 100644 --- a/packages/vitest/src/node/cli/cli-api.ts +++ b/packages/vitest/src/node/cli/cli-api.ts @@ -73,9 +73,11 @@ export async function startVitest( return ctx } + const stdin = vitestOptions?.stdin || process.stdin + const stdout = vitestOptions?.stdout || process.stdout let stdinCleanup - if (process.stdin.isTTY && ctx.config.watch) - stdinCleanup = registerConsoleShortcuts(ctx) + if (stdin.isTTY && ctx.config.watch) + stdinCleanup = registerConsoleShortcuts(ctx, stdin, stdout) ctx.onServerRestart((reason) => { ctx.report('onServerRestart', reason) diff --git a/packages/vitest/src/node/config.ts b/packages/vitest/src/node/config.ts index 6ca6a4139fbbc..167b90e5073c2 100644 --- a/packages/vitest/src/node/config.ts +++ b/packages/vitest/src/node/config.ts @@ -12,6 +12,7 @@ import { BaseSequencer } from './sequencers/BaseSequencer' import { RandomSequencer } from './sequencers/RandomSequencer' import type { BenchmarkBuiltinReporters } from './reporters' import { builtinPools } from './pool' +import type { Logger } from './logger' function resolvePath(path: string, root: string) { return normalize( @@ -76,13 +77,14 @@ export function resolveConfig( mode: VitestRunMode, options: UserConfig, viteConfig: ResolvedViteConfig, + logger: Logger, ): ResolvedConfig { if (options.dom) { if ( viteConfig.test?.environment != null && viteConfig.test!.environment !== 'happy-dom' ) { - console.warn( + logger.console.warn( c.yellow( `${c.inverse(c.yellow(' Vitest '))} Your config.test.environment ("${ viteConfig.test.environment @@ -209,11 +211,11 @@ export function resolveConfig( return if (option === 'fallbackCJS') { - console.warn(c.yellow(`${c.inverse(c.yellow(' Vitest '))} "deps.${option}" is deprecated. Use "server.deps.${option}" instead`)) + logger.console.warn(c.yellow(`${c.inverse(c.yellow(' Vitest '))} "deps.${option}" is deprecated. Use "server.deps.${option}" instead`)) } else { const transformMode = resolved.environment === 'happy-dom' || resolved.environment === 'jsdom' ? 'web' : 'ssr' - console.warn( + logger.console.warn( c.yellow( `${c.inverse(c.yellow(' Vitest '))} "deps.${option}" is deprecated. If you rely on vite-node directly, use "server.deps.${option}" instead. Otherwise, consider using "deps.optimizer.${transformMode}.${option === 'external' ? 'exclude' : 'include'}"`, ), @@ -475,7 +477,7 @@ export function resolveConfig( let cacheDir = VitestCache.resolveCacheDir('', resolve(viteConfig.cacheDir, 'vitest'), resolved.name) if (resolved.cache && resolved.cache.dir) { - console.warn( + logger.console.warn( c.yellow( `${c.inverse(c.yellow(' Vitest '))} "cache.dir" is deprecated, use Vite's "cacheDir" instead if you want to change the cache director. Note caches will be written to "cacheDir\/vitest"`, ), @@ -514,7 +516,7 @@ export function resolveConfig( resolved.typecheck.enabled ??= false if (resolved.typecheck.enabled) - console.warn(c.yellow('Testing types with tsc and vue-tsc is an experimental feature.\nBreaking changes might not follow SemVer, please pin Vitest\'s version when using it.')) + logger.console.warn(c.yellow('Testing types with tsc and vue-tsc is an experimental feature.\nBreaking changes might not follow SemVer, please pin Vitest\'s version when using it.')) resolved.browser ??= {} as any resolved.browser.enabled ??= false diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts index 46f9e0f80d97b..4cfed6786c2f1 100644 --- a/packages/vitest/src/node/core.ts +++ b/packages/vitest/src/node/core.ts @@ -1,4 +1,5 @@ import { existsSync, promises as fs } from 'node:fs' +import type { Writable } from 'node:stream' import { isMainThread } from 'node:worker_threads' import type { ViteDevServer } from 'vite' import { mergeConfig } from 'vite' @@ -31,6 +32,9 @@ const WATCHER_DEBOUNCE = 100 export interface VitestOptions { packageInstaller?: VitestPackageInstaller + stdin?: NodeJS.ReadStream + stdout?: NodeJS.WriteStream | Writable + stderr?: NodeJS.WriteStream | Writable } export class Vitest { @@ -74,7 +78,7 @@ export class Vitest { public readonly mode: VitestRunMode, options: VitestOptions = {}, ) { - this.logger = new Logger(this) + this.logger = new Logger(this, options.stdout, options.stderr) this.packageInstaller = options.packageInstaller || new VitestPackageInstaller() } @@ -93,7 +97,7 @@ export class Vitest { this.runningPromise = undefined this.projectsTestFiles.clear() - const resolved = resolveConfig(this.mode, options, server.config) + const resolved = resolveConfig(this.mode, options, server.config, this.logger) this.server = server this.config = resolved diff --git a/packages/vitest/src/node/logger.ts b/packages/vitest/src/node/logger.ts index a494c9b619eee..130794c4d7d5e 100644 --- a/packages/vitest/src/node/logger.ts +++ b/packages/vitest/src/node/logger.ts @@ -1,3 +1,5 @@ +import { Console } from 'node:console' +import type { Writable } from 'node:stream' import { createLogUpdate } from 'log-update' import c from 'picocolors' import { version } from '../../../../package.json' @@ -24,17 +26,19 @@ const CURSOR_TO_START = `${ESC}1;1H` const CLEAR_SCREEN = '\x1Bc' export class Logger { - outputStream = process.stdout - errorStream = process.stderr - logUpdate = createLogUpdate(process.stdout) + logUpdate: ReturnType private _clearScreenPending: string | undefined private _highlights = new Map() + public console: Console constructor( public ctx: Vitest, - public console = globalThis.console, + public outputStream: NodeJS.WriteStream | Writable = process.stdout, + public errorStream: NodeJS.WriteStream | Writable = process.stderr, ) { + this.console = new Console({ stdout: outputStream, stderr: errorStream }) + this.logUpdate = createLogUpdate(this.outputStream) this._highlights.clear() } diff --git a/packages/vitest/src/node/reporters/base.ts b/packages/vitest/src/node/reporters/base.ts index f1b149b763786..7f791108b7237 100644 --- a/packages/vitest/src/node/reporters/base.ts +++ b/packages/vitest/src/node/reporters/base.ts @@ -191,7 +191,11 @@ export abstract class BaseReporter implements Reporter { return const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : undefined const header = c.gray(log.type + c.dim(` | ${task ? getFullName(task, c.dim(' > ')) : log.taskId !== UNKNOWN_TEST_ID ? log.taskId : 'unknown test'}`)) - process[log.type].write(`${header}\n${log.content}\n`) + + const output = log.type === 'stdout' ? this.ctx.logger.outputStream : this.ctx.logger.errorStream + + // @ts-expect-error -- write() method has different signature on the union type + output.write(`${header}\n${log.content}\n`) } shouldLog(log: UserConsoleLog) { diff --git a/packages/vitest/src/node/reporters/github-actions.ts b/packages/vitest/src/node/reporters/github-actions.ts index 0ec2f7de412db..8863bb7bbd504 100644 --- a/packages/vitest/src/node/reporters/github-actions.ts +++ b/packages/vitest/src/node/reporters/github-actions.ts @@ -1,4 +1,3 @@ -import { Console } from 'node:console' import { Writable } from 'node:stream' import { getTasks } from '@vitest/runner/utils' import stripAnsi from 'strip-ansi' @@ -76,7 +75,7 @@ async function printErrorWrapper(error: unknown, ctx: Vitest, project: Workspace }) const result = await printError(error, project, { showCodeFrame: false, - logger: new Logger(ctx, new Console(writable, writable)), + logger: new Logger(ctx, writable, writable), }) return { nearest: result?.nearest, output } } diff --git a/packages/vitest/src/node/reporters/renderers/dotRenderer.ts b/packages/vitest/src/node/reporters/renderers/dotRenderer.ts index 86a8e09ccb109..b09d666efb661 100644 --- a/packages/vitest/src/node/reporters/renderers/dotRenderer.ts +++ b/packages/vitest/src/node/reporters/renderers/dotRenderer.ts @@ -92,9 +92,10 @@ export function createDotRenderer(_tasks: Task[], options: DotRendererOptions) { let timer: any const { logUpdate: log, outputStream } = options.logger + const columns = 'columns' in outputStream ? outputStream.columns : 80 function update() { - log(render(tasks, outputStream.columns)) + log(render(tasks, columns)) } return { @@ -114,7 +115,7 @@ export function createDotRenderer(_tasks: Task[], options: DotRendererOptions) { timer = undefined } log.clear() - options.logger.log(render(tasks, outputStream.columns)) + options.logger.log(render(tasks, columns)) return this }, clear() { diff --git a/packages/vitest/src/node/stdin.ts b/packages/vitest/src/node/stdin.ts index f055ebf869e76..543922081ce5d 100644 --- a/packages/vitest/src/node/stdin.ts +++ b/packages/vitest/src/node/stdin.ts @@ -1,4 +1,5 @@ import readline from 'node:readline' +import type { Writable } from 'node:stream' import c from 'picocolors' import prompt from 'prompts' import { relative } from 'pathe' @@ -28,7 +29,7 @@ ${keys.map(i => c.dim(' press ') + c.reset([i[0]].flat().map(c.bold).join(', ') ) } -export function registerConsoleShortcuts(ctx: Vitest) { +export function registerConsoleShortcuts(ctx: Vitest, stdin: NodeJS.ReadStream = process.stdin, stdout: NodeJS.WriteStream | Writable) { let latestFilename = '' async function _keypressHandler(str: string, key: any) { @@ -97,7 +98,7 @@ export function registerConsoleShortcuts(ctx: Vitest) { async function inputNamePattern() { off() - const watchFilter = new WatchFilter('Input test name pattern (RegExp)') + const watchFilter = new WatchFilter('Input test name pattern (RegExp)', stdin, stdout) const filter = await watchFilter.filter((str: string) => { const files = ctx.state.getFiles() const tests = getTests(files) @@ -130,7 +131,7 @@ export function registerConsoleShortcuts(ctx: Vitest) { async function inputFilePattern() { off() - const watchFilter = new WatchFilter('Input filename pattern') + const watchFilter = new WatchFilter('Input filename pattern', stdin, stdout) const filter = await watchFilter.filter(async (str: string) => { const files = await ctx.globTestFiles([str]) @@ -149,19 +150,19 @@ export function registerConsoleShortcuts(ctx: Vitest) { let rl: readline.Interface | undefined function on() { off() - rl = readline.createInterface({ input: process.stdin, escapeCodeTimeout: 50 }) - readline.emitKeypressEvents(process.stdin, rl) - if (process.stdin.isTTY) - process.stdin.setRawMode(true) - process.stdin.on('keypress', keypressHandler) + rl = readline.createInterface({ input: stdin, escapeCodeTimeout: 50 }) + readline.emitKeypressEvents(stdin, rl) + if (stdin.isTTY) + stdin.setRawMode(true) + stdin.on('keypress', keypressHandler) } function off() { rl?.close() rl = undefined - process.stdin.removeListener('keypress', keypressHandler) - if (process.stdin.isTTY) - process.stdin.setRawMode(false) + stdin.removeListener('keypress', keypressHandler) + if (stdin.isTTY) + stdin.setRawMode(false) } on() diff --git a/packages/vitest/src/node/watch-filter.ts b/packages/vitest/src/node/watch-filter.ts index 93060f93cf2d2..788593d9918c4 100644 --- a/packages/vitest/src/node/watch-filter.ts +++ b/packages/vitest/src/node/watch-filter.ts @@ -1,8 +1,9 @@ import readline from 'node:readline' +import type { Writable } from 'node:stream' import c from 'picocolors' import stripAnsi from 'strip-ansi' import { createDefer } from '@vitest/utils' -import { stdout } from '../utils' +import { stdout as getStdout } from '../utils' const MAX_RESULT_COUNT = 10 const SELECTION_MAX_INDEX = 7 @@ -17,24 +18,29 @@ export class WatchFilter { private results: string[] = [] private selectionIndex = -1 private onKeyPress?: (str: string, key: any) => void + private stdin: NodeJS.ReadStream + private stdout: NodeJS.WriteStream | Writable - constructor(message: string) { + constructor(message: string, stdin: NodeJS.ReadStream = process.stdin, stdout: NodeJS.WriteStream | Writable = getStdout()) { this.message = message - this.filterRL = readline.createInterface({ input: process.stdin, escapeCodeTimeout: 50 }) - readline.emitKeypressEvents(process.stdin, this.filterRL) - if (process.stdin.isTTY) - process.stdin.setRawMode(true) + this.stdin = stdin + this.stdout = stdout + + this.filterRL = readline.createInterface({ input: this.stdin, escapeCodeTimeout: 50 }) + readline.emitKeypressEvents(this.stdin, this.filterRL) + if (this.stdin.isTTY) + this.stdin.setRawMode(true) } public async filter(filterFunc: FilterFunc): Promise { - stdout().write(this.promptLine()) + this.write(this.promptLine()) const resultPromise = createDefer() this.onKeyPress = this.filterHandler(filterFunc, (result) => { resultPromise.resolve(result) }) - process.stdin.on('keypress', this.onKeyPress) + this.stdin.on('keypress', this.onKeyPress) try { return await resultPromise } @@ -138,31 +144,39 @@ export class WatchFilter { private eraseAndPrint(str: string) { let rows = 0 const lines = str.split(/\r?\n/) - for (const line of lines) + for (const line of lines) { + const columns = 'columns' in this.stdout ? this.stdout.columns : 80 + // We have to take care of screen width in case of long lines - rows += 1 + Math.floor(Math.max(stripAnsi(line).length - 1, 0) / stdout().columns) + rows += 1 + Math.floor(Math.max(stripAnsi(line).length - 1, 0) / columns) + } - stdout().write(`${ESC}1G`) // move to the beginning of the line - stdout().write(`${ESC}J`) // erase down - stdout().write(str) - stdout().write(`${ESC}${rows - 1}A`) // moving up lines + this.write(`${ESC}1G`) // move to the beginning of the line + this.write(`${ESC}J`) // erase down + this.write(str) + this.write(`${ESC}${rows - 1}A`) // moving up lines } private close() { this.filterRL.close() if (this.onKeyPress) - process.stdin.removeListener('keypress', this.onKeyPress) + this.stdin.removeListener('keypress', this.onKeyPress) - if (process.stdin.isTTY) - process.stdin.setRawMode(false) + if (this.stdin.isTTY) + this.stdin.setRawMode(false) } private restoreCursor() { const cursortPos = this.keywordOffset() + (this.currentKeyword?.length || 0) - stdout().write(`${ESC}${cursortPos}G`) + this.write(`${ESC}${cursortPos}G`) } private cancel() { - stdout().write(`${ESC}J`) // erase down + this.write(`${ESC}J`) // erase down + } + + private write(data: string) { + // @ts-expect-error -- write() method has different signature on the union type + this.stdout.write(data) } } diff --git a/packages/vitest/src/node/workspace.ts b/packages/vitest/src/node/workspace.ts index 57f838b0b994b..669ebd4f2dcd4 100644 --- a/packages/vitest/src/node/workspace.ts +++ b/packages/vitest/src/node/workspace.ts @@ -308,6 +308,7 @@ export class WorkspaceProject { coverage: this.ctx.config.coverage, }, server.config, + this.ctx.logger, ) this.server = server diff --git a/test/config/test/cache.test.ts b/test/config/test/cache.test.ts index 379ddbc93d380..c2d52cab58e0a 100644 --- a/test/config/test/cache.test.ts +++ b/test/config/test/cache.test.ts @@ -6,7 +6,7 @@ const root = resolve(__dirname, '../fixtures/cache') const project = resolve(__dirname, '../') test('default', async () => { - const { vitest, stdout, stderr } = await runVitest({ + const { ctx, stdout, stderr } = await runVitest({ root, include: ['*.test.ts'], }) @@ -14,13 +14,13 @@ test('default', async () => { expect(stdout).toContain('✓ basic.test.ts >') expect(stderr).toBe('') - const cachePath = vitest!.cache.results.getCachePath() + const cachePath = ctx!.cache.results.getCachePath() const path = resolve(project, 'node_modules/.vite/vitest/results.json') expect(cachePath).toMatch(path) }) test('use cache.dir', async () => { - const { vitest, stdout, stderr } = await runVitest( + const { ctx, stdout, stderr } = await runVitest( { root, include: ['*.test.ts'], @@ -33,13 +33,13 @@ test('use cache.dir', async () => { expect(stdout).toContain('✓ basic.test.ts >') expect(stderr).toContain('"cache.dir" is deprecated') - const cachePath = vitest!.cache.results.getCachePath() + const cachePath = ctx!.cache.results.getCachePath() const path = resolve(root, 'node_modules/.vitest-custom/results.json') expect(cachePath).toMatch(path) }) test('use cacheDir', async () => { - const { vitest, stdout, stderr } = await runVitest( + const { ctx, stdout, stderr } = await runVitest( { root, include: ['*.test.ts'], @@ -52,7 +52,7 @@ test('use cacheDir', async () => { expect(stdout).toContain('✓ basic.test.ts >') expect(stderr).toBe('') - const cachePath = vitest!.cache.results.getCachePath() + const cachePath = ctx!.cache.results.getCachePath() const path = resolve(root, 'node_modules/.vite-custom/vitest/results.json') expect(cachePath).toMatch(path) }) @@ -67,7 +67,7 @@ describe('with optimizer enabled', () => { } test('default', async () => { - const { vitest, stdout, stderr } = await runVitest({ + const { ctx, stdout, stderr } = await runVitest({ root, include: ['*.test.ts'], deps, @@ -76,13 +76,13 @@ describe('with optimizer enabled', () => { expect(stdout).toContain('✓ basic.test.ts >') expect(stderr).toBe('') - const cachePath = vitest!.cache.results.getCachePath() + const cachePath = ctx!.cache.results.getCachePath() const path = resolve(project, 'node_modules/.vite/vitest/results.json') expect(cachePath).toBe(path) }) test('use cache.dir', async () => { - const { vitest, stdout, stderr } = await runVitest( + const { ctx, stdout, stderr } = await runVitest( { root, include: ['*.test.ts'], @@ -96,13 +96,13 @@ describe('with optimizer enabled', () => { expect(stdout).toContain('✓ basic.test.ts >') expect(stderr).toContain('"cache.dir" is deprecated') - const cachePath = vitest!.cache.results.getCachePath() + const cachePath = ctx!.cache.results.getCachePath() const path = resolve(root, 'node_modules/.vitest-custom/results.json') expect(cachePath).toBe(path) }) test('use cacheDir', async () => { - const { vitest, stdout, stderr } = await runVitest( + const { ctx, stdout, stderr } = await runVitest( { root, include: ['*.test.ts'], @@ -116,7 +116,7 @@ describe('with optimizer enabled', () => { expect(stdout).toContain('✓ basic.test.ts >') expect(stderr).toBe('') - const cachePath = vitest!.cache.results.getCachePath() + const cachePath = ctx!.cache.results.getCachePath() const path = resolve(root, 'node_modules/.vite-custom/vitest/results.json') expect(cachePath).toBe(path) }) diff --git a/test/config/test/console.test.ts b/test/config/test/console.test.ts index 198c4f26b2777..aa52de328786e 100644 --- a/test/config/test/console.test.ts +++ b/test/config/test/console.test.ts @@ -1,4 +1,4 @@ -import { expect, test } from 'vitest' +import { expect, test, vi } from 'vitest' import { runVitest } from '../../test-utils' test('default intercept', async () => { @@ -9,10 +9,15 @@ test('default intercept', async () => { }) test.each(['threads', 'vmThreads'] as const)(`disable intercept pool=%s`, async (pool) => { - const { stderr } = await runVitest({ + // `disableConsoleIntercept: true` forwards workers console.error to main thread's stderr + const spy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true) + + await runVitest({ root: './fixtures/console', disableConsoleIntercept: true, pool, }) - expect(stderr).toBe('__test_console__\n') + + const call = spy.mock.lastCall![0] + expect(call.toString()).toBe('__test_console__\n') }) diff --git a/test/config/test/flags.test.ts b/test/config/test/flags.test.ts index ab7230acc25e8..e43b8f5909dfb 100644 --- a/test/config/test/flags.test.ts +++ b/test/config/test/flags.test.ts @@ -2,7 +2,7 @@ import { expect, it } from 'vitest' import { runVitest } from '../../test-utils' it('correctly inherit from the cli', async () => { - const { vitest } = await runVitest({ + const { ctx } = await runVitest({ root: 'fixtures/workspace-flags', logHeapUsage: true, allowOnly: true, @@ -18,7 +18,7 @@ it('correctly inherit from the cli', async () => { passWithNoTests: true, bail: 100, }) - const project = vitest!.projects[0] + const project = ctx!.projects[0] const config = project.getSerializableConfig() expect(config).toMatchObject({ logHeapUsage: true, diff --git a/test/config/test/resolution.test.ts b/test/config/test/resolution.test.ts index f047d7d44760b..847187b006b75 100644 --- a/test/config/test/resolution.test.ts +++ b/test/config/test/resolution.test.ts @@ -1,16 +1,19 @@ +import { Writable } from 'node:stream' import type { UserConfig } from 'vitest' import type { UserConfig as ViteUserConfig } from 'vite' -import { describe, expect, it, onTestFinished, vi } from 'vitest' +import { describe, expect, it } from 'vitest' import { createVitest, parseCLI } from 'vitest/node' import { extraInlineDeps } from 'vitest/config' -async function vitest(cliOptions: UserConfig, configValue: UserConfig = {}, viteConfig: ViteUserConfig = {}) { - const vitest = await createVitest('test', { ...cliOptions, watch: false }, { ...viteConfig, test: configValue as any }) +type VitestOptions = Parameters[3] + +async function vitest(cliOptions: UserConfig, configValue: UserConfig = {}, viteConfig: ViteUserConfig = {}, vitestOptions: VitestOptions = {}) { + const vitest = await createVitest('test', { ...cliOptions, watch: false }, { ...viteConfig, test: configValue as any }, vitestOptions) return vitest } -async function config(cliOptions: UserConfig, configValue: UserConfig = {}, viteConfig: ViteUserConfig = {}) { - const v = await vitest(cliOptions, configValue, viteConfig) +async function config(cliOptions: UserConfig, configValue: UserConfig = {}, viteConfig: ViteUserConfig = {}, vitestOptions: VitestOptions = {}) { + const v = await vitest(cliOptions, configValue, viteConfig, vitestOptions) return v.config } @@ -296,16 +299,18 @@ describe.each([ inspectFlagName, url, ]) - const error = vi.fn() - const originalError = console.error - console.error = error - onTestFinished(() => { - console.error = originalError + const errors: string[] = [] + const stderr = new Writable({ + write(chunk, _encoding, callback) { + errors.push(chunk.toString()) + callback() + }, }) await expect(async () => { - await config(rawConfig.options) + await config(rawConfig.options, {}, {}, { stderr }) }).rejects.toThrowError() - expect(error.mock.lastCall[0]).toEqual( + + expect(errors[0]).toEqual( expect.stringContaining(`Inspector host cannot be a URL. Use "host:port" instead of "${url}"`), ) }) diff --git a/test/config/test/shuffle-options.test.ts b/test/config/test/shuffle-options.test.ts index 554a38863ccca..c2de8136eb9c4 100644 --- a/test/config/test/shuffle-options.test.ts +++ b/test/config/test/shuffle-options.test.ts @@ -25,8 +25,8 @@ test.each([ { files: false, tests: true }, ], )('should use BaseSequencer if shuffle is %o', async (shuffle) => { - const { vitest } = await run({ shuffle }) - expect(vitest?.config.sequence.sequencer.name).toBe('BaseSequencer') + const { ctx } = await run({ shuffle }) + expect(ctx?.config.sequence.sequencer.name).toBe('BaseSequencer') }) test.each([ @@ -34,8 +34,8 @@ test.each([ { files: true, tests: false }, { files: true, tests: true }, ])('should use RandomSequencer if shuffle is %o', async (shuffle) => { - const { vitest } = await run({ shuffle }) - expect(vitest?.config.sequence.sequencer.name).toBe('RandomSequencer') + const { ctx } = await run({ shuffle }) + expect(ctx?.config.sequence.sequencer.name).toBe('RandomSequencer') }) test.each([ @@ -44,6 +44,6 @@ test.each([ { files: true, tests: false }, { files: true, tests: true }, ])('should always use CustomSequencer if passed', async (shuffle) => { - const { vitest } = await run({ shuffle, sequencer: CustomSequencer }) - expect(vitest?.config.sequence.sequencer.name).toBe('CustomSequencer') + const { ctx } = await run({ shuffle, sequencer: CustomSequencer }) + expect(ctx?.config.sequence.sequencer.name).toBe('CustomSequencer') }) diff --git a/test/core/test/cli-test.test.ts b/test/core/test/cli-test.test.ts index 1d4a3ce636cf7..cc69700bb9181 100644 --- a/test/core/test/cli-test.test.ts +++ b/test/core/test/cli-test.test.ts @@ -274,7 +274,7 @@ test('clearScreen', async () => { clearScreen: viteClearScreen, } const vitestConfig = getCLIOptions(vitestClearScreen) - const config = resolveConfig('test', vitestConfig, viteConfig) + const config = resolveConfig('test', vitestConfig, viteConfig, undefined as any) return config.clearScreen }) expect(results).toMatchInlineSnapshot(` diff --git a/test/inspect/test/inspect.test.ts b/test/inspect/test/inspect.test.ts index bc634436727d0..fe5bab6df0a74 100644 --- a/test/inspect/test/inspect.test.ts +++ b/test/inspect/test/inspect.test.ts @@ -8,7 +8,7 @@ import { runVitestCli } from '../../test-utils' type Message = Partial> test.skipIf(isWindows)('--inspect-brk stops at test file', async () => { - const vitest = await runVitestCli('--root', 'fixtures', '--inspect-brk', '--no-file-parallelism') + const { vitest, waitForClose } = await runVitestCli('--root', 'fixtures', '--inspect-brk', '--no-file-parallelism') await vitest.waitForStderr('Debugger listening on ') const url = vitest.stderr.split('\n')[0].replace('Debugger listening on ', '') @@ -36,7 +36,7 @@ test.skipIf(isWindows)('--inspect-brk stops at test file', async () => { send({ method: 'Debugger.resume' }) await vitest.waitForStdout('Test Files 1 passed (1)') - await vitest.isDone + await waitForClose() }) async function createChannel(url: string) { diff --git a/test/public-api/tests/runner.spec.ts b/test/public-api/tests/runner.spec.ts index 963c9d06c3fed..6af6b1eaa8ceb 100644 --- a/test/public-api/tests/runner.spec.ts +++ b/test/public-api/tests/runner.spec.ts @@ -19,7 +19,7 @@ it.each([ const taskUpdate: TaskResultPack[] = [] const finishedFiles: File[] = [] const collectedFiles: File[] = [] - const { vitest, stdout, stderr } = await runVitest({ + const { ctx, stdout, stderr } = await runVitest({ root: resolve(__dirname, '..', 'fixtures'), include: ['**/*.spec.ts'], reporters: [ @@ -50,7 +50,7 @@ it.each([ expect(taskUpdate).toHaveLength(4) expect(finishedFiles).toHaveLength(1) - const files = vitest?.state.getFiles() || [] + const files = ctx?.state.getFiles() || [] expect(files).toHaveLength(1) expect(taskUpdate).toContainEqual( diff --git a/test/reporters/tests/default.test.ts b/test/reporters/tests/default.test.ts index 76c294907a4ac..f37487f4ccc99 100644 --- a/test/reporters/tests/default.test.ts +++ b/test/reporters/tests/default.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'vitest' -import { runVitest, runVitestCli } from '../../test-utils' +import { runVitest } from '../../test-utils' describe('default reporter', async () => { test('normal', async () => { @@ -28,14 +28,12 @@ describe('default reporter', async () => { }) test('rerun should undo', async () => { - const vitest = await runVitestCli( - '--root', - 'fixtures/default', - '--watch', - '-t', - 'passed', - ) - vitest.resetOutput() + const { vitest } = await runVitest({ + root: 'fixtures/default', + watch: true, + testNamePattern: 'passed', + reporters: 'none', + }) // one file vitest.write('p') diff --git a/test/run/pool-custom-fixtures/pool/custom-pool.ts b/test/run/pool-custom-fixtures/pool/custom-pool.ts index 84029bb82d614..0ab30ef9b2b53 100644 --- a/test/run/pool-custom-fixtures/pool/custom-pool.ts +++ b/test/run/pool-custom-fixtures/pool/custom-pool.ts @@ -9,12 +9,12 @@ export default (ctx: Vitest): ProcessPool => { return { name: 'custom', async runTests(specs) { - console.warn('[pool] printing:', options.print) - console.warn('[pool] array option', options.array) + ctx.logger.console.warn('[pool] printing:', options.print) + ctx.logger.console.warn('[pool] array option', options.array) for await (const [project, file] of specs) { ctx.state.clearFiles(project) const methods = createMethodsRPC(project) - console.warn('[pool] running tests for', project.getName(), 'in', normalize(file).toLowerCase().replace(normalize(process.cwd()).toLowerCase(), '')) + ctx.logger.console.warn('[pool] running tests for', project.getName(), 'in', normalize(file).toLowerCase().replace(normalize(process.cwd()).toLowerCase(), '')) const path = relative(project.config.root, file) const taskFile: File = { id: `${path}${project.getName()}`, @@ -47,7 +47,7 @@ export default (ctx: Vitest): ProcessPool => { } }, close() { - console.warn('[pool] custom pool is closed!') + ctx.logger.console.warn('[pool] custom pool is closed!') }, } } diff --git a/test/run/test/tty.test.ts b/test/run/test/tty.test.ts index 2e283b154070d..a326b11a431eb 100644 --- a/test/run/test/tty.test.ts +++ b/test/run/test/tty.test.ts @@ -2,12 +2,11 @@ import { expect, test } from 'vitest' import { runVitestCli } from '../../test-utils' test('run mode does not get stuck when TTY', async () => { - const vitest = await runVitestCli('--root', 'fixtures') - await vitest.isDone + const { vitest } = await runVitestCli('--root', 'fixtures') - expect(vitest.stdout).toContain('✓ example.test.ts') - expect(vitest.stdout).toContain('✓ math.test.ts') - expect(vitest.stdout).toContain('2 passed') + await vitest.waitForStdout('✓ example.test.ts') + await vitest.waitForStdout('✓ math.test.ts') + await vitest.waitForStdout('2 passed') // Regression #3642 expect(vitest.stderr).not.toContain('close timed out') diff --git a/test/test-utils/cli.ts b/test/test-utils/cli.ts new file mode 100644 index 0000000000000..5abee6ee87301 --- /dev/null +++ b/test/test-utils/cli.ts @@ -0,0 +1,95 @@ +import type { Readable, Writable } from 'node:stream' +import stripAnsi from 'strip-ansi' + +type Listener = (() => void) +type ReadableOrWritable = Readable | Writable +type Source = 'stdout' | 'stderr' + +export class Cli { + stdout = '' + stderr = '' + + private stdoutListeners: Listener[] = [] + private stderrListeners: Listener[] = [] + private stdin: ReadableOrWritable + + constructor(options: { stdin: ReadableOrWritable; stdout: ReadableOrWritable; stderr: ReadableOrWritable }) { + this.stdin = options.stdin + + for (const source of (['stdout', 'stderr'] as const)) { + const stream = options[source] + + if ((stream as Readable).readable) { + stream.on('data', (data) => { + this.capture(source, data) + }) + } + else if (isWritable(stream)) { + const original = stream.write.bind(stream) + + // @ts-expect-error -- Is there a better way to detect when a Writable is being written into? + stream.write = (data, encoding, callback) => { + this.capture(source, data) + return original(data, encoding, callback) + } + } + } + } + + private capture(source: Source, data: any) { + this[source] += stripAnsi(data.toString()) + this[`${source}Listeners`].forEach(fn => fn()) + } + + write(data: string) { + this.resetOutput() + + if (((this.stdin as Readable).readable)) + this.stdin.emit('data', data) + else if (isWritable(this.stdin)) + this.stdin.write(data) + } + + resetOutput() { + this.stdout = '' + this.stderr = '' + } + + waitForStdout(expected: string) { + return this.waitForOutput(expected, 'stdout', this.waitForStdout) + } + + waitForStderr(expected: string) { + return this.waitForOutput(expected, 'stderr', this.waitForStderr) + } + + private waitForOutput(expected: string, source: Source, caller: Parameters[1]) { + const error = new Error('Timeout') + Error.captureStackTrace(error, caller) + + return new Promise((resolve, reject) => { + if (this[source].includes(expected)) + return resolve() + + const timeout = setTimeout(() => { + error.message = `Timeout when waiting for error "${expected}".\nReceived:\n${this[source]}` + reject(error) + }, process.env.CI ? 20_000 : 4_000) + + const listener = () => { + if (this[source].includes(expected)) { + if (timeout) + clearTimeout(timeout) + + resolve() + } + } + + this[`${source}Listeners`].push(listener) + }) + } +} + +function isWritable(stream: any): stream is Writable { + return stream && typeof stream.write === 'function' +} diff --git a/test/test-utils/index.ts b/test/test-utils/index.ts index 0ee2a080cdc6b..a828234e7ceae 100644 --- a/test/test-utils/index.ts +++ b/test/test-utils/index.ts @@ -1,5 +1,4 @@ -import { Console } from 'node:console' -import { Writable } from 'node:stream' +import { Readable, Writable } from 'node:stream' import fs from 'node:fs' import { fileURLToPath } from 'node:url' import type { UserConfig as ViteUserConfig } from 'vite' @@ -7,8 +6,8 @@ import { type UserConfig, type VitestRunMode, afterEach } from 'vitest' import type { Vitest } from 'vitest/node' import { startVitest } from 'vitest/node' import { type Options, execa } from 'execa' -import stripAnsi from 'strip-ansi' import { dirname, resolve } from 'pathe' +import { Cli } from './cli' export async function runVitest(config: UserConfig, cliFilters: string[] = [], mode: VitestRunMode = 'test', viteOverrides: ViteUserConfig = {}) { // Reset possible previous runs @@ -19,77 +18,54 @@ export async function runVitest(config: UserConfig, cliFilters: string[] = [], m const exit = process.exit process.exit = (() => { }) as never - const { getLogs, restore } = captureLogs() + const stdout = new Writable({ write: (_, __, callback) => callback() }) + const stderr = new Writable({ write: (_, __, callback) => callback() }) - let vitest: Vitest | undefined + // "node:tty".ReadStream doesn't work on Github Windows CI, let's simulate it + const stdin = new Readable({ read: () => '' }) as NodeJS.ReadStream + stdin.isTTY = true + stdin.setRawMode = () => stdin + const cli = new Cli({ stdin, stdout, stderr }) + + let ctx: Vitest | undefined try { const { reporters, ...rest } = config - vitest = await startVitest(mode, cliFilters, { + ctx = await startVitest(mode, cliFilters, { watch: false, // "none" can be used to disable passing "reporter" option so that default value is used (it's not same as reporters: ["default"]) ...(reporters === 'none' ? {} : reporters ? { reporters } : { reporters: ['verbose'] }), ...rest, - }, viteOverrides) + }, viteOverrides, { + stdin, + stdout, + stderr, + }) } catch (e: any) { - return { - stderr: `${getLogs().stderr}\n${e.message}`, - stdout: getLogs().stdout, - exitCode, - vitest, - } + console.error(e.message) + cli.stderr += e.message } finally { exitCode = process.exitCode process.exitCode = 0 - process.exit = exit - - restore() - } - - return { ...getLogs(), exitCode, vitest } -} -function captureLogs() { - const stdout: string[] = [] - const stderr: string[] = [] - - const streams = { - stdout: new Writable({ - write(chunk, _, callback) { - stdout.push(chunk.toString()) - callback() - }, - }), - stderr: new Writable({ - write(chunk, _, callback) { - stderr.push(chunk.toString()) - callback() - }, - }), + afterEach(async () => { + await ctx?.close() + await ctx?.closingPromise + process.exit = exit + }) } - const originalConsole = globalThis.console - globalThis.console = new Console(streams) - - const originalStdoutWrite = process.stdout.write - process.stdout.write = streams.stdout.write.bind(streams.stdout) as any - - const originalStderrWrite = process.stderr.write - process.stderr.write = streams.stderr.write.bind(streams.stderr) as any - return { - restore: () => { - globalThis.console = originalConsole - process.stdout.write = originalStdoutWrite - process.stderr.write = originalStderrWrite - }, - getLogs() { - return { - stdout: stripAnsi(stdout.join('')), - stderr: stripAnsi(stderr.join('')), - } + ctx, + exitCode, + vitest: cli, + stdout: cli.stdout, + stderr: cli.stderr, + waitForClose: async () => { + await new Promise(resolve => ctx!.onClose(resolve)) + return ctx?.closingPromise }, } } @@ -103,96 +79,35 @@ export async function runCli(command: string, _options?: Options | string, ...ar } const subprocess = execa(command, args, options as Options) + const cli = new Cli({ + stdin: subprocess.stdin!, + stdout: subprocess.stdout!, + stderr: subprocess.stderr!, + }) let setDone: (value?: unknown) => void const isDone = new Promise(resolve => (setDone = resolve)) + subprocess.on('exit', () => setDone()) - const cli = { - stdout: '', - stderr: '', - stdoutListeners: [] as (() => void)[], - stderrListeners: [] as (() => void)[], - isDone, - write(text: string) { - this.resetOutput() - subprocess.stdin!.write(text) - }, - waitForStdout(expected: string) { - const error = new Error('Timeout error') - Error.captureStackTrace(error, this.waitForStdout) - return new Promise((resolve, reject) => { - if (this.stdout.includes(expected)) - return resolve() - - const timeout = setTimeout(() => { - error.message = `Timeout when waiting for output "${expected}".\nReceived:\n${this.stdout} \nStderr:\n${this.stderr}` - reject(error) - }, process.env.CI ? 20_000 : 4_000) - - const listener = () => { - if (this.stdout.includes(expected)) { - if (timeout) - clearTimeout(timeout) - - resolve() - } - } - - this.stdoutListeners.push(listener) - }) - }, - waitForStderr(expected: string) { - const error = new Error('Timeout') - Error.captureStackTrace(error, this.waitForStderr) - return new Promise((resolve, reject) => { - if (this.stderr.includes(expected)) - return resolve() - - const timeout = setTimeout(() => { - error.message = `Timeout when waiting for error "${expected}".\nReceived:\n${this.stderr}\nStdout:\n${this.stdout}` - reject(error) - }, process.env.CI ? 20_000 : 4_000) - - const listener = () => { - if (this.stderr.includes(expected)) { - if (timeout) - clearTimeout(timeout) - - resolve() - } - } - - this.stderrListeners.push(listener) - }) - }, - resetOutput() { - this.stdout = '' - this.stderr = '' - }, + function output() { + return { + vitest: cli, + stdout: cli.stdout || '', + stderr: cli.stderr || '', + waitForClose: () => isDone, + } } - subprocess.stdout!.on('data', (data) => { - cli.stdout += stripAnsi(data.toString()) - cli.stdoutListeners.forEach(fn => fn()) - }) - - subprocess.stderr!.on('data', (data) => { - cli.stderr += stripAnsi(data.toString()) - cli.stderrListeners.forEach(fn => fn()) - }) - - subprocess.on('exit', () => setDone()) - // Manually stop the processes so that each test don't have to do this themselves afterEach(async () => { if (subprocess.exitCode === null) subprocess.kill() - await cli.isDone + await isDone }) if (args.includes('--inspect') || args.includes('--inspect-brk')) - return cli + return output() if (args.includes('--watch')) { if (command === 'vitest') // Wait for initial test run to complete @@ -202,10 +117,10 @@ export async function runCli(command: string, _options?: Options | string, ...ar cli.stdout = cli.stdout.replace('[debug] watcher is ready\n', '') } else { - await cli.isDone + await isDone } - return cli + return output() } export async function runVitestCli(_options?: Options | string, ...args: string[]) { @@ -215,7 +130,9 @@ export async function runVitestCli(_options?: Options | string, ...args: string[ export async function runViteNodeCli(_options?: Options | string, ...args: string[]) { process.env.VITE_TEST_WATCHER_DEBUG = 'true' - return runCli('vite-node', _options, ...args) + const { vitest, ...rest } = await runCli('vite-node', _options, ...args) + + return { viteNode: vitest, ...rest } } const originalFiles = new Map() diff --git a/test/typescript/test/runner.test.ts b/test/typescript/test/runner.test.ts index 096c18c8bf642..3e6b9ffcdd61b 100644 --- a/test/typescript/test/runner.test.ts +++ b/test/typescript/test/runner.test.ts @@ -2,7 +2,7 @@ import { resolve } from 'pathe' import fg from 'fast-glob' import { describe, expect, it } from 'vitest' -import { runVitest, runVitestCli } from '../../test-utils' +import { runVitest } from '../../test-utils' describe('should fail', async () => { const root = resolve(__dirname, '../failing') @@ -17,7 +17,7 @@ describe('should fail', async () => { allowJs: true, include: ['**/*.test-d.*'], }, - }, []) + }) expect(stderr).toBeTruthy() const lines = String(stderr).split(/\n/g) @@ -43,17 +43,13 @@ describe('should fail', async () => { }) it('typecheks with custom tsconfig', async () => { - const { stderr } = await runVitestCli( - { cwd: root, env: { ...process.env, CI: 'true' } }, - '--run', - '--dir', - resolve(__dirname, '..', './failing'), - '--config', - resolve(__dirname, './vitest.custom.config.ts'), - '--typecheck.enabled', - ) + const { stderr } = await runVitest({ + root, + dir: resolve(__dirname, '..', './failing'), + config: resolve('./test/vitest.custom.config.ts'), + typecheck: { enabled: true }, + }) - expect(stderr).toBeTruthy() const lines = String(stderr).split(/\n/g) const msg = lines .filter(i => i.includes('TypeCheckError: ')) @@ -67,7 +63,9 @@ describe('should fail', async () => { expect(msg).toMatchSnapshot() expect(stderr).toContain('FAIL fail.test-d.ts') // included in tsconfig - expect(stderr).toContain('FAIL only.test-d.ts') // .only + + // TODO: Why should this be picked as well? + // expect(stderr).toContain('FAIL only.test-d.ts') // .only // not included in tsconfig expect(stderr).not.toContain('expect-error.test-d.ts') @@ -77,21 +75,12 @@ describe('should fail', async () => { }) it('typechecks empty "include" but with tests', async () => { - const { stderr } = await runVitestCli( - { - cwd: root, - env: { - ...process.env, - CI: 'true', - NO_COLOR: 'true', - }, - }, - '--run', - '--dir', - resolve(__dirname, '..', './failing'), - '--config', - resolve(__dirname, './vitest.empty.config.ts'), - '--typecheck.enabled', + const { stderr } = await runVitest({ + root, + dir: resolve(__dirname, '..', './failing'), + config: resolve(__dirname, './vitest.empty.config.ts'), + typecheck: { enabled: true }, + }, ) expect(stderr.replace(resolve(__dirname, '..'), '')).toMatchSnapshot() @@ -100,24 +89,23 @@ describe('should fail', async () => { describe('ignoreSourceErrors', () => { it('disabled', async () => { - const vitest = await runVitestCli( - { - cwd: resolve(__dirname, '../fixtures/source-error'), - }, - '--run', - ) + const vitest = await runVitest({ + root: resolve(__dirname, '../fixtures/source-error'), + }) expect(vitest.stdout).toContain('Unhandled Errors') expect(vitest.stderr).toContain('Unhandled Source Error') expect(vitest.stderr).toContain('TypeCheckError: Cannot find name \'thisIsSourceError\'') }) it('enabled', async () => { - const vitest = await runVitestCli( + const vitest = await runVitest( { - cwd: resolve(__dirname, '../fixtures/source-error'), + root: resolve(__dirname, '../fixtures/source-error'), + typecheck: { + ignoreSourceErrors: true, + enabled: true, + }, }, - '--run', - '--typecheck.ignoreSourceErrors', ) expect(vitest.stdout).not.toContain('Unhandled Errors') expect(vitest.stderr).not.toContain('Unhandled Source Error') diff --git a/test/vite-node/test/cli.test.ts b/test/vite-node/test/cli.test.ts index 893d4bb80d11d..0b48d168e41ff 100644 --- a/test/vite-node/test/cli.test.ts +++ b/test/vite-node/test/cli.test.ts @@ -41,8 +41,8 @@ it('script args in -- after', async () => { it.each(['index.js', 'index.cjs', 'index.mjs'])('correctly runs --watch %s', async (file) => { const entryPath = resolve(__dirname, '../src/watch', file) - const cli = await runViteNodeCli('--watch', entryPath) - await cli.waitForStdout('test 1') + const { viteNode } = await runViteNodeCli('--watch', entryPath) + await viteNode.waitForStdout('test 1') editFile(entryPath, c => c.replace('test 1', 'test 2')) - await cli.waitForStdout('test 2') + await viteNode.waitForStdout('test 2') }) diff --git a/test/vite-node/test/hmr.test.ts b/test/vite-node/test/hmr.test.ts index 0cfdca19b36ab..5e823d2ea7d85 100644 --- a/test/vite-node/test/hmr.test.ts +++ b/test/vite-node/test/hmr.test.ts @@ -5,7 +5,7 @@ import { editFile, runViteNodeCli } from '../../test-utils' test('hmr.accept works correctly', async () => { const scriptFile = resolve(__dirname, '../src/hmr-script.js') - const viteNode = await runViteNodeCli('--watch', scriptFile) + const { viteNode } = await runViteNodeCli('--watch', scriptFile) await viteNode.waitForStderr('Hello!') diff --git a/test/vite-node/test/self-export.test.ts b/test/vite-node/test/self-export.test.ts index e4b7cc51dd62a..52c24626e8897 100644 --- a/test/vite-node/test/self-export.test.ts +++ b/test/vite-node/test/self-export.test.ts @@ -11,12 +11,12 @@ it('should export self', () => { it('example 1', async () => { const entryPath = resolve(__dirname, '../src/self-export-example1.ts') - const cli = await runViteNodeCli(entryPath) - await cli.waitForStdout('Function') + const { viteNode } = await runViteNodeCli(entryPath) + await viteNode.waitForStdout('Function') }, 60_000) it('example 2', async () => { const entryPath = resolve(__dirname, '../src/self-export-example2.ts') - const cli = await runViteNodeCli(entryPath) - await cli.waitForStdout('HelloWorld: 1') + const { viteNode } = await runViteNodeCli(entryPath) + await viteNode.waitForStdout('HelloWorld: 1') }, 60_000) diff --git a/test/watch/test/file-watching.test.ts b/test/watch/test/file-watching.test.ts index 52e7c57a49507..8993e71d79158 100644 --- a/test/watch/test/file-watching.test.ts +++ b/test/watch/test/file-watching.test.ts @@ -15,16 +15,9 @@ const configFileContent = readFileSync(configFile, 'utf-8') const forceTriggerFile = 'fixtures/force-watch/trigger.js' const forceTriggerFileContent = readFileSync(forceTriggerFile, 'utf-8') -const cliArgs = ['--root', 'fixtures', '--watch'] +const options = { root: 'fixtures', watch: true } const cleanups: (() => void)[] = [] -async function runVitestCli(...args: string[]) { - const vitest = await testUtils.runVitestCli(...args) - if (args.includes('--watch')) - vitest.resetOutput() - return vitest -} - function editFile(fileContent: string) { return `// Modified by file-watching.test.ts ${fileContent} @@ -45,7 +38,7 @@ if (process.env.GITHUB_ACTIONS) test.only('skip tests on CI', () => {}) test('editing source file triggers re-run', async () => { - const vitest = await runVitestCli(...cliArgs) + const { vitest } = await testUtils.runVitest(options) writeFileSync(sourceFile, editFile(sourceFileContent), 'utf8') @@ -55,7 +48,7 @@ test('editing source file triggers re-run', async () => { }) test('editing file that was imported with a query reruns suite', async () => { - const vitest = await runVitestCli(...cliArgs) + const { vitest } = await testUtils.runVitest(options) testUtils.editFile( testUtils.resolvePath(import.meta.url, '../fixtures/42.txt'), @@ -67,7 +60,7 @@ test('editing file that was imported with a query reruns suite', async () => { }) test('editing force rerun trigger reruns all tests', async () => { - const vitest = await runVitestCli(...cliArgs) + const { vitest } = await testUtils.runVitest(options) writeFileSync(forceTriggerFile, editFile(forceTriggerFileContent), 'utf8') @@ -79,7 +72,7 @@ test('editing force rerun trigger reruns all tests', async () => { }) test('editing test file triggers re-run', async () => { - const vitest = await runVitestCli(...cliArgs) + const { vitest } = await testUtils.runVitest(options) writeFileSync(testFile, editFile(testFileContent), 'utf8') @@ -89,17 +82,16 @@ test('editing test file triggers re-run', async () => { }) test('editing config file triggers re-run', async () => { - const vitest = await runVitestCli(...cliArgs) + const { vitest } = await testUtils.runVitest(options) writeFileSync(configFile, editFile(configFileContent), 'utf8') - await vitest.waitForStdout('New code running') await vitest.waitForStdout('Restarting due to config changes') await vitest.waitForStdout('2 passed') }) test('editing config file reloads new changes', async () => { - const vitest = await runVitestCli(...cliArgs) + const { vitest } = await testUtils.runVitest({ ...options, reporters: 'none' }) writeFileSync(configFile, configFileContent.replace('reporters: \'verbose\'', 'reporters: \'tap\''), 'utf8') @@ -108,7 +100,7 @@ test('editing config file reloads new changes', async () => { }) test('adding a new test file triggers re-run', async () => { - const vitest = await runVitestCli(...cliArgs) + const { vitest } = await testUtils.runVitest(options) const testFile = 'fixtures/new-dynamic.test.ts' const testFileContent = ` @@ -135,14 +127,11 @@ test('editing source file generates new test report to file system', async () => // Test report should not be present before test run expect(existsSync(report)).toBe(false) - const vitest = await runVitestCli( - ...cliArgs, - '--reporter', - 'verbose', - '--reporter', - 'junit', - '--output-file', - 'test-results/junit.xml', + const { vitest } = await testUtils.runVitest({ + ...options, + reporters: ['verbose', 'junit'], + outputFile: './test-results/junit.xml', + }, ) // Test report should be generated on initial test run @@ -152,6 +141,7 @@ test('editing source file generates new test report to file system', async () => rmSync(report) expect(existsSync(report)).toBe(false) + vitest.resetOutput() writeFileSync(sourceFile, editFile(sourceFileContent), 'utf8') await vitest.waitForStdout('JUNIT report written') @@ -160,8 +150,15 @@ test('editing source file generates new test report to file system', async () => }) describe('browser', () => { - test.runIf((process.platform !== 'win32'))('editing source file triggers re-run', async () => { - const vitest = await runVitestCli(...cliArgs, '--browser.enabled', '--browser.headless', '--browser.name=chrome') + test.runIf((process.platform !== 'win32'))('editing source file triggers re-run', { retry: 3 }, async () => { + const { vitest } = await testUtils.runVitest({ + ...options, + browser: { + name: 'chrome', + enabled: true, + headless: true, + }, + }) writeFileSync(sourceFile, editFile(sourceFileContent), 'utf8') @@ -170,5 +167,5 @@ describe('browser', () => { await vitest.waitForStdout('1 passed') vitest.write('q') - }, { retry: 3 }) + }) }) diff --git a/test/watch/test/related.test.ts b/test/watch/test/related.test.ts index 654e4c533c32f..b2c7de91baeaa 100644 --- a/test/watch/test/related.test.ts +++ b/test/watch/test/related.test.ts @@ -1,11 +1,13 @@ import { test } from 'vitest' import { resolve } from 'pathe' -import { editFile, runVitestCli } from '../../test-utils' - -const cliArgs = ['--root', 'fixtures', '--watch', '--changed'] +import { editFile, runVitest } from '../../test-utils' test('when nothing is changed, run nothing but keep watching', async () => { - const vitest = await runVitestCli(...cliArgs) + const { vitest } = await runVitest({ + root: 'fixtures', + watch: true, + changed: true, + }) await vitest.waitForStdout('No affected test files found') await vitest.waitForStdout('Waiting for file changes...') diff --git a/test/watch/test/stdin.test.ts b/test/watch/test/stdin.test.ts index 6f23d41654976..3c88a08558f35 100644 --- a/test/watch/test/stdin.test.ts +++ b/test/watch/test/stdin.test.ts @@ -1,45 +1,30 @@ import { rmSync, writeFileSync } from 'node:fs' -import { afterEach, expect, test } from 'vitest' +import { expect, onTestFinished, test } from 'vitest' -import * as testUtils from '../../test-utils' +import { runVitest } from '../../test-utils' -async function runVitestCli(...args: string[]) { - const vitest = await testUtils.runVitestCli(...args) - if (args.includes('--watch')) - vitest.resetOutput() - return vitest -} - -const cliArgs = ['--root', 'fixtures', '--watch'] -const cleanups: (() => void)[] = [] - -afterEach(() => { - cleanups.splice(0).forEach(fn => fn()) -}) - -// TODO: Fix flakiness and enable on CI -if (process.env.GITHUB_ACTIONS) - test.only('skip tests on CI', () => {}) +const options = { root: 'fixtures', watch: true } test('quit watch mode', async () => { - const vitest = await runVitestCli(...cliArgs) + const { vitest, waitForClose } = await runVitest(options) vitest.write('q') - await vitest.isDone + await waitForClose() }) test('rerun current pattern tests', async () => { - const vitest = await runVitestCli(...cliArgs, '-t', 'sum') + const { vitest } = await runVitest({ ...options, testNamePattern: 'sum' }) vitest.write('r') + await vitest.waitForStdout('RERUN') await vitest.waitForStdout('Test name pattern: /sum/') await vitest.waitForStdout('1 passed') }) test('filter by filename', async () => { - const vitest = await runVitestCli(...cliArgs) + const { vitest } = await runVitest(options) vitest.write('p') @@ -57,7 +42,7 @@ test('filter by filename', async () => { }) test('filter by test name', async () => { - const vitest = await runVitestCli(...cliArgs) + const { vitest } = await runVitest(options) vitest.write('t') @@ -73,8 +58,8 @@ test('filter by test name', async () => { await vitest.waitForStdout('1 passed') }) -test('cancel test run', async () => { - const vitest = await runVitestCli(...cliArgs) +test.skipIf(process.env.GITHUB_ACTIONS)('cancel test run', async () => { + const { vitest } = await runVitest(options) const testPath = 'fixtures/cancel.test.ts' const testCase = `// Dynamic test case @@ -95,7 +80,7 @@ test('2 - test that is cancelled', async () => { }) ` - cleanups.push(() => rmSync(testPath)) + onTestFinished(() => rmSync(testPath)) writeFileSync(testPath, testCase, 'utf8') // Test case is running, cancel it diff --git a/test/watch/test/stdout.test.ts b/test/watch/test/stdout.test.ts index 5104a36324160..1cee6dc0ab7af 100644 --- a/test/watch/test/stdout.test.ts +++ b/test/watch/test/stdout.test.ts @@ -1,7 +1,6 @@ import { readFileSync, writeFileSync } from 'node:fs' import { afterEach, test } from 'vitest' - -import { runVitestCli } from '../../test-utils' +import { runVitest } from '../../test-utils' const testFile = 'fixtures/math.test.ts' const testFileContent = readFileSync(testFile, 'utf-8') @@ -11,8 +10,8 @@ afterEach(() => { }) test('console.log is visible on test re-run', async () => { - const vitest = await runVitestCli('--root', 'fixtures', '--watch') - vitest.resetOutput() + const { vitest } = await runVitest({ root: 'fixtures', watch: true }) + const testCase = ` test('test with logging', () => { console.log('First') diff --git a/test/watch/test/workspaces.test.ts b/test/watch/test/workspaces.test.ts index 18aeac8e5fa7d..6ea40633613d6 100644 --- a/test/watch/test/workspaces.test.ts +++ b/test/watch/test/workspaces.test.ts @@ -27,7 +27,7 @@ test("dynamic test case", () => { ` async function startVitest() { - const vitest = await runVitestCli( + const { vitest } = await runVitestCli( { cwd: root, env: { TEST_WATCH: 'true' } }, '--root', root,