Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3 testing best practices with Vitest, Vue Test Utils, component testing, mocking, and Playwright E2E.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
reference/testing-vitest-recommended-for-vue.md
1---2title: Use Vitest for Vue 3 Testing - Recommended by Vue Team3impact: MEDIUM4impactDescription: Using Jest or other runners with Vite projects requires complex configuration and causes slower test runs5type: best-practice6tags: [vue3, testing, vitest, vite, configuration, setup]7---89# Use Vitest for Vue 3 Testing - Recommended by Vue Team1011**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.1213Use Vitest for new Vue 3 projects. Only consider Jest if migrating an existing test suite.1415## Task Checklist1617- [ ] Install Vitest and related packages for Vue testing18- [ ] Configure vitest in vite.config.js or vitest.config.js19- [ ] Set up proper test environment (happy-dom or jsdom)20- [ ] Add test scripts to package.json21- [ ] Configure globals if desired for cleaner test syntax22- [ ] Use @vue/test-utils for component mounting2324## Quick Setup2526```bash27# Install required packages28npm install -D vitest @vue/test-utils happy-dom29# or with jsdom30npm install -D vitest @vue/test-utils jsdom31```3233**vite.config.js:**34```javascript35import { defineConfig } from 'vite'36import vue from '@vitejs/plugin-vue'3738export default defineConfig({39plugins: [vue()],40test: {41// Enable global test APIs (describe, it, expect)42globals: true,43// Use happy-dom for faster tests (or 'jsdom' for better compatibility)44environment: 'happy-dom',45// Optional: Setup files for global configuration46setupFiles: ['./src/test/setup.js']47}48})49```5051**package.json:**52```json53{54"scripts": {55"test": "vitest",56"test:run": "vitest run",57"test:coverage": "vitest run --coverage"58}59}60```6162**tsconfig.json (if using TypeScript):**63```json64{65"compilerOptions": {66"types": ["vitest/globals"]67}68}69```7071## Test File Example7273```javascript74// src/components/Counter.test.js75import { describe, it, expect, beforeEach } from 'vitest' // optional with globals: true76import { mount } from '@vue/test-utils'77import Counter from './Counter.vue'7879describe('Counter', () => {80let wrapper8182beforeEach(() => {83wrapper = mount(Counter)84})8586it('renders initial count', () => {87expect(wrapper.find('[data-testid="count"]').text()).toBe('0')88})8990it('increments when button clicked', async () => {91await wrapper.find('[data-testid="increment"]').trigger('click')92expect(wrapper.find('[data-testid="count"]').text()).toBe('1')93})94})95```9697## Vitest vs Jest Comparison9899| Feature | Vitest | Jest |100|---------|--------|------|101| Vite Integration | Native | Requires config |102| Speed | Very fast (ESM native) | Slower with Vite |103| Watch Mode | Excellent | Good |104| Vue SFC Support | Works with Vite | Needs vue-jest |105| Config Sharing | Same as vite.config | Separate |106| API | Jest-compatible | Standard |107108## Using with Testing Library109110```bash111npm install -D @testing-library/vue @testing-library/jest-dom112```113114```javascript115// src/test/setup.js116import { expect } from 'vitest'117import * as matchers from '@testing-library/jest-dom/matchers'118119expect.extend(matchers)120```121122```javascript123// Component.test.js124import { render, screen, fireEvent } from '@testing-library/vue'125import UserCard from './UserCard.vue'126127test('displays user name', () => {128render(UserCard, {129props: { name: 'John Doe' }130})131132expect(screen.getByText('John Doe')).toBeInTheDocument()133})134```135136## Advanced Configuration137138```javascript139// vitest.config.js (separate file if preferred)140import { defineConfig } from 'vitest/config'141import vue from '@vitejs/plugin-vue'142143export default defineConfig({144plugins: [vue()],145test: {146globals: true,147environment: 'happy-dom',148include: ['**/*.{test,spec}.{js,ts,jsx,tsx}'],149exclude: ['node_modules', 'dist', 'e2e'],150coverage: {151provider: 'v8',152reporter: ['text', 'json', 'html'],153exclude: ['node_modules', 'test']154},155// Helpful for debugging156reporters: ['verbose'],157// Run tests in sequence in CI158poolOptions: {159threads: {160singleThread: process.env.CI === 'true'161}162}163}164})165```166167## Common Patterns168169### Mocking Modules170```javascript171import { vi } from 'vitest'172173vi.mock('@/api/users', () => ({174fetchUser: vi.fn().mockResolvedValue({ name: 'John' })175}))176```177178### Testing with Fake Timers179```javascript180import { vi, beforeEach, afterEach } from 'vitest'181182beforeEach(() => {183vi.useFakeTimers()184})185186afterEach(() => {187vi.restoreAllMocks()188})189190test('debounced search', async () => {191const wrapper = mount(SearchBox)192await wrapper.find('input').setValue('vue')193194vi.advanceTimersByTime(300)195await flushPromises()196197expect(wrapper.emitted('search')).toBeTruthy()198})199```200201## Reference202- [Vitest Documentation](https://vitest.dev/)203- [Vue.js Testing Guide](https://vuejs.org/guide/scaling-up/testing)204- [Vue Test Utils](https://test-utils.vuejs.org/)205