yarn add -D vitest @vue/test-utils
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
environment: 'jsdom'
}
})
import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import MyComponent from './MyComponent.vue'
describe('MyComponent', () => {
it('renders properly', () => {
const wrapper = mount(MyComponent, {
props: { message: 'Hello' }
})
expect(wrapper.text()).toContain('Hello')
})
})
it('emits event when button clicked', async () => {
const wrapper = mount(MyComponent)
await wrapper.find('button').trigger('click')
expect(wrapper.emitted()).toHaveProperty('submit')
expect(wrapper.emitted('submit')).toHaveLength(1)
})
it('accepts props', () => {
const wrapper = mount(MyComponent, {
props: {
title: 'Test Title',
count: 10
}
})
expect(wrapper.props('title')).toBe('Test Title')
expect(wrapper.props('count')).toBe(10)
})
it('renders slot content', () => {
const wrapper = mount(MyComponent, {
slots: {
default: '<div>Slot Content</div>'
}
})
expect(wrapper.html()).toContain('Slot Content')
})
import { describe, it, expect } from 'vitest'
import { useMouse } from './useMouse'
describe('useMouse', () => {
it('returns mouse position', () => {
const { x, y } = useMouse()
expect(x.value).toBe(0)
expect(y.value).toBe(0)
})
})
import { setActivePinia, createPinia } from 'pinia'
import { describe, it, expect, beforeEach } from 'vitest'
import { useCounterStore } from './counter'
describe('Counter Store', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
it('increments counter', () => {
const counter = useCounterStore()
expect(counter.count).toBe(0)
counter.increment()
expect(counter.count).toBe(1)
})
})
import { mount } from '@vue/test-utils'
import { createRouter, createMemoryHistory } from 'vue-router'
const router = createRouter({
history: createMemoryHistory(),
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About }
]
})
it('navigates to about page', async () => {
router.push('/about')
await router.isReady()
const wrapper = mount(App, {
global: {
plugins: [router]
}
})
expect(wrapper.html()).toContain('About')
})
import { vi } from 'vitest'
it('calls callback', () => {
const callback = vi.fn()
const wrapper = mount(MyComponent, {
props: { onSubmit: callback }
})
wrapper.find('button').trigger('click')
expect(callback).toHaveBeenCalled()
})
import { vi } from 'vitest'
global.fetch = vi.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ data: 'test' })
})
)
it('fetches data', async () => {
const wrapper = mount(MyComponent)
await wrapper.vm.$nextTick()
expect(fetch).toHaveBeenCalled()
})
it('matches snapshot', () => {
const wrapper = mount(MyComponent, {
props: { message: 'Hello' }
})
expect(wrapper.html()).toMatchSnapshot()
})
yarn add -D @playwright/test
import { test, expect } from '@playwright/test'
test('homepage has title', async ({ page }) => {
await page.goto('http://localhost:5173')
await expect(page).toHaveTitle(/My App/)
})
test('can navigate to about page', async ({ page }) => {
await page.goto('http://localhost:5173')
await page.click('text=About')
await expect(page).toHaveURL(/about/)
})