fix(tooling): restore L0 coverage sweep across all packages
The template baseline shipped 9 packages without @vitest/coverage-v8 and documented an L0 invocation turbo cannot parse — the full coverage sweep had never run. Adds the provider (pinned to the feature-package spec), a root test:coverage script, corrects every live doc/prompt/CI occurrence, and calibrates coverage excludes for the 4 packages whose latent threshold failures the outage masked (framework glue only — zero threshold numbers changed). L0 sweep now passes 21/21. Squash of a284baa + 5c6af95 (worktree-agent-a013c67cea83b2636), implemented and reviewed via the dispatch loop under the epic's baseline waiver (lint pending story 03). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
This commit is contained in:
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -80,7 +80,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
DATABASE_URL: postgres://postgres:postgres@localhost:5432/cms_test
|
DATABASE_URL: postgres://postgres:postgres@localhost:5432/cms_test
|
||||||
PAYLOAD_SECRET: test-secret-do-not-use-in-prod
|
PAYLOAD_SECRET: test-secret-do-not-use-in-prod
|
||||||
run: pnpm test -- --coverage
|
run: pnpm test:coverage
|
||||||
# L2 — merge per-package lcovs to coverage/lcov.info + emit
|
# L2 — merge per-package lcovs to coverage/lcov.info + emit
|
||||||
# coverage/summary.json (ADR-020). Runs even on test failure so the
|
# coverage/summary.json (ADR-020). Runs even on test failure so the
|
||||||
# artifact still captures what was produced.
|
# artifact still captures what was produced.
|
||||||
|
|||||||
2
.github/workflows/coverage-snapshot.yml
vendored
2
.github/workflows/coverage-snapshot.yml
vendored
@@ -52,7 +52,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
DATABASE_URL: postgres://postgres:postgres@localhost:5432/cms_test
|
DATABASE_URL: postgres://postgres:postgres@localhost:5432/cms_test
|
||||||
PAYLOAD_SECRET: test-secret-do-not-use-in-prod
|
PAYLOAD_SECRET: test-secret-do-not-use-in-prod
|
||||||
run: pnpm test -- --coverage
|
run: pnpm test:coverage
|
||||||
- name: Aggregate
|
- name: Aggregate
|
||||||
run: pnpm coverage:aggregate
|
run: pnpm coverage:aggregate
|
||||||
- name: Commit summary.json if changed
|
- name: Commit summary.json if changed
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -30,6 +30,7 @@ storybook-static
|
|||||||
# Testing — per-package coverage output (vitest)
|
# Testing — per-package coverage output (vitest)
|
||||||
packages/*/coverage/
|
packages/*/coverage/
|
||||||
apps/*/coverage/
|
apps/*/coverage/
|
||||||
|
turbo/generators/coverage/
|
||||||
# Aggregated coverage output (pnpm coverage:aggregate): ignore everything
|
# Aggregated coverage output (pnpm coverage:aggregate): ignore everything
|
||||||
# under /coverage/ EXCEPT summary.json (committed for trend history per
|
# under /coverage/ EXCEPT summary.json (committed for trend history per
|
||||||
# ADR-020) and .gitkeep markers.
|
# ADR-020) and .gitkeep markers.
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ All five pass before you commit. If any fail, fix or report BLOCKED — do not p
|
|||||||
The coverage architecture has its own multi-layer enforcement that's distinct from the conformance gates above. Run all of these before declaring done:
|
The coverage architecture has its own multi-layer enforcement that's distinct from the conformance gates above. Run all of these before declaring done:
|
||||||
|
|
||||||
```
|
```
|
||||||
pnpm test -- --coverage # L0 — per-layer thresholds (100% on entities/use-cases/controllers)
|
pnpm test:coverage # L0 — per-layer thresholds (100% on entities/use-cases/controllers)
|
||||||
pnpm coverage:aggregate # L2 — merges per-package lcovs to coverage/lcov.info + coverage/summary.json
|
pnpm coverage:aggregate # L2 — merges per-package lcovs to coverage/lcov.info + coverage/summary.json
|
||||||
pnpm coverage:diff -- --base <base-ref> # L1 — cover-the-diff: every changed line must be exercised
|
pnpm coverage:diff -- --base <base-ref> # L1 — cover-the-diff: every changed line must be exercised
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ docker compose up -d # Start PostgreSQL
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm test --watch --filter @repo/<feature> # watch one feature
|
pnpm test --watch --filter @repo/<feature> # watch one feature
|
||||||
pnpm test -- --coverage # full run with coverage
|
pnpm test:coverage # full run with coverage
|
||||||
pnpm test:stories # Storybook smoke tests
|
pnpm test:stories # Storybook smoke tests
|
||||||
pnpm test:e2e # Playwright e2e
|
pnpm test:e2e # Playwright e2e
|
||||||
```
|
```
|
||||||
@@ -85,7 +85,7 @@ Coverage runs in parallel to the 5-gate conformance system above — same multi-
|
|||||||
|
|
||||||
| Layer | Catches | Surface |
|
| Layer | Catches | Surface |
|
||||||
| ---------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
|
| ---------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
|
||||||
| **L0** Per-layer vitest thresholds | Drift below declared bands (entities/use-cases/controllers at 100%) | `pnpm test -- --coverage` |
|
| **L0** Per-layer vitest thresholds | Drift below declared bands (entities/use-cases/controllers at 100%) | `pnpm test:coverage` |
|
||||||
| **L1** Diff coverage | Changed line not exercised by tests | `pnpm coverage:diff` — CI-gated on PRs + dispatch post-task |
|
| **L1** Diff coverage | Changed line not exercised by tests | `pnpm coverage:diff` — CI-gated on PRs + dispatch post-task |
|
||||||
| **L2** Aggregate trend | Codebase coverage drifted over time | `pnpm coverage:aggregate` → committed `coverage/summary.json` |
|
| **L2** Aggregate trend | Codebase coverage drifted over time | `pnpm coverage:aggregate` → committed `coverage/summary.json` |
|
||||||
| **L3** Mutation testing | Tests that exist + execute the code but assert nothing | `pnpm mutate` — on-demand + nightly GH Action |
|
| **L3** Mutation testing | Tests that exist + execute the code but assert nothing | `pnpm mutate` — on-demand + nightly GH Action |
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
"@types/node": "^22.0.0",
|
"@types/node": "^22.0.0",
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.0.0",
|
||||||
"@types/react-dom": "^19.0.0",
|
"@types/react-dom": "^19.0.0",
|
||||||
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"vitest": "^3.0.0"
|
"vitest": "^3.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,20 @@ import path from "node:path";
|
|||||||
import { mergeConfig } from "vitest/config";
|
import { mergeConfig } from "vitest/config";
|
||||||
import { nodeVitestConfig } from "@repo/core-typescript/vitest.base.node";
|
import { nodeVitestConfig } from "@repo/core-typescript/vitest.base.node";
|
||||||
|
|
||||||
|
// Coverage excludes mirror the feature-package pattern (see
|
||||||
|
// packages/auth/vitest.config.ts): framework glue is excluded, thresholds
|
||||||
|
// stay inherited from the shared base — never lowered here.
|
||||||
export default mergeConfig(nodeVitestConfig, {
|
export default mergeConfig(nodeVitestConfig, {
|
||||||
|
test: {
|
||||||
|
coverage: {
|
||||||
|
exclude: [
|
||||||
|
// Payload-generated admin UI + API mount points: importMap.js is
|
||||||
|
// stamped "GENERATED AUTOMATICALLY BY PAYLOAD"; the layout/page/
|
||||||
|
// route files are one-line re-exports of @payloadcms/next handlers.
|
||||||
|
// Exercised through the running CMS, not unit-testable.
|
||||||
|
"src/app/**",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
resolve: { alias: { "@": path.resolve(__dirname, "./src") } },
|
resolve: { alias: { "@": path.resolve(__dirname, "./src") } },
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
"@types/node": "^22.0.0",
|
"@types/node": "^22.0.0",
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.0.0",
|
||||||
"@types/react-dom": "^19.0.0",
|
"@types/react-dom": "^19.0.0",
|
||||||
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"jsdom": "^25.0.0",
|
"jsdom": "^25.0.0",
|
||||||
"tsx": "^4.0.0",
|
"tsx": "^4.0.0",
|
||||||
"vitest": "^3.0.0"
|
"vitest": "^3.0.0"
|
||||||
|
|||||||
@@ -2,7 +2,25 @@ import path from "node:path";
|
|||||||
import { mergeConfig } from "vitest/config";
|
import { mergeConfig } from "vitest/config";
|
||||||
import { jsdomVitestConfig } from "@repo/core-typescript/vitest.base.jsdom";
|
import { jsdomVitestConfig } from "@repo/core-typescript/vitest.base.jsdom";
|
||||||
|
|
||||||
|
// Coverage excludes mirror the feature-package pattern (see
|
||||||
|
// packages/auth/vitest.config.ts): framework glue is excluded, thresholds
|
||||||
|
// stay inherited from the shared base — never lowered here.
|
||||||
export default mergeConfig(jsdomVitestConfig, {
|
export default mergeConfig(jsdomVitestConfig, {
|
||||||
esbuild: { jsx: "automatic" },
|
esbuild: { jsx: "automatic" },
|
||||||
|
test: {
|
||||||
|
coverage: {
|
||||||
|
exclude: [
|
||||||
|
// Next.js App Router entry points — async server components and the
|
||||||
|
// tRPC route-handler mount, invoked by the framework and covered by
|
||||||
|
// Playwright e2e; not unit-testable in jsdom. providers.tsx and
|
||||||
|
// src/server/** stay counted (they have unit tests).
|
||||||
|
"src/app/**/layout.tsx",
|
||||||
|
"src/app/**/page.tsx",
|
||||||
|
"src/app/**/route.ts",
|
||||||
|
// Ambient type declarations — no executable code
|
||||||
|
"src/**/*.d.ts",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
resolve: { alias: { "@": path.resolve(__dirname, "./src") } },
|
resolve: { alias: { "@": path.resolve(__dirname, "./src") } },
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
"@types/node": "^22.0.0",
|
"@types/node": "^22.0.0",
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.0.0",
|
||||||
"@types/react-dom": "^19.0.0",
|
"@types/react-dom": "^19.0.0",
|
||||||
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"jsdom": "^25.0.0",
|
"jsdom": "^25.0.0",
|
||||||
"vitest": "^3.0.0"
|
"vitest": "^3.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,25 @@ import path from "node:path";
|
|||||||
import { mergeConfig } from "vitest/config";
|
import { mergeConfig } from "vitest/config";
|
||||||
import { jsdomVitestConfig } from "@repo/core-typescript/vitest.base.jsdom";
|
import { jsdomVitestConfig } from "@repo/core-typescript/vitest.base.jsdom";
|
||||||
|
|
||||||
|
// Coverage excludes mirror the feature-package pattern (see
|
||||||
|
// packages/auth/vitest.config.ts): framework glue is excluded, thresholds
|
||||||
|
// stay inherited from the shared base — never lowered here.
|
||||||
export default mergeConfig(jsdomVitestConfig, {
|
export default mergeConfig(jsdomVitestConfig, {
|
||||||
esbuild: { jsx: "automatic" },
|
esbuild: { jsx: "automatic" },
|
||||||
|
test: {
|
||||||
|
coverage: {
|
||||||
|
exclude: [
|
||||||
|
// TanStack Router route definitions — framework-invoked entry
|
||||||
|
// points, covered by Playwright e2e; not unit tests
|
||||||
|
"src/routes/**",
|
||||||
|
// Server-entry OTel/Sentry boot wiring — import-time side effects
|
||||||
|
// run once at startup (same class as feature DI bootstrap).
|
||||||
|
// instrumentation-client.ts stays counted (it has a unit test).
|
||||||
|
"src/instrumentation.ts",
|
||||||
|
// Ambient type declarations — no executable code
|
||||||
|
"src/**/*.d.ts",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
resolve: { alias: { "@": path.resolve(__dirname, "./src") } },
|
resolve: { alias: { "@": path.resolve(__dirname, "./src") } },
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ The agent-first coverage architecture has four layers. This guide is the day-to-
|
|||||||
|
|
||||||
| Layer | Question it answers | Command |
|
| Layer | Question it answers | Command |
|
||||||
| ---------------------------------- | ------------------------------------------------ | ---------------------------------------------------- |
|
| ---------------------------------- | ------------------------------------------------ | ---------------------------------------------------- |
|
||||||
| **L0** Per-layer vitest thresholds | "Did the last test run meet the declared bands?" | `pnpm test -- --coverage` |
|
| **L0** Per-layer vitest thresholds | "Did the last test run meet the declared bands?" | `pnpm test:coverage` |
|
||||||
| **L1** Diff coverage | "Did this PR/slice cover its own changed lines?" | `pnpm coverage:diff` |
|
| **L1** Diff coverage | "Did this PR/slice cover its own changed lines?" | `pnpm coverage:diff` |
|
||||||
| **L2** Aggregate trend | "How is coverage trending across the repo?" | `pnpm coverage:aggregate` → `coverage/summary.json` |
|
| **L2** Aggregate trend | "How is coverage trending across the repo?" | `pnpm coverage:aggregate` → `coverage/summary.json` |
|
||||||
| **L3** Mutation testing | "Do my tests actually assert anything?" | `pnpm mutate` _(opt-in, not in default `pnpm test`)_ |
|
| **L3** Mutation testing | "Do my tests actually assert anything?" | `pnpm mutate` _(opt-in, not in default `pnpm test`)_ |
|
||||||
@@ -58,7 +58,7 @@ Two readers pick this up today:
|
|||||||
### Before pushing
|
### Before pushing
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm test -- --coverage # L0 — per-package thresholds enforced
|
pnpm test:coverage # L0 — per-package thresholds enforced
|
||||||
pnpm coverage:aggregate # L2 — produce coverage/lcov.info + summary.json
|
pnpm coverage:aggregate # L2 — produce coverage/lcov.info + summary.json
|
||||||
pnpm coverage:diff # L1 — fails if changed lines aren't covered
|
pnpm coverage:diff # L1 — fails if changed lines aren't covered
|
||||||
```
|
```
|
||||||
@@ -255,7 +255,7 @@ Fix: read the surviving mutant's diff in `reports/mutation/index.html`, identify
|
|||||||
|
|
||||||
**"Coverage for lines (X%) does not meet 'src/...' threshold (Y%)"** — L0 failure. Real test gap. Either write the missing test or adjust the manifest band downward (rare; band relaxation should be justified).
|
**"Coverage for lines (X%) does not meet 'src/...' threshold (Y%)"** — L0 failure. Real test gap. Either write the missing test or adjust the manifest band downward (rare; band relaxation should be justified).
|
||||||
|
|
||||||
**`pnpm coverage:diff` says "lcov file not found"** — run `pnpm test -- --coverage && pnpm coverage:aggregate` first. The diff script reads the merged root `coverage/lcov.info`.
|
**`pnpm coverage:diff` says "lcov file not found"** — run `pnpm test:coverage && pnpm coverage:aggregate` first. The diff script reads the merged root `coverage/lcov.info`.
|
||||||
|
|
||||||
**`coverage/summary.json` differs every commit** — expected. It includes `generatedAt` (ISO timestamp) and `commit` (SHA). The snapshot workflow only commits it when the underlying numbers change; in local dev, regenerating it shows diff noise.
|
**`coverage/summary.json` differs every commit** — expected. It includes `generatedAt` (ISO timestamp) and `commit` (SHA). The snapshot workflow only commits it when the underlying numbers change; in local dev, regenerating it shows diff noise.
|
||||||
|
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ HTML report lands at `packages/blog/coverage/index.html` — open it in a browse
|
|||||||
To run coverage across all packages:
|
To run coverage across all packages:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm test -- --coverage
|
pnpm test:coverage
|
||||||
```
|
```
|
||||||
|
|
||||||
Coverage thresholds are enforced in `packages/core-typescript/vitest.base.ts` and inherited by every package's `vitest.config.ts` via `nodeVitestConfig` / `jsdomVitestConfig`.
|
Coverage thresholds are enforced in `packages/core-typescript/vitest.base.ts` and inherited by every package's `vitest.config.ts` via `nodeVitestConfig` / `jsdomVitestConfig`.
|
||||||
@@ -655,10 +655,10 @@ Then attach Chrome DevTools at `chrome://inspect`.
|
|||||||
**Coverage:**
|
**Coverage:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm test --coverage --filter @repo/blog
|
pnpm test --filter @repo/blog -- --coverage
|
||||||
# HTML report: packages/blog/coverage/index.html
|
# HTML report: packages/blog/coverage/index.html
|
||||||
|
|
||||||
pnpm test -- --coverage
|
pnpm test:coverage
|
||||||
# HTML reports: packages/*/coverage/index.html
|
# HTML reports: packages/*/coverage/index.html
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
"dev": "dotenv -- turbo run dev",
|
"dev": "dotenv -- turbo run dev",
|
||||||
"lint": "turbo run lint",
|
"lint": "turbo run lint",
|
||||||
"test": "turbo run test",
|
"test": "turbo run test",
|
||||||
|
"test:coverage": "turbo run test -- --coverage",
|
||||||
"test:e2e": "turbo run test:e2e",
|
"test:e2e": "turbo run test:e2e",
|
||||||
"test:stories": "turbo run test:stories",
|
"test:stories": "turbo run test:stories",
|
||||||
"test:visual": "pnpm --filter @repo/storybook exec concurrently -k -s first -n 'SB,VRT' -c 'magenta,blue' 'pnpm --filter @repo/storybook exec http-server storybook-static --port 6006 --silent' 'pnpm --filter @repo/storybook exec wait-on tcp:6006 && pnpm exec playwright test'",
|
"test:visual": "pnpm --filter @repo/storybook exec concurrently -k -s first -n 'SB,VRT' -c 'magenta,blue' 'pnpm --filter @repo/storybook exec http-server storybook-static --port 6006 --silent' 'pnpm --filter @repo/storybook exec wait-on tcp:6006 && pnpm exec playwright test'",
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
"@repo/core-eslint": "workspace:*",
|
"@repo/core-eslint": "workspace:*",
|
||||||
"@repo/core-testing": "workspace:*",
|
"@repo/core-testing": "workspace:*",
|
||||||
"@repo/core-typescript": "workspace:*",
|
"@repo/core-typescript": "workspace:*",
|
||||||
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"inversify": "^6.2.0",
|
"inversify": "^6.2.0",
|
||||||
"payload": "^3.14.0",
|
"payload": "^3.14.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
|
|||||||
@@ -14,20 +14,21 @@
|
|||||||
"test": "vitest run --passWithNoTests"
|
"test": "vitest run --passWithNoTests"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@payloadcms/db-postgres": "^3.14.0",
|
||||||
|
"@payloadcms/richtext-lexical": "^3.14.0",
|
||||||
"@repo/auth": "workspace:*",
|
"@repo/auth": "workspace:*",
|
||||||
"@repo/blog": "workspace:*",
|
"@repo/blog": "workspace:*",
|
||||||
"@repo/media": "workspace:*",
|
|
||||||
"@repo/marketing-pages": "workspace:*",
|
"@repo/marketing-pages": "workspace:*",
|
||||||
|
"@repo/media": "workspace:*",
|
||||||
"@repo/navigation": "workspace:*",
|
"@repo/navigation": "workspace:*",
|
||||||
"payload": "^3.14.0",
|
"payload": "^3.14.0"
|
||||||
"@payloadcms/db-postgres": "^3.14.0",
|
|
||||||
"@payloadcms/richtext-lexical": "^3.14.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@repo/core-eslint": "workspace:*",
|
"@repo/core-eslint": "workspace:*",
|
||||||
"@repo/core-testing": "workspace:*",
|
"@repo/core-testing": "workspace:*",
|
||||||
"@repo/core-typescript": "workspace:*",
|
"@repo/core-typescript": "workspace:*",
|
||||||
"@types/node": "^22.0.0",
|
"@types/node": "^22.0.0",
|
||||||
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"vitest": "^3.0.0"
|
"vitest": "^3.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
"@eslint/js": "^9.20.0",
|
"@eslint/js": "^9.20.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.25.0",
|
"@typescript-eslint/eslint-plugin": "^8.25.0",
|
||||||
"@typescript-eslint/parser": "^8.25.0",
|
"@typescript-eslint/parser": "^8.25.0",
|
||||||
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"eslint": "^9.20.0",
|
"eslint": "^9.20.0",
|
||||||
"eslint-config-prettier": "^10.1.0",
|
"eslint-config-prettier": "^10.1.0",
|
||||||
"eslint-plugin-boundaries": "^4.2.2",
|
"eslint-plugin-boundaries": "^4.2.2",
|
||||||
|
|||||||
@@ -25,16 +25,16 @@
|
|||||||
"test": "vitest run"
|
"test": "vitest run"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tanstack/react-query": "^5.59.0",
|
||||||
"@testing-library/jest-dom": "^6.5.0",
|
"@testing-library/jest-dom": "^6.5.0",
|
||||||
"zod": "^3.23.0",
|
|
||||||
"@testing-library/react": "^16.0.0",
|
"@testing-library/react": "^16.0.0",
|
||||||
"@testing-library/user-event": "^14.5.0",
|
"@testing-library/user-event": "^14.5.0",
|
||||||
"@trpc/client": "^11.0.0",
|
"@trpc/client": "^11.0.0",
|
||||||
"@tanstack/react-query": "^5.59.0",
|
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"superjson": "^2.2.0",
|
"superjson": "^2.2.0",
|
||||||
"vitest": "^3.0.0"
|
"vitest": "^3.0.0",
|
||||||
|
"zod": "^3.23.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@trpc/server": "^11.0.0",
|
"@trpc/server": "^11.0.0",
|
||||||
@@ -54,6 +54,7 @@
|
|||||||
"@sentry/nextjs": "^10.51.0",
|
"@sentry/nextjs": "^10.51.0",
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.0.0",
|
||||||
"@types/react-dom": "^19.0.0",
|
"@types/react-dom": "^19.0.0",
|
||||||
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"jsdom": "^25.0.0",
|
"jsdom": "^25.0.0",
|
||||||
"typescript": "^5.8.0"
|
"typescript": "^5.8.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
"@testing-library/jest-dom": "^6.5.0",
|
"@testing-library/jest-dom": "^6.5.0",
|
||||||
"@testing-library/react": "^16.0.0",
|
"@testing-library/react": "^16.0.0",
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.0.0",
|
||||||
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"jsdom": "^25.0.0",
|
"jsdom": "^25.0.0",
|
||||||
"vitest": "^3.0.0"
|
"vitest": "^3.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,20 @@ import path from "node:path";
|
|||||||
import { mergeConfig } from "vitest/config";
|
import { mergeConfig } from "vitest/config";
|
||||||
import { jsdomVitestConfig } from "@repo/core-typescript/vitest.base.jsdom";
|
import { jsdomVitestConfig } from "@repo/core-typescript/vitest.base.jsdom";
|
||||||
|
|
||||||
|
// Coverage excludes mirror the feature-package pattern (see
|
||||||
|
// packages/auth/vitest.config.ts): framework glue is excluded, thresholds
|
||||||
|
// stay inherited from the shared base — never lowered here.
|
||||||
export default mergeConfig(jsdomVitestConfig, {
|
export default mergeConfig(jsdomVitestConfig, {
|
||||||
|
test: {
|
||||||
|
coverage: {
|
||||||
|
exclude: [
|
||||||
|
// React context providers wiring tRPC + React Query into each
|
||||||
|
// framework's render tree — integration-tested in the apps
|
||||||
|
"src/providers/**",
|
||||||
|
// QueryClient bootstrap factory consumed by the providers
|
||||||
|
"src/query-client.ts",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
resolve: { alias: { "@": path.resolve(__dirname, "./src") } },
|
resolve: { alias: { "@": path.resolve(__dirname, "./src") } },
|
||||||
});
|
});
|
||||||
|
|||||||
27
pnpm-lock.yaml
generated
27
pnpm-lock.yaml
generated
@@ -110,6 +110,9 @@ importers:
|
|||||||
"@types/react-dom":
|
"@types/react-dom":
|
||||||
specifier: ^19.0.0
|
specifier: ^19.0.0
|
||||||
version: 19.2.3(@types/react@19.2.14)
|
version: 19.2.3(@types/react@19.2.14)
|
||||||
|
"@vitest/coverage-v8":
|
||||||
|
specifier: ^3.2.4
|
||||||
|
version: 3.2.4(vitest@3.2.4(@types/debug@4.1.13)(@types/node@22.19.17)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0))
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.2.4(@types/debug@4.1.13)(@types/node@22.19.17)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0)
|
version: 3.2.4(@types/debug@4.1.13)(@types/node@22.19.17)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0)
|
||||||
@@ -264,6 +267,9 @@ importers:
|
|||||||
"@types/react-dom":
|
"@types/react-dom":
|
||||||
specifier: ^19.0.0
|
specifier: ^19.0.0
|
||||||
version: 19.2.3(@types/react@19.2.14)
|
version: 19.2.3(@types/react@19.2.14)
|
||||||
|
"@vitest/coverage-v8":
|
||||||
|
specifier: ^3.2.4
|
||||||
|
version: 3.2.4(vitest@3.2.4(@types/debug@4.1.13)(@types/node@22.19.17)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0))
|
||||||
jsdom:
|
jsdom:
|
||||||
specifier: ^25.0.0
|
specifier: ^25.0.0
|
||||||
version: 25.0.1
|
version: 25.0.1
|
||||||
@@ -349,6 +355,9 @@ importers:
|
|||||||
"@types/react-dom":
|
"@types/react-dom":
|
||||||
specifier: ^19.0.0
|
specifier: ^19.0.0
|
||||||
version: 19.2.3(@types/react@19.2.14)
|
version: 19.2.3(@types/react@19.2.14)
|
||||||
|
"@vitest/coverage-v8":
|
||||||
|
specifier: ^3.2.4
|
||||||
|
version: 3.2.4(vitest@3.2.4(@types/debug@4.1.13)(@types/node@22.19.17)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0))
|
||||||
jsdom:
|
jsdom:
|
||||||
specifier: ^25.0.0
|
specifier: ^25.0.0
|
||||||
version: 25.0.1
|
version: 25.0.1
|
||||||
@@ -570,6 +579,9 @@ importers:
|
|||||||
"@repo/core-typescript":
|
"@repo/core-typescript":
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../core-typescript
|
version: link:../core-typescript
|
||||||
|
"@vitest/coverage-v8":
|
||||||
|
specifier: ^3.2.4
|
||||||
|
version: 3.2.4(vitest@3.2.4(@types/debug@4.1.13)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0))
|
||||||
inversify:
|
inversify:
|
||||||
specifier: ^6.2.0
|
specifier: ^6.2.0
|
||||||
version: 6.2.2(reflect-metadata@0.2.2)
|
version: 6.2.2(reflect-metadata@0.2.2)
|
||||||
@@ -625,6 +637,9 @@ importers:
|
|||||||
"@types/node":
|
"@types/node":
|
||||||
specifier: ^22.0.0
|
specifier: ^22.0.0
|
||||||
version: 22.19.17
|
version: 22.19.17
|
||||||
|
"@vitest/coverage-v8":
|
||||||
|
specifier: ^3.2.4
|
||||||
|
version: 3.2.4(vitest@3.2.4(@types/debug@4.1.13)(@types/node@22.19.17)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0))
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.2.4(@types/debug@4.1.13)(@types/node@22.19.17)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0)
|
version: 3.2.4(@types/debug@4.1.13)(@types/node@22.19.17)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0)
|
||||||
@@ -724,6 +739,9 @@ importers:
|
|||||||
"@typescript-eslint/parser":
|
"@typescript-eslint/parser":
|
||||||
specifier: ^8.25.0
|
specifier: ^8.25.0
|
||||||
version: 8.58.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)
|
version: 8.58.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)
|
||||||
|
"@vitest/coverage-v8":
|
||||||
|
specifier: ^3.2.4
|
||||||
|
version: 3.2.4(vitest@3.2.4(@types/debug@4.1.13)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0))
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ^9.20.0
|
specifier: ^9.20.0
|
||||||
version: 9.39.4(jiti@2.7.0)
|
version: 9.39.4(jiti@2.7.0)
|
||||||
@@ -891,6 +909,9 @@ importers:
|
|||||||
"@types/react-dom":
|
"@types/react-dom":
|
||||||
specifier: ^19.0.0
|
specifier: ^19.0.0
|
||||||
version: 19.2.3(@types/react@19.2.14)
|
version: 19.2.3(@types/react@19.2.14)
|
||||||
|
"@vitest/coverage-v8":
|
||||||
|
specifier: ^3.2.4
|
||||||
|
version: 3.2.4(vitest@3.2.4(@types/debug@4.1.13)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0))
|
||||||
jsdom:
|
jsdom:
|
||||||
specifier: ^25.0.0
|
specifier: ^25.0.0
|
||||||
version: 25.0.1
|
version: 25.0.1
|
||||||
@@ -943,6 +964,9 @@ importers:
|
|||||||
"@types/react":
|
"@types/react":
|
||||||
specifier: ^19.0.0
|
specifier: ^19.0.0
|
||||||
version: 19.2.14
|
version: 19.2.14
|
||||||
|
"@vitest/coverage-v8":
|
||||||
|
specifier: ^3.2.4
|
||||||
|
version: 3.2.4(vitest@3.2.4(@types/debug@4.1.13)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0))
|
||||||
jsdom:
|
jsdom:
|
||||||
specifier: ^25.0.0
|
specifier: ^25.0.0
|
||||||
version: 25.0.1
|
version: 25.0.1
|
||||||
@@ -1179,6 +1203,9 @@ importers:
|
|||||||
"@repo/core-typescript":
|
"@repo/core-typescript":
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/core-typescript
|
version: link:../../packages/core-typescript
|
||||||
|
"@vitest/coverage-v8":
|
||||||
|
specifier: ^3.2.4
|
||||||
|
version: 3.2.4(vitest@3.2.4(@types/debug@4.1.13)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0))
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.8.0
|
specifier: ^5.8.0
|
||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ function main() {
|
|||||||
if (lcovs.length === 0) {
|
if (lcovs.length === 0) {
|
||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`[coverage:aggregate] No per-package lcov.info files found.\n` +
|
`[coverage:aggregate] No per-package lcov.info files found.\n` +
|
||||||
`Run \`pnpm test -- --coverage\` first.\n`,
|
`Run \`pnpm test:coverage\` first.\n`,
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ export function computeDiffCoverage(diff, lcov, opts = {}) {
|
|||||||
// Try matching by suffix in either direction. lcov paths can be:
|
// Try matching by suffix in either direction. lcov paths can be:
|
||||||
// - absolute (vitest with `coverage.reportsDirectory` at default)
|
// - absolute (vitest with `coverage.reportsDirectory` at default)
|
||||||
// - repo-relative (after `pnpm coverage:aggregate` normalizes)
|
// - repo-relative (after `pnpm coverage:aggregate` normalizes)
|
||||||
// - package-relative (per-package lcov from `pnpm test -- --coverage`)
|
// - package-relative (per-package lcov from `pnpm test:coverage`)
|
||||||
// The diff path is always repo-relative.
|
// The diff path is always repo-relative.
|
||||||
for (const [k, v] of lcov.entries()) {
|
for (const [k, v] of lcov.entries()) {
|
||||||
if (file.endsWith("/" + k) || k.endsWith("/" + file) || k === file) {
|
if (file.endsWith("/" + k) || k.endsWith("/" + file) || k === file) {
|
||||||
@@ -264,7 +264,7 @@ function main() {
|
|||||||
if (!fs.existsSync(lcovPath)) {
|
if (!fs.existsSync(lcovPath)) {
|
||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`[coverage:diff] lcov file not found at ${lcovPath}\n` +
|
`[coverage:diff] lcov file not found at ${lcovPath}\n` +
|
||||||
`Run \`pnpm test -- --coverage\` first, then \`pnpm coverage:aggregate\`.\n`,
|
`Run \`pnpm test:coverage\` first, then \`pnpm coverage:aggregate\`.\n`,
|
||||||
);
|
);
|
||||||
// Emit JSON anyway so the dispatch loop can read it
|
// Emit JSON anyway so the dispatch loop can read it
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@repo/core-eslint": "workspace:*",
|
"@repo/core-eslint": "workspace:*",
|
||||||
"@repo/core-typescript": "workspace:*",
|
"@repo/core-typescript": "workspace:*",
|
||||||
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"typescript": "^5.8.0",
|
"typescript": "^5.8.0",
|
||||||
"vitest": "^3.1.0"
|
"vitest": "^3.1.0"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user