Skip to content

chore(vitest): upgrade to Vitest 5 and share one preset across package configs - #6473

Draft
kanadgupta wants to merge 12 commits into
kanad-claude/e2e-stack-splitfrom
kanad-claude/vitest-5-preset
Draft

chore(vitest): upgrade to Vitest 5 and share one preset across package configs#6473
kanadgupta wants to merge 12 commits into
kanad-claude/e2e-stack-splitfrom
kanad-claude/vitest-5-preset

Conversation

@kanadgupta

@kanadgupta kanadgupta commented Sep 4, 2026

Copy link
Copy Markdown
Member

Note

Stacked on #6472 (PR A). The base is that branch so only PR B's changes show here; retarget to develop once A merges. Draft with run-ci so the suite runs; installs will fail with HTTP 451 from the dependency firewall until it releases the vitest@5.0.0 tarballs, which is the external blocker for this whole PR.

Summary

Second of three PRs from docs/superpowers/plans/2026-09-04-test-execution-topology.md: the Vitest 5 upgrade, its migration blockers, and one shared preset for every package config. Supersedes #6457 and #6456; their useful commits are cherry-picked here.

Vitest 5 at the root. vitest becomes a root devDependency and a root vitest.config.mts references every package config as a nested project group, so bun --bun vitest run --project '*(unit)' from the repo root runs one kind across all workspaces. Projects are named <package> (<kind>), for example supabase (e2e-stack). A root test:vitest script is a temporary entry point; PR C replaces the script layout.

Migration blockers.

  • @vitest/coverage-v8 moves to 5.x: the 4.x providers crash under Vitest 5, which breaks the --coverage.enabled CI jobs. Same-day publish, so it gets the same minimumReleaseAgeExclude entry as vitest@5.0.0.
  • Every @effect/vitest 4.0.0-rc.x pins vitest <5; it runs cleanly on Vitest 5, so a peerDependencyRules.allowedVersions entry records the override until upstream widens the range.
  • Declaring vitest at the root enabled knip's Vitest plugin for the root workspace, which followed the projects globs and re-analyzed every package's tests as root entries, misattributing release-script dependencies and failing knip:check. The root config is registered as a plain knip entry and the plugin stays off at the root.
  • .vitest/ is ignored (Vitest 5's artifact directory) and one CLI unit test resolves its fixture path from import.meta.dirname instead of process.cwd(), which differs under a root run.

One shared preset. vitest.shared.ts owns what every package config repeated: coverage, passWithNoTests, console output only from failing tests, the bun export-condition resolution for workspace packages, and the include globs per test kind. definePackageConfig merges it and testProject(kind, overrides) declares one inline project per kind, so the stack package's config is now three testProject calls. The preset knows the e2e-stack sub-kind from #6472: e2e excludes *.stack.e2e.test.ts and e2e-stack defaults to serial execution, so the CLI's split is one testProject call each. Vitest 5 inherits the declaring config into inline projects, so the resolve blocks Vitest 4 forced onto every inline project are gone. apps/cli-e2e becomes a nested e2e project so it appears as @supabase/cli-e2e (e2e) from the root; its lexicographic sequencer stays a run-level option for standalone runs.

A real bug the preset uncovered, fixed here. packages/stack exports a bun condition (src/bun.ts) and a default (src/node.ts). Its own tests never had the bun condition, so they exercised the Node implementation while the shipped CLI runs the Bun one. With the preset they switch to src/bun.ts, and the native PostgREST e2e failed on every DELETE with Bad gateway: Transport error. Cause: the API proxy forwarded every non-GET body as a stream, so a body-less DELETE from supabase-js reached PostgREST as an empty chunked body, which it drops under the Bun HTTP client. The proxy now sends an empty body when the incoming request has no transfer-encoding and no or zero content-length; a unit test asserts the upstream request is not chunked, and the native e2e passes again. This is a product fix in the gateway, hence the fix(stack) commit.

Package configs remain dual-role: the run root for pnpm test:unit inside a package, and one member of the root run's project list. Standalone per-package runs and the root run collect the same projects and test counts as #6472.

kanadgupta and others added 10 commits September 4, 2026 15:24
(cherry picked from commit cf1433f)
(cherry picked from commit eb3639b)
(cherry picked from commit 7d294eb)
(cherry picked from commit 25aa3e6)
The 4.x coverage providers crash under Vitest 5 (the istanbul variant fails
with "Expected string coverage payload, received object"), which breaks
the --coverage.enabled unit and integration CI jobs. The 5.0.0 provider
shipped the same day as vitest@5.0.0, so it needs the same
minimumReleaseAge exclusion.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every @effect/vitest 4.0.0-rc.x pins vitest <5, but it only uses the
stable entrypoint and the whole unit/integration suite passes on Vitest 5.
Record the deliberate override so installs stop warning; drop it once
upstream widens the range.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 338843b)
Declaring vitest in the root manifest enabled knip's Vitest plugin for the
root workspace. It followed the root config's projects globs and
re-analyzed every package's test files as root entries, which
misattributed the dependencies of the release scripts referenced from
GitHub workflows and failed knip:check with four unused devDependencies.
Register the root config as a plain entry instead; package-level plugins
already analyze their own configs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 5a0b26f)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 30fa169)
Every TypeScript workspace repeated the same Vitest scaffolding: istanbul
coverage, passWithNoTests, the unit/integration/e2e include globs, and, in
apps/cli and packages/config, the bun export-condition resolve blocks
copied onto every inline project because Vitest 4 did not inherit them.

vitest.shared.ts now owns that. definePackageConfig merges the shared
defaults, and testProject(kind, overrides) declares one inline project per
test kind with the file-suffix convention baked in. Vitest 5 inherits the
declaring config into inline projects, so the duplicated resolve blocks and
Dockerfile plugin entries are gone. The root config reuses the same
run-level defaults and loads each package config as a nested project group.

apps/cli-e2e also becomes a nested e2e project so it shows up as
'@supabase/cli-e2e (e2e)' from the root and matches a '*(e2e)' filter; its
lexicographic sequencer stays a run-level option for standalone runs.
Its redundant node_modules exclude is dropped in favour of Vitest's
defaults.

vite is now an explicit root devDependency because the preset imports its
default export-condition lists.

Standalone per-package runs, the CI coverage commands, and a root run all
collect the same projects and test counts as before.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Adapted while rebasing onto the e2e split: the preset's coverage provider is
v8 (develop switched from istanbul in #6470), and testProject knows the
e2e-stack sub-kind: the e2e kind excludes *.stack.e2e.test.ts and e2e-stack
defaults to serial execution, so the CLI and stack package configs express
the split as one testProject call each. runDefaults is typed with
`satisfies TestUserConfig` (folded from the follow-up commit).

(cherry picked from commit dd07660)
@kanadgupta kanadgupta added the run-ci Run full develop CI (tests + preview pkgs) on drafts and non-develop PRs. label Sep 4, 2026
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Supabase CLI preview

npx --yes https://pkg.pr.new/supabase/cli/supabase@eeff93a2eb0e82a251632db8371305fa3f2f6989

Preview package for commit eeff93a.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…a chunked body

The gateway forwarded every non-GET request body as a stream, so a DELETE
from supabase-js, which carries no body, went to PostgREST as an empty
chunked body. Under the Bun HTTP client PostgREST drops that connection,
and every native delete surfaced as "Bad gateway: Transport error".

The stack package's own e2e never saw it because, until the shared Vitest
preset added the bun export condition, its tests resolved @supabase/stack
to src/node.ts rather than the src/bun.ts the shipped CLI runs. A request
with no transfer-encoding and no (or zero) content-length is now forwarded
with an empty body; the unit test asserts the upstream request is not
chunked, and the native PostgREST e2e passes again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-ci Run full develop CI (tests + preview pkgs) on drafts and non-develop PRs.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant