Skip to content

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:coverage

Visual Testing

javascript
// in Playwright
await page.screenshot({ path: 'screenshot.png' })