Appearance
Testing
Introduction
This guide includes testing strategies and best practices for the project.
Types of Tests
Unit Tests
Unit tests for individual functions and components:
javascript
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import Counter from './Counter.vue'
describe('Counter', () => {
it('increments count when button is clicked', async () => {
const wrapper = mount(Counter)
const button = wrapper.find('button')
await button.trigger('click')
expect(wrapper.text()).toContain('Count: 1')
})
})Integration Tests
Integration tests for interaction between components:
javascript
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import UserProfile from './UserProfile.vue'
describe('UserProfile', () => {
it('displays user data from store', () => {
const wrapper = mount(UserProfile, {
global: {
provide: {
userStore: {
user: { name: 'John', email: '[email protected]' }
}
}
}
})
expect(wrapper.text()).toContain('John')
expect(wrapper.text()).toContain('[email protected]')
})
})E2E Tests
End-to-end tests for complete scenarios:
javascript
import { test, expect } from '@playwright/test'
test('user can login and view dashboard', async ({ page }) => {
await page.goto('/login')
await page.fill('[data-testid="email"]', '[email protected]')
await page.fill('[data-testid="password"]', 'password123')
await page.click('[data-testid="login-button"]')
await expect(page).toHaveURL('/dashboard')
await expect(page.locator('[data-testid="welcome-message"]')).toBeVisible()
})Testing Tools
Vitest
Main framework for unit testing:
javascript
// vitest.config.js
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
environment: 'jsdom',
globals: true
}
})Vue Test Utils
For testing Vue components:
javascript
import { mount, shallowMount } from '@vue/test-utils'
// mount: complete component with children
const wrapper = mount(Component)
// shallowMount: only main component
const wrapper = shallowMount(Component)Playwright
For E2E testing:
javascript
// playwright.config.js
import { defineConfig } from '@playwright/test'
export default defineConfig({
testDir: './tests/e2e',
use: {
baseURL: 'http://localhost:3000',
screenshot: 'only-on-failure'
}
})Best Practices
Test Naming
javascript
describe('UserService', () => {
describe('createUser', () => {
it('should create user with valid data', () => {
// test implementation
})
it('should throw error with invalid email', () => {
// test implementation
})
})
})Using data-testid
vue
<template>
<button data-testid="submit-button" @click="submit">
Submit
</button>
</template>javascript
// in test
const button = wrapper.find('[data-testid="submit-button"]')Mocking
javascript
import { vi } from 'vitest'
// Mock API calls
vi.mock('@/api/user', () => ({
createUser: vi.fn().mockResolvedValue({ id: 1, name: 'John' })
}))
// Mock Vue composables
vi.mock('@vueuse/core', () => ({
useLocalStorage: vi.fn().mockReturnValue(ref('test'))
}))Testing Async Code
javascript
it('should fetch user data', async () => {
const wrapper = mount(UserComponent)
// wait for async operation
await wrapper.vm.$nextTick()
expect(wrapper.text()).toContain('User data loaded')
})Testing Vue Components
Testing Props
javascript
it('should display title prop', () => {
const wrapper = mount(Component, {
props: { title: 'Test Title' }
})
expect(wrapper.text()).toContain('Test Title')
})Testing Events
javascript
it('should emit click event', async () => {
const wrapper = mount(Component)
const button = wrapper.find('button')
await button.trigger('click')
expect(wrapper.emitted('click')).toBeTruthy()
})Testing Slots
javascript
it('should render slot content', () => {
const wrapper = mount(Component, {
slots: {
default: '<span>Slot content</span>'
}
})
expect(wrapper.html()).toContain('Slot content')
})Testing API Calls
Mocking Axios
javascript
import axios from 'axios'
import { vi } from 'vitest'
vi.mock('axios')
it('should fetch users', async () => {
const mockUsers = [{ id: 1, name: 'John' }]
axios.get.mockResolvedValue({ data: mockUsers })
const result = await fetchUsers()
expect(result).toEqual(mockUsers)
})Testing Error Handling
javascript
it('should handle API errors', async () => {
axios.get.mockRejectedValue(new Error('Network error'))
const wrapper = mount(Component)
await wrapper.vm.loadData()
expect(wrapper.text()).toContain('Error loading data')
})Coverage
Coverage Configuration
javascript
// vitest.config.js
export default defineConfig({
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
thresholds: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80
}
}
}
}
})Running Coverage
bash
pnpm test:coverageVisual Testing
javascript
// in Playwright
await page.screenshot({ path: 'screenshot.png' })