Skip to main content
skill CX Codex

vitest-testing · existential-birds — Claude Code skill: Vitest patterns

A skill that hands your coding agent a Vitest reference: assertions, mocks, async matchers, config. Useful when the project already runs on Vitest.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add existential-birds/beagle --skill vitest-testing -a claude-code
Open on GitHub

What vitest-testing does

The skill gives the agent a working reference for Vitest. Assertions are grouped by what you check: equality with toBe, toEqual and toStrictEqual, numbers with toBeCloseTo, strings and arrays with toMatch, toContain and toHaveLength, objects with toHaveProperty and toMatchObject, exceptions with toThrow.

Async gets its own section. The rule there is blunt: expect(...).resolves and expect(...).rejects always need await, otherwise the test passes for the wrong reason. Mocks are covered through vi.fn() and vi.mock — return values, mockResolvedValue, call assertions — with vi.clearAllMocks() in beforeEach as the cleanup habit. Test methods it.todo, it.skip, it.only, .concurrent and .each([...]) are listed in a table.

There is a verification sequence for when you add or change tests. First run the same command CI runs — check the package.json scripts, often vitest run — and confirm exit code 0 with no failures. Then scan every resolves and rejects line for a missing await. Three files under references/ go further: mocking, config, and patterns covering timers and snapshots. The advice assumes Vitest; swap in another runner and the guidance stops matching your setup.

What it helps with

  • write a unit test for a function that awaits a network call
  • set up vitest.config and setup files
  • mock a module with vi.mock and assert on its calls
  • catch a test that passes falsely because await is missing
  • run the same case against several inputs with .each([...])

Example prompts for the agent

  • write Vitest tests for this module and mock fetchData with vi.mock
  • check my tests: does every expect(...).resolves and rejects have await?
  • add a parameterized test with it.each for these three cases

How to install vitest-testing

1Skills CLI (Vercel)

npx skills add existential-birds/beagle --skill vitest-testing -a claude-code

2Manually: put the files in place

~/.claude/skills/vitest-testing/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/vitest-testing/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about vitest-testing

How do I install vitest-testing in Claude?

Run npx skills add existential-birds/beagle --skill vitest-testing -a claude-code. The skill file lands at ~/.claude/skills/vitest-testing/SKILL.md.

What does vitest-testing do?

It feeds the agent a Vitest reference: assertions, async matchers, mocks via vi.fn and vi.mock, the it.skip and it.todo methods, plus a pass/fail checklist to run before committing tests.

What does the skill need to work?

A project running Vitest, since the test command comes from your package.json scripts. Under a different runner the guidance will not match.

Source text

SKILL.md · Apache-2.0
---
name: vitest-testing
description: Vitest testing framework patterns and best practices. Use when writing unit tests, integration tests, configuring vitest.config, mocking with vi.mock/vi.fn, using snapshots, or setting up test coverage. Triggers on describe, it, expect, vi.mock, vi.fn, beforeEach, afterEach, vitest.
---

# Vitest Best Practices

## Quick Reference

```ts
import { describe, it, expect, beforeEach, vi } from 'vitest'

describe('feature name', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('should do something specific', () => {
    expect(actual).toBe(expected)
  })

  it.todo('planned test')
  it.skip('temporarily disabled')
  it.only('run only this during dev')
})
```

## Common Assertions

```ts
// Equality
expect(value).toBe(42)                    // Strict (===)
expect(obj).toEqual({ a: 1 })             // Deep equality
expect(obj).toStrictEqual({ a: 1 })       // Strict deep (checks types)

// Truthiness
expect(value).toBeTruthy()
expect(value).toBeFalsy()
expect(value).toBeNull()
expect(value).toBeUndefined()

// Numbers
expect(0.1 + 0.2).toBeCloseTo(0.3)
expect(value).toBeGreaterThan(5)

// Strings/Arrays
expect(str).toMatch(/pattern/)
expect(str).toContain('substring')
expect(array).toContain(item)
expect(array).toHaveLength(3)

// Objects
expect(obj).toHaveProperty('key')
expect(obj).toHaveProperty('nested.key', 'value')
expect(obj).toMatchObject({ subset: 'of properties' })

// Exceptions
expect(() => fn()).toThrow()
expect(() => fn()).toThrow('error message')
expect(() => fn()).toThrow(/pattern/)
```

## Async Testing

```ts
// Async/await (preferred)
it('fetches data', async () => {
  const data = await fetchData()
  expect(data).toEqual({ id: 1 })
})

// Promise matchers - ALWAYS await these
await expect(fetchData()).resolves.toEqual({ id: 1 })
await expect(fetchData()).rejects.toThrow('Error')

// Wrong - creates false positive
expect(promise).resolves.toBe(value)  // Missing await!
```

## Quick Mock Reference

```ts
const mockFn = vi.fn()
mockFn.mockReturnValue(42)
mockFn.mockResolvedValue({ data: 'value' })

expect(mockFn).toHaveBeenCalled()
expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2')
expect(mockFn).toHaveBeenCalledTimes(2)
```

## Verification gates

Use this sequence when you add or change tests; each step has an objective pass condition.

1. **Run the test suite** — From the package or workspace root, run the same command CI uses (check `package.json` scripts; often `vitest run`, `pnpm test`, or `npm test`). **Pass:** exit code is 0 and the report shows zero failing tests.
2. **Async matchers** — **Pass:** every `expect(…).resolves` and `expect(…).rejects` is prefixed with `await` (`await expect(...)`), as in [Async Testing](#async-testing). A line where `resolves` or `rejects` appears without `await` fails this gate.

## Additional Documentation

- **Mocking**: See [references/mocking.md](references/mocking.md) for module mocking, spying, cleanup
- **Configuration**: See [references/config.md](references/config.md) for vitest.config, setup files, coverage
- **Patterns**: See [references/patterns.md](references/patterns.md) for timers, snapshots, anti-patterns

## Test Methods Quick Reference

| Method | Purpose |
|--------|---------|
| `it()` / `test()` | Define test |
| `describe()` | Group tests |
| `beforeEach()` / `afterEach()` | Per-test hooks |
| `beforeAll()` / `afterAll()` | Per-suite hooks |
| `.skip` | Skip test/suite |
| `.only` | Run only this |
| `.todo` | Placeholder |
| `.concurrent` | Parallel execution |
| `.each([...])` | Parameterized tests |

© existential-birds · Apache-2.0 · existential-birds/beagle

Similar skills

All skills for Testing and QA →

vitest-testing by other authors comes first.

From the same set9

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor