diff --git a/scripts/coverage/diff.mjs b/scripts/coverage/diff.mjs index 732e472..2d9aaf7 100644 --- a/scripts/coverage/diff.mjs +++ b/scripts/coverage/diff.mjs @@ -68,6 +68,14 @@ const ALLOWED_GLOBS = [ // Tooling packages that don't generate a vitest lcov (no @vitest/coverage-v8) /^packages\/core-testing\//, /^packages\/core-eslint\//, + // App packages (web-next, web-tanstack, cms) do not configure + // @vitest/coverage-v8, so their source files never appear in the merged lcov. + /^apps\//, + // core-shared Sentry client init files — explicitly excluded from per-package + // vitest coverage in core-shared/vitest.config.ts ("Sentry client init — + // browser/node SDK init, tested in apps"); they have test files but coverage + // is excluded by design (browser SDK calls, not unit-testable in isolation). + /\/instrumentation\/sentry\//, // Pure type-alias / interface files (no executable code) /\.d\.ts$/, // ambient declaration files — no runtime code by definition /\.interface\.ts$/, diff --git a/scripts/coverage/diff.test.mjs b/scripts/coverage/diff.test.mjs index 0ca2193..534735b 100644 --- a/scripts/coverage/diff.test.mjs +++ b/scripts/coverage/diff.test.mjs @@ -243,6 +243,44 @@ describe("computeDiffCoverage", () => { assert.equal(result.summary.filesChanged, 2); }); + test("skips apps/ files (app packages don't configure @vitest/coverage-v8)", () => { + const lcov = parseLcov(lcovText); + const diff = new Map([ + // web-next and web-tanstack have no @vitest/coverage-v8 — never in lcov + ["apps/web-next/instrumentation-client.ts", new Set([1, 2, 3, 4, 5, 6])], + ["apps/web-next/middleware.ts", new Set([1, 2, 3, 4, 5])], + ["apps/web-next/src/app/layout.tsx", new Set([1, 2, 3])], + [ + "apps/web-tanstack/src/instrumentation-client.ts", + new Set([1, 2, 3, 4, 5]), + ], + ["apps/web-tanstack/app.config.ts", new Set([1, 2, 3])], + ]); + const result = computeDiffCoverage(diff, lcov); + assert.equal(result.status, "pass"); + assert.equal(result.summary.filesGated, 0); + assert.equal(result.summary.filesChanged, 5); + }); + + test("skips core-shared sentry init files (excluded from vitest coverage by design)", () => { + const lcov = parseLcov(lcovText); + const diff = new Map([ + // core-shared/vitest.config.ts excludes src/instrumentation/sentry/** + [ + "packages/core-shared/src/instrumentation/sentry/init-client.ts", + new Set([1, 2, 3, 4, 5]), + ], + [ + "packages/core-shared/src/instrumentation/sentry/init-client-react.ts", + new Set([1, 2, 3, 4, 5]), + ], + ]); + const result = computeDiffCoverage(diff, lcov); + assert.equal(result.status, "pass"); + assert.equal(result.summary.filesGated, 0); + assert.equal(result.summary.filesChanged, 2); + }); + test("end-to-end fixture: mixed pass/fail/skip/no-data", () => { const lcov = parseLcov(lcovText); const diff = parseGitDiff(diffText);