fix(coverage): exempt .d.ts files from diff coverage gate

Ambient declaration files have no runtime code so v8 coverage
never generates DA records for them. Without an allowlist entry,
coverage:diff reports no-coverage-data for every .d.ts in the
diff. Add /\.d\.ts$/ to ALLOWED_GLOBS with a companion test.

Also configure @vitest/coverage-v8 for core-shared and add
targeted vitest exclusions for infrastructure files that are not
unit-testable (DI symbols, interface files, tRPC context, Sentry
SDK init) — bringing core-shared into the L2 aggregate and making
the L1 diff gate enforce coverage on new executable code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-18 18:26:50 +00:00
parent a94e8032b5
commit 0d4be0a4f4
4 changed files with 32 additions and 16 deletions

View File

@@ -1,18 +1,18 @@
{ {
"generatedAt": "2026-05-18T18:22:54.558Z", "generatedAt": "2026-05-18T18:25:58.074Z",
"commit": "c298f39", "commit": "a94e803",
"repo": { "repo": {
"statements": 96.34, "statements": 96.34,
"branches": 91.4, "branches": 91.41,
"functions": 96.75, "functions": 96.76,
"lines": 96.34, "lines": 96.34,
"counts": { "counts": {
"lf": 4100, "lf": 4100,
"lh": 3950, "lh": 3950,
"brf": 767, "brf": 768,
"brh": 701, "brh": 702,
"fnf": 246, "fnf": 247,
"fnh": 238 "fnh": 239
} }
}, },
"byPackage": { "byPackage": {
@@ -60,16 +60,16 @@
}, },
"@repo/core-shared": { "@repo/core-shared": {
"statements": 97.75, "statements": 97.75,
"branches": 95.52, "branches": 95.54,
"functions": 91.49, "functions": 91.58,
"lines": 97.75, "lines": 97.75,
"counts": { "counts": {
"lf": 935, "lf": 935,
"lh": 914, "lh": 914,
"brf": 268, "brf": 269,
"brh": 256, "brh": 257,
"fnf": 94, "fnf": 95,
"fnh": 86 "fnh": 87
} }
}, },
"@repo/marketing-pages": { "@repo/marketing-pages": {

View File

@@ -16,8 +16,6 @@ export default mergeConfig(nodeVitestConfig, {
"src/trpc/context.ts", "src/trpc/context.ts",
// Sentry client init — browser/node SDK init, tested in apps // Sentry client init — browser/node SDK init, tested in apps
"src/instrumentation/sentry/**", "src/instrumentation/sentry/**",
// Pure type-alias file — no executable code
"src/payload/retention-types.ts",
], ],
}, },
}, },

View File

@@ -62,6 +62,7 @@ const ALLOWED_GLOBS = [
/\/integrations\/cms\//, /\/integrations\/cms\//,
/\/ui\//, /\/ui\//,
// Pure type-alias / interface files (no executable code) // Pure type-alias / interface files (no executable code)
/\.d\.ts$/, // ambient declaration files — no runtime code by definition
/\.interface\.ts$/, /\.interface\.ts$/,
/\/index\.ts$/, // barrel re-exports — no executable code /\/index\.ts$/, // barrel re-exports — no executable code
// Build artifacts // Build artifacts

View File

@@ -154,6 +154,23 @@ describe("computeDiffCoverage", () => {
assert.equal(result.summary.filesChanged, 4); assert.equal(result.summary.filesChanged, 4);
}); });
test("skips TypeScript ambient declaration files (.d.ts)", () => {
const lcov = parseLcov(lcovText);
const diff = new Map([
// Ambient declaration files have no runtime code — v8 coverage never
// sees them, so they must be exempted from the no-coverage-data gate.
[
"packages/core-shared/src/payload/payload-custom-ambient.d.ts",
new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
],
["packages/foo/src/bar/some-types.d.ts", new Set([1, 2])],
]);
const result = computeDiffCoverage(diff, lcov);
assert.equal(result.status, "pass");
assert.equal(result.summary.filesGated, 0);
assert.equal(result.summary.filesChanged, 2);
});
test("skips .env template files (.env, .env.example, .env.local)", () => { test("skips .env template files (.env, .env.example, .env.local)", () => {
const lcov = parseLcov(lcovText); const lcov = parseLcov(lcovText);
const diff = new Map([ const diff = new Map([