Vitest — современная тестовая библиотека для проектов на Vue.js и Vuetify, ориентированная на скорость и интеграцию с современными сборщиками, такими как Vite. Она сочетает возможности Jest с легкостью конфигурации и быстродействием. В контексте Vuetify особое внимание уделяется тестированию компонентов интерфейса, их реактивности, событий и взаимодействий с DOM.
Для начала необходимо установить Vitest и сопутствующие пакеты:
npm install -D vitest @vue/test-utils vue
Если проект использует Vuetify, подключение также потребует самого Vuetify:
npm install vuetify@next
Создание конфигурационного файла vitest.config.js:
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: './vitest.setup.js'
}
})
В файле vitest.setup.js можно инициализировать Vuetify
для тестов:
import { createVuetify } from 'vuetify'
import { config } from '@vue/test-utils'
const vuetify = createVuetify()
config.global.plugins = [vuetify]
Для Vuetify-компонентов важна изоляция и проверка их визуальной и
функциональной составляющей. Vitest совместно с
@vue/test-utils позволяет рендерить компонент в виртуальном
DOM и взаимодействовать с ним программно.
Пример теста простого компонента VBtn:
import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import { VBtn } from 'vuetify/components'
describe('VBtn', () => {
it('рендерит текст кнопки', () => {
const wrapper = mount(VBtn, {
slots: { default: 'Нажми меня' }
})
expect(wrapper.text()).toBe('Нажми меня')
})
it('генерирует событие click', async () => {
const wrapper = mount(VBtn)
await wrapper.trigger('click')
expect(wrapper.emitted()).toHaveProperty('click')
})
})
Ключевой момент — использование mount для полного
рендеринга компонента, что особенно важно для Vuetify, где компоненты
зависят от глобальных стилей и контекста темы.
Vuetify часто использует плагины и глобальные функции, такие как
$vuetify или темы. Для корректного тестирования их можно
замокировать:
import { mount } from '@vue/test-utils'
import MyComponent from './MyComponent.vue'
const globalMock = {
$vuetify: {
theme: { dark: false }
}
}
const wrapper = mount(MyComponent, {
global: {
mocks: globalMock
}
})
Это позволяет проверить реакцию компонента на изменение темы или других глобальных состояний без необходимости реальной инициализации всего Vuetify.
Vuetify предоставляет множество формовых компонентов:
VTextField, VSelect, VCheckbox.
Их тестирование требует проверки как визуального рендеринга, так и
реактивного поведения.
Пример теста VTextField:
import { mount } from '@vue/test-utils'
import { VTextField } from 'vuetify/components'
describe('VTextField', () => {
it('принимает ввод пользователя', async () => {
const wrapper = mount(VTextField, {
props: { modelValue: '' }
})
await wrapper.setValue('Привет')
expect(wrapper.props('modelValue')).toBe('Привет')
expect(wrapper.find('input').element.value).toBe('Привет')
})
})
Особенность Vuetify в том, что многие компоненты используют слоты и
реактивные свойства v-model, поэтому важно тестировать
через setValue и проверять как свойства компонента, так и
фактический DOM.
Vitest поддерживает снапшот-тестирование, что особенно полезно для сложных интерфейсных компонентов Vuetify:
import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import MyCard from './MyCard.vue'
describe('MyCard', () => {
it('совпадает со снапшотом', () => {
const wrapper = mount(MyCard)
expect(wrapper.html()).toMatchSnapshot()
})
})
Это позволяет отслеживать изменения в структуре компонента и предотвращать случайные визуальные регрессии.
Многие Vuetify-компоненты запускают асинхронные действия при
взаимодействии (например, открытие VDialog). Vitest
поддерживает асинхронное тестирование с помощью
async/await:
import { mount } from '@vue/test-utils'
import { VDialog, VBtn } from 'vuetify/components'
describe('VDialog', () => {
it('открывает диалог по кнопке', async () => {
const wrapper = mount({
template: `
<v-dialog v-model="open">
<template #activator="{ on }">
<v-btn v-on="on">Открыть</v-btn>
</template>
<div>Содержимое диалога</div>
</v-dialog>
`,
data: () => ({ open: false })
})
await wrapper.findComponent(VBtn).trigger('click')
expect(wrapper.vm.open).toBe(true)
})
})
Здесь важно тестировать через реальный DOM и события Vuetify, поскольку многие компоненты используют внутренние обработчики и слоты-активаторы.
Для комплексного тестирования интерфейсов можно комбинировать несколько компонентов и проверять их совместное поведение. Vitest позволяет организовать тесты так, чтобы проверять маршрутизацию, состояние и взаимодействие компонентов Vuetify в едином окружении.
Пример интеграции нескольких компонентов с состоянием:
import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import MyForm from './MyForm.vue'
import { createVuetify } from 'vuetify'
const vuetify = createVuetify()
describe('MyForm', () => {
it('отправляет данные после заполнения всех полей', async () => {
const wrapper = mount(MyForm, {
global: { plugins: [vuetify] }
})
await wrapper.find('input[name="name"]').setValue('Иван')
await wrapper.find('input[name="email"]').setValue('ivan@example.com')
await wrapper.find('form').trigger('submit.prevent')
expect(wrapper.emitted()).toHaveProperty('submit')
expect(wrapper.emitted('submit')[0][0]).toEqual({ name: 'Иван', email: 'ivan@example.com' })
})
})
Такой подход обеспечивает тестирование компонентов не только изолированно, но и в контексте взаимодействия между ними, что критично для сложных Vuetify-интерфейсов.
Тестирование Vuetify с Vitest сочетает быстрый рендеринг, поддержку
слотов, событий и реактивных свойств, позволяя создавать стабильные,
проверяемые интерфейсы. Основные методы — mount,
trigger, setValue, мокирование глобальных
функций и снапшоты — дают полный инструментарий для контроля визуального
и функционального поведения компонентов.