Chore(test): hoist the shared vitest alias map into one constant - #434
Open
AmaadMartin wants to merge 1 commit into
Open
Chore(test): hoist the shared vitest alias map into one constant#434AmaadMartin wants to merge 1 commit into
AmaadMartin wants to merge 1 commit into
Conversation
The six test projects in vitest.config.ts each declared a byte-identical
two-entry alias object. Adding a workspace package meant editing six places,
and wiring it into five of six fails silently: the sixth project resolves the
specifier through node_modules to built output instead of source.
Define the map once at module scope and reference it with the ES shorthand
`alias,` from every project. The resolved configuration is unchanged.
`@google/adk-devtools` stays unaliased, and the constant's doc comment says
why: AdkApiServer serves the web UI from a path relative to dist/{esm,cjs}/
server, so resolving it from dev/src makes GET /dev-ui/ return 404.
Owner
Author
|
Measured result for the fixture suite referenced in the testing plan (item 5), run locally on the pushed commit: Every fixture still resolves |
This was referenced Aug 1, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
No issue; internal maintenance refactor of
vitest.config.ts.Problem:
vitest.config.tsdeclares six test projects (unit:core,unit:dev,unit:integrations,integration,e2e,cross-language) and each one repeats a byte-identical two-entryaliasobject (vitest.config.ts:38-44, 52-58, 66-72, 82-88, 96-102, 110-116before this change;grep -c "'@google/adk': path.resolve" vitest.config.tsreturned6). There is no per-project variation. Adding a fourth workspace package means editing six places, and wiring it into five of six is a silent failure: the sixth project resolves the specifier through the npm-workspace symlink innode_modulesto built output instead of source, and nothing in CI notices.Solution: Define the map once at module scope and reference it from every project with the ES shorthand
alias,. The namealias(rather thanSHARED_ALIAS) is what makes the shorthand possible; the two existing module-scope constants in this file areSCREAMING_SNAKEbecause they are bare numeric literals whose meaning is not otherwise apparent, whereas here the property name carries the meaning. The file goes from 141 to 121 lines and the resolved configuration is unchanged — proven by equivalence, see below. No type annotation orsatisfiesclause is added: the inferred{'@google/adk': string; '@google/adk-integrations': string}is already assignable to Vitest'sAliasOptions, andtsc --noEmitverifies it.@google/adk-devtoolsis deliberately not added to the map, and the constant's doc comment records why so the omission is not "fixed" later.dev/src/server/adk_api_server.ts:208serves the web UI withexpress.static(path.join(__dirname, '../../browser')), a path calibrated to the built layout (dev/dist/{esm,cjs}/server→dev/dist/browser, populated byensureBrowserAssets()indev/build.js:90). Under adev/srcalias, vite-node supplies__dirname = <repo>/dev/src/server,../../browserresolves to the nonexistent<repo>/dev/browser,express.staticcallsnext(), andGET /dev-ui/404s. This is measured, not argued — see Mutation C below.tests/integration/adk_web/webui_test.tsis also adescribe.eachover two server implementations, the other of which spawnsnode <repo>/dev/dist/esm/cli_entrypoint.jsas a child process (tests/integration/test_api_server.ts:59-62), which no vitest alias can reach. Tests that want dev sources import them relatively, astest_api_server.ts:9andtests/integration/app_loader/app_loader_test.ts:13do.Scope: exactly one file,
vitest.config.ts. No source, no tests, no lockfile, no CHANGELOG.Overlap check (open PRs on this fork, run before writing any code):
gh pr list --state open --limit 100surfaced #380 (fix/vitest-alias-exact-match), which touches the same six hunks of this file — it hoists the map into an exportedworkspaceAliasesand converts the entries from plain strings to anchoredRegExpfinds so deep specifiers such as@google/adk/sessions/session.jsstop resolving, which also requires editing two test files and adding a third. That is a behavioural change to specifier matching; this PR is a pure refactor whose resolved config is provably identical, touching one file. The two are alternatives for the same lines, not stackable (stacking would leave this PR with an empty diff), so this one branches frommain. Whichever merges first makes the other a trivial rebase-or-close; reviewers should pick one. Othervitest.config.tsPRs open at the time of writing (#362 coverageinclude, #349 worker log level, #377 coverage-drift, #405 hook timeouts) touch disjoint keys and only conflict textually.Testing Plan
Please describe the tests that you ran to verify your changes. This is required for all PRs that are not small documentation or typo fixes.
Unit Tests:
[x] I have added or updated unit tests for my change.
No test is added, deliberately. This change adds zero lines of product code, and
vitest.config.tsis not in the coverage denominator (coverage.includeiscore/src/**,dev/src/**,integrations/src/**), so the existing thresholds are untouched. A test asserting that a build-config file contains a particular constant would test the diff, not the behaviour. The substitute is an equivalence proof plus mutation testing, below.[x] All unit tests pass locally.
1. Discovery equivalence — all six projects, before vs. after.
Run on the change, then again with the change stashed. Both emit 2707 tests. Raw output order is not stable, so the sorted output is the correct comparison:
Control for that ordering claim: a second
vitest liston the identical post-change tree differs from the first by 734 raw lines while hashing to the same6123c037…. So the raw-order churn is vitest's parallel collection order, not this change. Collection loads every matched test file, so an identical set across all six projects proves each project still exists, still has itsincludeglob, and still resolves every import in every collected file.2. Targeted runs.
npx vitest run --project unit:dev(exercises@google/adk)npx vitest run --project unit:integrations(the only consumer of@google/adk-integrations)npx vitest run --project integration tests/integration/adk_web/webui_test.tsnpx vitest run --project integration tests/integration/app_loader/app_loader_test.tsBoth failures reproduce identically on the unmodified baseline (verified by
git stash, re-running,git stash pop), so neither is caused by this change:dev/test/cli/cli_create_test.ts > … > should handle Vertex AI selection with gcloud defaults—AssertionError: expected "spy" to be called with arguments, environment-dependent (reads local gcloud defaults).integrations/test/version_test.ts > version > should return the correct version—AssertionError: expected '1.5.0' to be '1.3.0', a stale hard-coded version pin againstintegrations/package.json.app_loader_test.tsfailed on its first invocation with all 6 tests skipped: itsbeforeAllrunsnpm installin each fixture under a 40s per-hook budget (app_loader_test.ts:31) and the cold install exceeded it. The warm rerun passed 6/6. Unrelated to this change (no alias is involved in a hook that shells out).3. Static gates.
npx prettier vitest.config.ts --check→ clean. Hoisting removed four levels of indentation, so the@google/adk-integrationsentry now fits on one line and prettier collapses the previously-wrappedpath.resolve(...); that collapse is expected, not an accidental edit.quoteProps: 'preserve'keeps the quotes on the keys.npx eslint vitest.config.ts→ clean.npm run ts:check→ the repo-wide run is red onmaintoday (281 pre-existing errors in test files). The error list is byte-identical before and after this change (diffof the two sorted error sets is empty) and none of the 281 is invitest.config.ts, so the new constant type-checks.git diff main -U0 | grep -E '@ts-expect-error|@ts-ignore|eslint-disable|as any|as never|: any'→ no hits. Noany, no casts, noconsole.log.4. Mutation testing — proof the verification above can actually fail.
Since there is no new test, the thing that must be shown to have signal is the equivalence check and the claim that all six projects consume the one constant.
Mutation A — delete the
'@google/adk-integrations'entry from the constant.unit:integrationsstill passed (its lone test then resolves through the workspace symlink tointegrations/dist, which exists afternpm run build). This mutation is reported because it did NOT produce a failure: it is exactly the silent-fallback failure mode this refactor exists to prevent, and it shows why a pass/fail suite alone is not sufficient evidence here.Mutation B (the load-bearing one) — repoint the single constant at nonexistent roots (
./core/src_MUTANT,./integrations/src_MUTANT) and runvitest listper project. All six projects failed collection, which is the property the refactor must preserve (the pre-change hazard is a package wired into five of six):Mutation C — add the
'@google/adk-devtools': path.resolve(__dirname, './dev/src')entry that this change deliberately omits, and run the web UI test:Exactly the predicted 404. The CLI-spawning case still passes because it never touches the alias. This is why the doc comment on the constant exists.
vitest.config.tswas restored from a byte-checked backup after each mutation (md5sumverified) and the gates re-run before committing.5. Fixture suite (
tests/integration/build_setup/build_setup_test.ts). Vitest aliases cannot affect it by construction: every fixture is reached through a child process (execAsync('npm install'),npm run build,spawn('npm', ['run','start']),npx @google/adk-devtools --version), and module resolution does not cross a process boundary. The fixtures' owndevtools_check.ts/verify_devtools.tsdo not match**/*_test.ts, so vitest never loads them; each fixture resolves"@google/adk-devtools": "file:../../../../dev"against its own manifest and consumes the built package, which is the point of those fixtures. Its measured result in this environment is recorded in the final comment on this PR.Manual End-to-End (E2E) Tests:
Checklist
[x] I have read the CONTRIBUTING.md document.
[x] I have performed a self-review of my own code.
[x] I have commented my code, particularly in hard-to-understand areas.
[x] I have added tests that prove my fix is effective or that my feature works.
[x] New and existing unit tests pass locally with my changes.