Files
agent-skills/skills/vue-testing-best-practices/reference/testing-vitest-recommended-for-vue.md
Jason Woltje f5792c40be feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:27:42 -06:00

4.9 KiB

title, impact, impactDescription, type, tags
title impact impactDescription type tags
Use Vitest for Vue 3 Testing - Recommended by Vue Team MEDIUM Using Jest or other runners with Vite projects requires complex configuration and causes slower test runs best-practice
vue3
testing
vitest
vite
configuration
setup

Use Vitest for Vue 3 Testing - Recommended by Vue Team

Impact: MEDIUM - Vitest is created and maintained by Vue/Vite team members and shares the same configuration and transform pipeline as Vite. Using Jest or other test runners with Vite-based projects requires additional configuration and can result in slower test execution and compatibility issues.

Use Vitest for new Vue 3 projects. Only consider Jest if migrating an existing test suite.

Task Checklist

  • Install Vitest and related packages for Vue testing
  • Configure vitest in vite.config.js or vitest.config.js
  • Set up proper test environment (happy-dom or jsdom)
  • Add test scripts to package.json
  • Configure globals if desired for cleaner test syntax
  • Use @vue/test-utils for component mounting

Quick Setup

# Install required packages
npm install -D vitest @vue/test-utils happy-dom
# or with jsdom
npm install -D vitest @vue/test-utils jsdom

vite.config.js:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  test: {
    // Enable global test APIs (describe, it, expect)
    globals: true,
    // Use happy-dom for faster tests (or 'jsdom' for better compatibility)
    environment: 'happy-dom',
    // Optional: Setup files for global configuration
    setupFiles: ['./src/test/setup.js']
  }
})

package.json:

{
  "scripts": {
    "test": "vitest",
    "test:run": "vitest run",
    "test:coverage": "vitest run --coverage"
  }
}

tsconfig.json (if using TypeScript):

{
  "compilerOptions": {
    "types": ["vitest/globals"]
  }
}

Test File Example

// src/components/Counter.test.js
import { describe, it, expect, beforeEach } from 'vitest'  // optional with globals: true
import { mount } from '@vue/test-utils'
import Counter from './Counter.vue'

describe('Counter', () => {
  let wrapper

  beforeEach(() => {
    wrapper = mount(Counter)
  })

  it('renders initial count', () => {
    expect(wrapper.find('[data-testid="count"]').text()).toBe('0')
  })

  it('increments when button clicked', async () => {
    await wrapper.find('[data-testid="increment"]').trigger('click')
    expect(wrapper.find('[data-testid="count"]').text()).toBe('1')
  })
})

Vitest vs Jest Comparison

Feature Vitest Jest
Vite Integration Native Requires config
Speed Very fast (ESM native) Slower with Vite
Watch Mode Excellent Good
Vue SFC Support Works with Vite Needs vue-jest
Config Sharing Same as vite.config Separate
API Jest-compatible Standard

Using with Testing Library

npm install -D @testing-library/vue @testing-library/jest-dom
// src/test/setup.js
import { expect } from 'vitest'
import * as matchers from '@testing-library/jest-dom/matchers'

expect.extend(matchers)
// Component.test.js
import { render, screen, fireEvent } from '@testing-library/vue'
import UserCard from './UserCard.vue'

test('displays user name', () => {
  render(UserCard, {
    props: { name: 'John Doe' }
  })

  expect(screen.getByText('John Doe')).toBeInTheDocument()
})

Advanced Configuration

// vitest.config.js (separate file if preferred)
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  test: {
    globals: true,
    environment: 'happy-dom',
    include: ['**/*.{test,spec}.{js,ts,jsx,tsx}'],
    exclude: ['node_modules', 'dist', 'e2e'],
    coverage: {
      provider: 'v8',
      reporter: ['text', 'json', 'html'],
      exclude: ['node_modules', 'test']
    },
    // Helpful for debugging
    reporters: ['verbose'],
    // Run tests in sequence in CI
    poolOptions: {
      threads: {
        singleThread: process.env.CI === 'true'
      }
    }
  }
})

Common Patterns

Mocking Modules

import { vi } from 'vitest'

vi.mock('@/api/users', () => ({
  fetchUser: vi.fn().mockResolvedValue({ name: 'John' })
}))

Testing with Fake Timers

import { vi, beforeEach, afterEach } from 'vitest'

beforeEach(() => {
  vi.useFakeTimers()
})

afterEach(() => {
  vi.restoreAllMocks()
})

test('debounced search', async () => {
  const wrapper = mount(SearchBox)
  await wrapper.find('input').setValue('vue')

  vi.advanceTimersByTime(300)
  await flushPromises()

  expect(wrapper.emitted('search')).toBeTruthy()
})

Reference