Vitest 5.0 was released on September 3, 2026, and it's one of the more substantial updates to the test runner so far. The headline is speed (the team reports up to 53% faster runs on dependency-heavy apps), but the release also tightens several defaults that will surface hidden problems in existing test suites. This post walks through the most useful new features and a practical upgrade path for a typical React or Next.js project.
Before You Upgrade: Minimum Versions
Vitest 5 requires:
- Node.js 22.12.0 or newer
- Vite 6.4.0 or newer
Check both first, since an older Node in CI is the most common reason an upgrade "works locally" and then fails:
node --version
npm ls vite
npm install -D vitest@5
If you use @vitest/ui, @vitest/coverage-v8 or @vitest/browser, upgrade them in the same step so all @vitest/* packages stay on matching versions.
New Features Worth Adopting
vi.when: Per-Argument Mock Behavior
Mocks that return different values depending on their arguments used to need a hand-written mockImplementation with if branches. The new vi.when API makes that declarative:
import { vi, test, expect } from 'vitest'
import { findById } from './users'
vi.mock('./users')
test('returns the user or rejects', async () => {
vi.when(findById)
.calledWith(1)
.thenResolve({ id: 1, name: 'Ella' })
.calledWith(expect.any(Number))
.thenReject(new Error('not found'))
await expect(findById(1)).resolves.toEqual({ id: 1, name: 'Ella' })
await expect(findById(2)).rejects.toThrow('not found')
})
The more specific match is listed first, and asymmetric matchers like expect.any() work as fallbacks.
Projects Inherit the Root Config
In Vitest 5, projects inherit the root configuration by default. You no longer need extends: true on each one, and project config files can declare their own nested projects:
// vitest.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
projects: [
{ test: { name: 'unit', environment: 'node', include: ['src/**/*.test.ts'] } },
{ test: { name: 'dom', environment: 'jsdom', include: ['src/**/*.test.tsx'] } },
],
},
})
Run a single project with the new -p shorthand:
npx vitest run -p dom
Trace View for Browser Mode
Browser Mode can now record interactions and assertions as DOM snapshots and replay them step by step afterwards, in the browser UI, Vitest UI or the HTML reporter. Enable it with browser.traceView: true. It's a big help when a component test fails only in CI.
Hunting Flaky Tests
The new --repeats CLI option reruns tests to surface intermittent failures, and fake timers now mock the Temporal API alongside Date.
Breaking Changes That Will Bite
clearMocks Is Now true by Default
Mock call history is cleared before each test (implementations are kept). Tests that accidentally depended on calls recorded in a previous test will now fail, which is usually a real bug in test isolation. Fix the test rather than setting clearMocks: false globally.
Unawaited Async Assertions Fail
This was a silent source of false positives. A missing await now fails the test:
// Before: could pass silently even if the promise rejected
expect(fetchUser(1)).resolves.toMatchObject({ id: 1 })
// Vitest 5: the assertion must be awaited
await expect(fetchUser(1)).resolves.toMatchObject({ id: 1 })
The same applies to rejects and toMatchFileSnapshot. expect.poll also fails when its callback doesn't resolve in time.
Stricter Text and Locator Matching
toHaveTextContent is now strict; use the new toMatchTextContent for partial matches. In Browser Mode, locators.exact is on by default, so locators no longer match partial text by accident.
Removed and Moved Options
- The
sequentialtest and suite options are removed in favor ofconcurrent. - Config files are no longer looked up in ancestor directories, so monorepo packages need their own config or an explicit
--config. - Reporter output (HTML, JSON, JUnit, blob) and attachments now go to a single
.vitestdirectory by default. - The
benchAPI was rewritten: benchmarks now use abenchfixture insidetest(). - The
webdriveriopackage is removed from Browser Mode.
Add the new output directory to .gitignore:
echo ".vitest/" >> .gitignore
A Safe Upgrade Workflow
- Upgrade Node in CI to 22.12 or newer.
- Bump
vitestand all@vitest/*packages together. - Run the suite and fix unawaited assertions first; they point to real gaps.
- Fix isolation failures from
clearMocksinstead of disabling it. - Update CI artifact paths to the
.vitestdirectory. - Read the official migration guide for anything specific to your setup.
Key Takeaways
- Vitest 5.0 (September 3, 2026) needs Node.js 22.12+ and Vite 6.4+.
vi.whenmakes argument-specific mocking declarative.- Projects inherit root config by default; use
-pto run one project. clearMocksdefaults totrue, and unawaited async assertions now fail.- Reports and attachments move into a single
.vitestdirectory.
