From b1bc5694ce4d6448550e211a85cd90048b26a284 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 13 Aug 2026 03:06:40 +0000 Subject: [PATCH] fix(test): count examples/* source in the coverage denominator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `examples` is a first-class workspace group in both workspaceSource.ts and testDiscovery.ts, and all three example packages — @workglow/cli, @workglow/eval and @workglow/web — are published with none marked private. They carry 24 test files between them. The denominator listed only packages/* and providers/*, so their source was rewritten to src, executed by their own tests, and then left out of the measurement entirely: a coverage run from examples/cli reported `All files 0%` with no file rows at all. Pins coverage.root to the config's own directory rather than making the globs absolute. coverage.root is the documented base for include/exclude, and this config is invoked from package directories too (vitest run --config ../../vitest.config.ts), where a repo-relative glob would otherwise match nothing. It also does not depend on whether vitest accepts absolute glob patterns. Excludes examples/*/src/test/**: those dirs hold the example suites plus the occasional non-`.test.` helper the filename rules cannot catch, and counting a test helper is what the adjacent excludes already exist to prevent. Guards the invariant that broke, in workspaceSource.test.ts: every entry in WORKSPACE_GROUPS must be a prefix of some coverage.include glob, read from the actual config so the two cannot drift apart again. A missing group is invisible in a coverage report — it shows a shorter file list, not an error. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01H797qbH356jjznKgUax63o --- scripts/workspaceSource.test.ts | 25 ++++++++++++++++++++++++- vitest.config.ts | 24 +++++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/scripts/workspaceSource.test.ts b/scripts/workspaceSource.test.ts index 0eeef134f..c6247915b 100644 --- a/scripts/workspaceSource.test.ts +++ b/scripts/workspaceSource.test.ts @@ -9,7 +9,7 @@ import { join } from "node:path"; import { describe, expect, it } from "vitest"; import { stubSpecsFor, type PackageManifest } from "./lib/sourceStubs"; import { ROOT } from "./lib/testDiscovery"; -import { distToSource, listWorkspacePackages } from "./lib/workspaceSource"; +import { distToSource, listWorkspacePackages, WORKSPACE_GROUPS } from "./lib/workspaceSource"; const packages = listWorkspacePackages(ROOT); @@ -61,4 +61,27 @@ describe("workspace source resolution", () => { expect(distToSource(invented)).toBeUndefined(); expect(distToSource(join(ROOT, "packages/ai/src/node.ts"))).toBeUndefined(); }); + + /** + * The invariant that actually broke: the resolver covers all three workspace + * groups, but the coverage denominator listed only two, so `examples/*` + * source was rewritten to `src`, executed by its own tests, and then left out + * of the denominator entirely. All three example packages are published and + * none is `private`, so there is no "not really shipped" argument for the + * omission — and a missing group is invisible in a coverage report, which + * shows a smaller file list rather than an error. + * + * Reads the ACTUAL config rather than re-deriving it, so the two cannot drift + * back apart. + */ + it("counts every workspace group in the coverage denominator", async () => { + const mod = (await import("../vitest.config.ts")) as { + default: { test?: { coverage?: { include?: string[] } } }; + }; + const include = mod.default.test?.coverage?.include ?? []; + const missing = WORKSPACE_GROUPS.filter( + (group) => !include.some((glob) => glob.startsWith(`${group}/`)) + ); + expect(missing).toEqual([]); + }); }); diff --git a/vitest.config.ts b/vitest.config.ts index 6769d1d4d..330a978f1 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -105,14 +105,32 @@ export default defineConfig({ coverage: { provider: "v8", // or 'istanbul' reporter: ["text", "json", "json-summary", "html"], + /** + * Base directory the globs below resolve against. Pinned rather than + * inherited: `include`/`exclude` are documented as relative to + * `coverage.root`, which otherwise follows the run's root — and this + * config is invoked from package directories too + * (`vitest run --config ../../vitest.config.ts`), where a repo-relative + * glob would match nothing. + */ + root: __dirname, /** * The denominator is every package's own `src`, stated explicitly. Left * to vitest's default (files loaded during the run), a package's score * silently omits the modules no test imports at all — the ones a coverage * report exists to surface — and its file list changes with whichever * section CI happened to run. + * + * All THREE workspace groups, matching `WORKSPACE_GROUPS`: `examples/*` + * holds published, non-private packages with tests of their own, so + * omitting it drops real source from the denominator while still counting + * the tests that cover it. */ - include: ["packages/*/src/**/*.{ts,tsx}", "providers/*/src/**/*.{ts,tsx}"], + include: [ + "packages/*/src/**/*.{ts,tsx}", + "providers/*/src/**/*.{ts,tsx}", + "examples/*/src/**/*.{ts,tsx}", + ], exclude: [ ...configDefaults.exclude, // Built output is never the unit of measure. Nothing should resolve @@ -122,6 +140,10 @@ export default defineConfig({ "**/dist/**", // The cross-package suite is the harness, not the subject. "packages/test/**", + // The examples keep their suites in `src/test`, which also holds the + // odd non-`.test.` helper (`chromeAvailability.ts`) that the filename + // rules below cannot catch. + "examples/*/src/test/**", // Tests, fixtures and testing-only helpers: counting them inflates // every package by the coverage of code that exists to be run. "**/__tests__/**",