skills/oakoss/agent-skills/vitest-testing

vitest-testing

SKILL.md

Vitest Testing

Overview

Vitest is a Vite-native unit testing framework that shares the same configuration and plugin ecosystem. Built for speed with native ESM support, hot module replacement for tests, and parallel execution.

When to use: Unit tests, component tests, integration tests, hook tests, in-source tests. Testing React components with React Testing Library. Testing TanStack Query/Router/Form patterns.

When NOT to use: End-to-end testing (use Playwright), visual regression testing (use Percy/Chromatic), load testing (use k6).

Quick Reference

Pattern API Key Points
Test structure describe('suite', () => {}) Organize related tests
Single test test('behavior', () => {}) or it() Both are aliases
Parameterized tests test.each([...])('name', (arg) => {}) Run same test with different inputs
Concurrent tests test.concurrent('name', async () => {}) Run tests in parallel
Skip test test.skip('name', () => {}) or skipIf(cond) Conditionally skip tests
Only test test.only('name', () => {}) Run specific test for debugging
Assertions expect(value).toBe(expected) Compare primitive values
Deep equality expect(obj).toEqual(expected) Compare objects/arrays
Async assertions await expect(promise).resolves.toBe(value) Test promise resolution
Before each test beforeEach(() => {}) Setup before each test
After each test afterEach(() => {}) Cleanup after each test
Mock function vi.fn() Create spy function
Mock module vi.mock('./module') Replace entire module
Spy on method vi.spyOn(obj, 'method') Track calls to existing method
Clear mocks vi.clearAllMocks() Clear call history
Fake timers vi.useFakeTimers() Control setTimeout/setInterval
Render component render(<Component />) Mount React component for testing
Query by role screen.getByRole('button') Find elements by accessibility role
User interaction await user.click(element) Simulate user events
Wait for change await waitFor(() => expect(...)) Wait for async changes
Find async element await screen.findByText('text') Query + wait combined
Render hook renderHook(() => useHook()) Test custom hooks
Update hook props rerender(newProps) Re-render hook with new props
Snapshot expect(value).toMatchSnapshot() Compare against saved snapshot
Inline snapshot expect(value).toMatchInlineSnapshot() Snapshot stored in test file
CLI run once vitest run Single run, no watch
Run changed tests vitest --changed Tests affected by git changes
Filter by name vitest -t "pattern" Grep test names
Soft assertions expect.soft(value).toBe(x) Continue on failure, collect all
Poll assertions await expect.poll(() => val).toBe(x) Retry until passing
Test fixtures const test = base.extend<F>({...}) Reusable setup via test.extend
Hoisted mocks vi.hoisted(() => ({ fn: vi.fn() })) Variables for vi.mock factory
Shard tests vitest --shard 1/3 Split across CI workers
Tags test('name', { tags: ['slow'] }, ...) Filter with --tags-filter
Stub globals vi.stubGlobal('fetch', vi.fn()) Replace global objects cleanly

Common Mistakes

Mistake Correct Pattern
Using getBy for async content Use findBy or waitFor for async
Testing implementation details Test behavior and public API
Using getByTestId as first choice Prefer getByRole, getByLabelText, getByText
Missing userEvent.setup() Always call const user = userEvent.setup() first
Shared state between tests Use beforeEach to reset or create fresh instances
Not cleaning up mocks Use vi.clearAllMocks() in afterEach
Mocking too much Only mock external dependencies and APIs
Not disabling retries in tests Set retry: false for TanStack Query tests
Immediate assertions on async Use await waitFor() or findBy queries
Creating QueryClient in render Create once in wrapper or use useState
Testing library code Trust the library, test your usage
Not awaiting user events All user.* methods return promises
Using act manually userEvent and Testing Library handle this
Inline select without memoization Extract to stable function for TanStack Query
Variables in vi.mock factory Use vi.hoisted() to declare mock variables
Single expect for multiple checks Use expect.soft() to collect all failures
setTimeout in tests for async waits Use expect.poll() or vi.waitFor()
Manual beforeEach for reusable setup Use test.extend fixtures for composable setup

Delegation

  • Test discovery: For finding untested code paths, use Explore agent
  • Coverage analysis: For full coverage review, use Task agent
  • E2E testing: If playwright skill is available, delegate E2E testing to it
  • Code review: After writing tests, delegate to code-reviewer agent

References

Weekly Installs
38
GitHub Stars
4
First Seen
Feb 20, 2026
Installed on
claude-code36
opencode34
gemini-cli34
github-copilot34
amp34
codex34