diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0d72161..1c659c6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -21,5 +21,10 @@ updates: patterns: - 'playwright' - 'playwright-core' + # The coverage provider requires the exact vitest version it was released with. + vitest: + patterns: + - 'vitest' + - '@vitest/*' assignees: - sadjow diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 2f25533..2edb8df 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -17,3 +17,5 @@ Contact any of our current maintainers, or send us an email at [community@stackb Use the pnpm version pinned in `package.json`. With Corepack installed, run `corepack enable`, then `pnpm install --frozen-lockfile` and `pnpm dev:prepare` from the repository root. The module and playground share `pnpm-lock.yaml`; install dependencies from the root and use `pnpm --dir playground build` to build the playground directly. Before submitting a change, run `pnpm lint`, `pnpm format:check`, `pnpm test:types`, `pnpm test`, and `pnpm test:package`. Prettier owns formatting and ESLint checks everything else; `pnpm format` applies the formatting. For runtime changes, also run `pnpm test:compatibility` and `NUXT_VERSION=3 pnpm test:compatibility` to test independent consumers that are server-rendered, prerendered, and rendered only in the browser. `test/integration-rendering-modes.test.ts` covers the same three modes in `pnpm test`; extend it when a change affects when the module captures a visit. + +Run `pnpm test:coverage` to see how much of `src/` the tests cover. It runs the same tests as `pnpm test`, prints a per-file table, and writes an HTML report to `coverage/index.html`. The numbers count only code that runs inside the Vitest process: the unit tests and the module setup that runs while fixtures build. Code that the integration tests exercise in the browser or in the fixture's Nuxt server is not counted, so runtime files such as `src/runtime/composables.ts` can show low coverage even when integration tests use them. Read uncovered lines in `src/runtime` as having no unit test, not as untested. diff --git a/package.json b/package.json index 6c34793..e0653ba 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "lint:fix": "eslint . --fix && prettier --write .", "test": "vitest run", "test:watch": "vitest watch", + "test:coverage": "vitest run --coverage", "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit", "test:package": "pnpm run prepack && node scripts/test-package.mjs", "test:compatibility": "pnpm run prepack && node scripts/test-package.mjs --app" @@ -68,6 +69,7 @@ "@nuxt/schema": "^4.2.1", "@nuxt/test-utils": "^3.20.1 || ^4.0.0", "@types/node": "^26.2.0", + "@vitest/coverage-v8": "^5.0.0", "changelogen": "^0.6.1", "eslint": "^10.7.0", "eslint-config-prettier": "^10.1.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 323874f..c20c1e1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,10 +42,13 @@ importers: version: 4.5.2 '@nuxt/test-utils': specifier: ^3.20.1 || ^4.0.0 - version: 4.3.3(4ce1049374c1e4ab6917a26d2c293fa2) + version: 4.3.3(f49eb64441297c53bb0b1a87b9de950a) '@types/node': specifier: ^26.2.0 version: 26.6.4 + '@vitest/coverage-v8': + specifier: ^5.0.0 + version: 5.0.3(vitest@5.0.3) changelogen: specifier: ^0.6.1 version: 0.6.2(magicast@0.5.4) @@ -75,7 +78,7 @@ importers: version: 5.9.3 vitest: specifier: ^5.0.0 - version: 5.0.3(@types/node@26.6.4)(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0)) + version: 5.0.3(@types/node@26.6.4)(@vitest/coverage-v8@5.0.3)(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0)) vue: specifier: ^3.5.41 version: 3.5.43(typescript@5.9.3) @@ -228,6 +231,10 @@ packages: resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + '@bomb.sh/tab@0.0.19': resolution: {integrity: sha512-dTRfo9Q9B+lbLG3JCu8a/AGQSfD2XXcFcnakQzVjSOX+VvR/s9zpsH8TlqV3iHqazniRn1Ypwd1hcRlXcu/4BA==} hasBin: true @@ -1489,6 +1496,23 @@ packages: vite: ^8.1.5 vue: ^3.2.25 + '@vitest/coverage-v8@5.0.3': + resolution: {integrity: sha512-+klsyz7BvT1vCU28Zkfzms1Ia78XD0V41U3FUtRaa3S+vOr/EXvK1O6BvVD7l1RzEjm6SONR2aybOvDDf9u0mQ==} + peerDependencies: + '@vitest/browser': 5.0.3 + vitest: 5.0.3 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/istanbul-lib-coverage@1.0.2': + resolution: {integrity: sha512-9J/JMwOf9AoJhAywhrn7ScKTL38hsWQP/qPG60OtaAFcQ5OXPwKsxZFlbnuCKmZ61m8/lGgHYnFpdyQZUvG/iA==} + engines: {node: '>=22'} + + '@vitest/istanbul-lib-report@1.0.2': + resolution: {integrity: sha512-gUsfXZJbzPamoIY5TvHFiMMoXESBrUMo+xqaj+rYrWI69+EnvRlYBlP96ZnHPY4vX8kyUpgAnFUCg5wZG/HkDQ==} + engines: {node: '>=22'} + '@vitest/mocker@5.0.3': resolution: {integrity: sha512-T8sWAIbkSyAjkwTcaEc3Iu0o9A27X1/kdXrizhZkGuSKScRQtRzclfAMpOTcGdXCsqxeWlpGy3XjqaW8CpLORg==} peerDependencies: @@ -1672,6 +1696,9 @@ packages: resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==} engines: {node: '>=20.19.0'} + ast-v8-to-istanbul@1.0.7: + resolution: {integrity: sha512-kFL68AG6ajd8fg248zwM9GQrUWEp79gsmjum34OEXjs4yHuUMZfYKwOLW9GMmB4oNvVrj+EAGxsP7ye2UR9UlA==} + ast-walker-scope@0.9.0: resolution: {integrity: sha512-IJdzo2vLiElBxKzwS36VsCue/62d6IdWjnPB2v3nuPKeWGynp6FF/CYoLa5i/3jXH/z97ZDdsXz6abpgM6w07A==} engines: {node: '>=20.19.0'} @@ -4113,6 +4140,10 @@ packages: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} + tinyrainbow@3.2.0: + resolution: {integrity: sha512-LgO3D9yZJjApUiuUfl9iFAwrtaX4+lok3wJIqttGoKCHlWUqHqbQpnxCf82L8FjgKsh4iGo78hqJwgL8F6To2A==} + engines: {node: '>=14.0.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -4961,6 +4992,8 @@ snapshots: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 + '@bcoe/v8-coverage@1.0.2': {} + '@bomb.sh/tab@0.0.19(cac@7.0.0)(citty@0.2.2)': optionalDependencies: cac: 7.0.0 @@ -5811,7 +5844,7 @@ snapshots: rc9: 3.1.0 std-env: 4.3.0 - '@nuxt/test-utils@4.3.3(4ce1049374c1e4ab6917a26d2c293fa2)': + '@nuxt/test-utils@4.3.3(f49eb64441297c53bb0b1a87b9de950a)': dependencies: '@clack/prompts': 1.8.1 '@nuxt/devtools-kit': 3.4.2(magic-string@1.4.2)(magicast@0.5.4)(rolldown@1.2.7)(unplugin@3.4.0(esbuild@0.28.1)(rolldown@1.2.7)(rollup@4.63.1)(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0)))(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0)) @@ -5832,13 +5865,13 @@ snapshots: tinyexec: 1.3.1 ufo: 1.6.4 unplugin: 3.4.0(esbuild@0.28.1)(rolldown@1.2.7)(rollup@4.63.1)(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0)) - vitest-environment-nuxt: 2.0.0(4ce1049374c1e4ab6917a26d2c293fa2) + vitest-environment-nuxt: 2.0.0(f49eb64441297c53bb0b1a87b9de950a) vue: 3.5.43(typescript@5.9.3) optionalDependencies: h3: 1.15.11 nuxt: 4.5.2(@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7(supports-color@10.2.2)))(@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7(supports-color@10.2.2)))(@oxc-project/types@0.148.0)(@parcel/watcher@2.5.6)(@types/node@26.6.4)(@vue/compiler-sfc@3.5.43)(cac@7.0.0)(db0@0.3.4)(esbuild@0.28.1)(eslint@10.11.0(jiti@2.7.0)(supports-color@10.2.2))(ioredis@5.11.1(supports-color@10.2.2))(lightningcss@1.33.0)(magicast@0.5.4)(optionator@0.9.4)(rolldown@1.2.7)(rollup-plugin-visualizer@7.1.1(rolldown@1.2.7)(rollup@4.63.1))(rollup@4.63.1)(srvx@0.11.22)(supports-color@10.2.2)(terser@5.51.2)(typescript@5.9.3)(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0))(vue-tsc@3.3.12(typescript@5.9.3))(yaml@2.9.0) playwright-core: 1.63.0 - vitest: 5.0.3(@types/node@26.6.4)(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0)) + vitest: 5.0.3(@types/node@26.6.4)(@vitest/coverage-v8@5.0.3)(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0)) transitivePeerDependencies: - '@farmfe/core' - '@oxc-project/types' @@ -6551,6 +6584,24 @@ snapshots: vite: 8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0) vue: 3.5.43(typescript@5.9.3) + '@vitest/coverage-v8@5.0.3(vitest@5.0.3)': + dependencies: + '@bcoe/v8-coverage': 1.0.2 + '@vitest/istanbul-lib-coverage': 1.0.2 + '@vitest/istanbul-lib-report': 1.0.2 + ast-v8-to-istanbul: 1.0.7 + magicast: 0.5.4 + obug: 2.2.1 + std-env: 4.3.0 + tinyrainbow: 3.2.0 + vitest: 5.0.3(@types/node@26.6.4)(@vitest/coverage-v8@5.0.3)(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0)) + + '@vitest/istanbul-lib-coverage@1.0.2': {} + + '@vitest/istanbul-lib-report@1.0.2': + dependencies: + '@vitest/istanbul-lib-coverage': 1.0.2 + '@vitest/mocker@5.0.3(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0))': dependencies: '@jridgewell/trace-mapping': 0.3.31 @@ -6781,6 +6832,12 @@ snapshots: '@babel/parser': 7.29.8 pathe: 2.0.3 + ast-v8-to-istanbul@1.0.7: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + estree-walker: 3.0.3 + js-tokens: 10.0.0 + ast-walker-scope@0.9.0: dependencies: '@babel/parser': 7.29.8 @@ -9721,6 +9778,8 @@ snapshots: fdir: 6.5.0(picomatch@4.0.7) picomatch: 4.0.7 + tinyrainbow@3.2.0: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -10089,9 +10148,9 @@ snapshots: terser: 5.51.2 yaml: 2.9.0 - vitest-environment-nuxt@2.0.0(4ce1049374c1e4ab6917a26d2c293fa2): + vitest-environment-nuxt@2.0.0(f49eb64441297c53bb0b1a87b9de950a): dependencies: - '@nuxt/test-utils': 4.3.3(4ce1049374c1e4ab6917a26d2c293fa2) + '@nuxt/test-utils': 4.3.3(f49eb64441297c53bb0b1a87b9de950a) transitivePeerDependencies: - '@cucumber/cucumber' - '@farmfe/core' @@ -10120,7 +10179,7 @@ snapshots: - vue - webpack - vitest@5.0.3(@types/node@26.6.4)(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0)): + vitest@5.0.3(@types/node@26.6.4)(@vitest/coverage-v8@5.0.3)(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0)): dependencies: '@types/chai': 5.2.3 '@vitest/mocker': 5.0.3(vite@8.2.2(@types/node@26.6.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.51.2)(yaml@2.9.0)) @@ -10138,6 +10197,7 @@ snapshots: why-is-node-running: 3.2.1 optionalDependencies: '@types/node': 26.6.4 + '@vitest/coverage-v8': 5.0.3(vitest@5.0.3) transitivePeerDependencies: - msw diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..2fc08a1 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + coverage: { + include: ['src/**'], + }, + }, +})