---
name: write-unit-tests-with-vitest
description: Writes fast JavaScript and TypeScript unit tests with Vitest - set it up, test pure functions and async code, mock modules and timers sparingly, and test React or Vue components with Testing Library. Use when the user wants JavaScript tests, to set up Vitest or migrate from Jest, or to test a component or function.
license: MIT
compatibility: Needs Node 18+
metadata:
  category: debugging
  tags: "testing,typescript,react"
  author: johnny-bravo
  version: "1.0"
  updated: "2026-11-02"
  status: published
  aliases: "vitest, jest, javascript unit tests, testing library"
  source_url: "https://github.com/wshobson/agents/tree/7e2fb559cf4b824b27f1fec49fe88f7511066d26/plugins/javascript-typescript/skills/javascript-testing-patterns"
  source_license: MIT
  copyright: "Copyright (c) 2024 Seth Hobson"
  original_author: "Seth Hobson (wshobson/agents, javascript-testing-patterns)"
  modified: "Adapted by TheSkillVault: narrowed to Vitest with a Jest note, rewritten as beginner steps with original examples; dropped the long Jest config and class examples; added gotchas and done-when."
  imported_on: "2026-11-02"
---

# Write unit tests with Vitest

Vitest runs tests fast and reads your Vite config. Its API matches Jest, so most Jest knowledge carries over.

## When to use
- Your JavaScript or TypeScript code has no tests.
- You want to test a React, Vue or Svelte component.
- You are moving from Jest to something faster.

## Steps
1. Install: `npm i -D vitest` (add `@testing-library/react` and `jsdom` for components).
2. Add `"test": "vitest"` to package.json scripts. For components, set `test.environment = "jsdom"` in `vitest.config.ts`.
3. Put tests next to code as `thing.test.ts`.
4. Start with pure functions: given an input, expect an output.
5. For async code, `await` the call and use `expect(...).rejects` for errors.
6. Mock only edges: `vi.mock("./api")` for network modules, `vi.useFakeTimers()` for time.
7. For components, render and act like a user: find by role or label, click, then assert what shows.
8. Run `npx vitest run --coverage` to see gaps, then add tests for risky branches.
9. Run `vitest run` in CI.

```ts
import { describe, it, expect } from "vitest";
import { slugify } from "./slugify";

describe("slugify", () => {
  it("lowercases and joins words", () => expect(slugify("Hello World")).toBe("hello-world"));
  it("drops symbols", () => expect(slugify("Hi! There?")).toBe("hi-there"));
});
```

## Gotchas
- Testing implementation details (state names, private functions) breaks on every refactor. Test what users see.
- Reset mocks between tests (`vi.restoreAllMocks()`) or one test leaks into the next.
- Keep real API keys and tokens out of test files and snapshots. Use fake values.
- Huge snapshots hide real changes. Prefer small, specific assertions.

## Portability
Works with any Vite, Next.js, Nuxt or Node project. If you use Jest, the same tests run with small import changes; swap `vi` for `jest` instead.

## Example prompt
"Set up Vitest in my React app and write tests for the cart total function and the Add to cart button."

## Done when
- `npm test` passes locally and in CI.
- Key functions and components have tests for normal and error cases.
- Mocks are reset between tests and no real secrets appear in tests.

---
Adapted from "javascript-testing-patterns" in wshobson/agents (MIT, Copyright (c) 2024 Seth Hobson). See LICENSE.txt.
