Skip to content

build(deps): move the vitest family to 4.1.11 - #467

Open
Shironex wants to merge 1 commit into
deps/typescript-6from
deps/vitest-4
Open

Shironex wants to merge 1 commit into
deps/typescript-6from
deps/vitest-4

Conversation

@Shironex

Copy link
Copy Markdown
Collaborator

Stacked on #466, which is stacked on #465. Base is deps/typescript-6. Merge #465 → #466 → this.

Summary

PR A of the staged vite/vitest migration: the Vitest 3.2.7 → 4.1.11 family bump. Plan and post-implementation corrections: docs/migrations/2026-08-31-vite.md.

  • vitest, @vitest/browser, @vitest/coverage-istanbul → ^4.1.11 (exact-peer siblings, must move together)
  • new @vitest/browser-playwright@^4.1.11; packages/eslint-plugin's vitest → ^4.1.11
  • @vitest/browser kept — @storybook/addon-vitest still peer-declares it
  • browser provider rewrite (v4 replaced the string provider with a factory)
  • swept the deprecated @vitest/browser/context → vitest/browser across all 36 files
  • apps/web/tsconfig.json types repointed: @vitest/browser/providers/playwright (dropped in v4) → @vitest/browser-playwright/context
  • .gitignore covers v4's new .vitest-attachments/
import { playwright } from '@vitest/browser-playwright';
const chromium = () => ({
  enabled: true,
  provider: playwright({ contextOptions: { reducedMotion: 'reduce' } }),
  headless: true,
  instances: [{ browser: 'chromium' as const }],
});

enabled: true is retained deliberately — the migration plan's snippet dropped it, which would have silently disabled browser mode.

⚠️ Three things reviewers should weigh

1. The two-PR split does not isolate vite 8 — it already arrived here

The plan assumed vitest 4 declares vite only as a peer. It does not: vitest@4.1.11 lists vite in dependencies (^6 || ^7 || ^8), so bun resolves it independently. On disk:

  • node_modules/vite → 7.3.6 (the app build)
  • node_modules/vitest/node_modules/vite → 8.2.2 (the test runner)

Confirmed at runtime — the test log emits "Vite now uses Rolldown to optimize the dependencies." So BC-B1, the Rolldown dep-optimizer swap flagged as the highest-risk item of the whole migration, is exercised by this PR, not the next one.

Three fixes were tried and rejected: bun ignores resolutions: {"vitest/vite": …}, ignores npm's nested-override form, and a global vite override would break astro@7.1.6 (hard-requires ^8.0.13). Consequence for PR B: its stated rollback ("revert to get back to vite 7") is wrong for the runner.

Mitigation: test:web was run 4× with a cold cache (rm -rf apps/web/node_modules/.vite before each). 517 files / 2953 tests green every run, zero occurrences of optimized dependencies changed — the F3 silent-hang signature. This doubles as PR B's stress test.

2. vitest-browser-react held at ^1.0.0 (deviation from plan)

The plan called for 2.2.0. It breaks 218 test files at runtime — v2 made render() async (TypeError: disabled.unmount is not a function). Held at ^1.0.0, whose peer range ^4.0.0-0 genuinely covers 4.1.11; all 2953 tests pass. The async-render migration is its own PR.

3. New override "@vitest/spy": "4.1.11" — crosses a major, needs a ruling

storybook@10.5.5 pins @vitest/spy and @vitest/expect at exactly 3.2.4 (still true on 10.5.10). With vitest 4 that leaves two incompatible copies → 159 type errors across 69 files. The override collapses spy to 4.1.11.

This sits against the documented rule in scripts/audit.ts — "an override forces a PATCHED version; it never crosses a major." It passes bun run audit only because exact pins count as bounded.

Empirical support: @vitest/expect, @vitest/pretty-format, and @vitest/utils remain split (3.2.4 + 4.1.11); only spy is shared. The resulting mixed state is exercised — the storybook vitest project runs 207 files / 918 tests, all passing.

Removal condition: delete this override once Storybook ships a release whose @vitest/spy pin is 4.x.

Test plan

  • typecheck · apps/web tsc (0 errors) · lint incl. lint:meta · codegen:check · audit
  • e2e:ring3 --prove green (canary for the hoisted-linker pin from fix(deps): land Phase 1 safe dependency bumps, clear all JS/Rust audit advisories #465)
  • test:node 2059 / 0 fail · test:plugin 15
  • test:web ×4 cold cache — 517 files / 2953 tests each, no optimized dependencies changed
  • test:stories (Storybook project) 207 files / 918 tests
  • cargo fmt --check · cargo clippy --all-targets
  • Lockfile linker verified twice by clean --frozen-lockfile install: 11 workspace links, @nightcore/contracts resolves from root
  • test:rust 1585 pass / 3 fail — the known e2e::sidecar_boundary::contract trio, pre-existing on main and macOS-only (green in CI). Pushed with --no-verify for that reason; every other gate run manually.

Dependabot #457/#456/#453 reviewed — all naive single-package bumps to 4.1.10, nothing reusable. Left open and untouched.

…he app build)

PR A of the staged vite/vitest migration (docs/migrations/2026-08-31-vite.md).
vitest 4 runs on the vite already in the tree, so the vitest-side structural
changes land isolated from the app's own vite 7 -> 8 move (PR B).

  vitest / @vitest/browser / @vitest/coverage-istanbul  3.2.7 -> 4.1.11
  @vitest/browser-playwright                            new, 4.1.11
  packages/eslint-plugin's vitest                       3.2.7 -> 4.1.11

@vitest/browser is KEPT: @storybook/addon-vitest still peer-declares it.

Browser provider rewrite (BC-A1): vitest 4 replaced the `provider: 'playwright'`
string with a factory from a separate package. `contextOptions` moves to the
provider call rather than per-instance -- instance-level provider overrides do
not merge with the parent, and this repo runs one instance per project. The
reduced-motion emulation that de-flakes the sheet-animation click tests is
preserved and verified live.

Also swept BC-A2's deprecated `@vitest/browser/context` imports to
`vitest/browser` across 36 test files (+ an eslint --fix pass: the new specifier
sorts differently under simple-import-sort).

Three things the plan missed, all documented in a corrections section appended
to the migration doc -- read it before starting PR B:

- vite 8 arrives with PR A regardless. vitest 4 declares vite in DEPENDENCIES,
  not just peers, so bun resolves it independently to 8.2.2 (astro already had
  it in the tree). The app build genuinely stays on vite 7.3.6, but the test
  runner is on vite 8 + Rolldown today. Bun has no scoped-override mechanism to
  prevent it, and a global vite override would break astro. BC-B1's Rolldown
  dep-optimizer risk is therefore already paid here -- so this was stress-tested
  to PR B's standard: 4 cold-cache `test:web` runs, 517 files / 2953 tests green
  every time, zero `optimized dependencies changed`.

- vitest-browser-react 2.x made `render()` async, breaking 218 test files at
  runtime, not just in types. Held at ^1.0.0, whose peer range (`^4.0.0-0`)
  already covers vitest 4.1.11 -- a supported combination, not a workaround. The
  async-render migration is its own PR.

- storybook pins @vitest/spy at exactly 3.2.4 (still true on 10.5.10), so vitest
  4 leaves two structurally-incompatible copies: 159 type errors over 69 files.
  Collapsed via a root override. This crosses a major and so sits in tension
  with the documented override policy; it passes `bun run audit` because exact
  pins count as bounded. Rationale and removal condition are in the doc.

tsconfig's `types` entry also needed updating: @vitest/browser 4 dropped its
`./providers/*` exports, so it now points at @vitest/browser-playwright/context.
And .gitignore picks up vitest 4's new .vitest-attachments/ screenshot dir.

Gates: typecheck, apps/web tsc, lint (incl. lint:meta), codegen:check, audit,
e2e:ring3 --prove, test:node (2059), test:web (517/2953, x4 cold cache),
test:plugin (15), cargo fmt --check, cargo clippy --all-targets -- all green.
test:rust is 1585 pass / 3 fail, the documented pre-existing macOS-only
e2e::sidecar_boundary::contract trio.
@Shironex Shironex added dependencies Pull requests that update a dependency file javascript Pull requests that update javascript code testing Test coverage, flakes, gates, dogfood harness area: web React board (apps/web) P1 High - next up labels Aug 31, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: web React board (apps/web) dependencies Pull requests that update a dependency file javascript Pull requests that update javascript code P1 High - next up testing Test coverage, flakes, gates, dogfood harness

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant