При работе с библиотекой Vuetify тестирование
компонентов имеет свои особенности, так как большинство элементов
завязано на внутренние стили, слоты и реактивное управление состоянием
через v-model. Vue Test Utils
предоставляет мощный инструмент для создания юнит-тестов и
интеграционных тестов Vue-компонентов, включая компоненты Vuetify.
Для корректной работы компонентов Vuetify в тестах необходимо создать специальный конфиг, который будет инициализировать плагин Vuetify перед монтированием компонентов:
import { createLocalVue, mount } from '@vue/test-utils'
import Vuetify from 'vuetify'
import Vue from 'vue'
Vue.use(Vuetify)
const localVue = createLocalVue()
function mountVuetifyComponent(component, options = {}) {
const vuetify = new Vuetify()
return mount(component, {
localVue,
vuetify,
...options,
})
}
Важным моментом является использование
Vue.use(Vuetify) и передача экземпляра
vuetify при монтировании. Без этого многие компоненты
(например, v-btn, v-dialog) будут рендериться
некорректно.
Для проверки того, что компонент корректно отображается, используют
метод find или findComponent:
import MyButton from '@/components/MyButton.vue'
test('рендеринг кнопки с текстом', () => {
const wrapper = mountVuetifyComponent(MyButton, {
propsData: { label: 'Нажми меня' }
})
const button = wrapper.find('button')
expect(button.exists()).toBe(true)
expect(button.text()).toBe('Нажми меня')
})
В случае компонентов Vuetify часто лучше использовать
findComponent с указанием v-btn:
const button = wrapper.findComponent({ name: 'VBtn' })
expect(button.text()).toBe('Нажми меня')
Vuetify-компоненты активно используют события.
Vue Test Utils позволяет проверять их с помощью метода
trigger и emitted:
const wrapper = mountVuetifyComponent(MyButton)
const button = wrapper.findComponent({ name: 'VBtn' })
button.trigger('click')
expect(wrapper.emitted('click')).toBeTruthy()
Для проверки v-model используют синтаксис привязки:
import MyInput from '@/components/MyInput.vue'
test('изменение значения через v-model', async () => {
const wrapper = mountVuetifyComponent(MyInput, {
propsData: { value: 'initial' }
})
const input = wrapper.findComponent({ name: 'VTextField' })
input.setValue('новое значение')
await wrapper.vm.$nextTick()
expect(wrapper.emitted('input')[0]).toEqual(['новое значение'])
})
Многие компоненты Vuetify используют слоты для кастомизации содержимого. Проверка слотов выполняется через передачу контента при монтировании:
import MyCard from '@/components/MyCard.vue'
test('рендеринг кастомного слота', () => {
const wrapper = mountVuetifyComponent(MyCard, {
slots: {
default: '<span class="custom-slot">Контент</span>'
}
})
expect(wrapper.find('.custom-slot').exists()).toBe(true)
expect(wrapper.text()).toContain('Контент')
})
Многие Vuetify-компоненты, такие как v-dialog,
v-menu, управляются через свойства value или
v-model. Тестирование требует использования
nextTick:
import MyDialog from '@/components/MyDialog.vue'
test('открытие и закрытие диалога', async () => {
const wrapper = mountVuetifyComponent(MyDialog)
wrapper.setProps({ value: true })
await wrapper.vm.$nextTick()
expect(wrapper.findComponent({ name: 'VDialog' }).vm.value).toBe(true)
wrapper.setProps({ value: false })
await wrapper.vm.$nextTick()
expect(wrapper.findComponent({ name: 'VDialog' }).vm.value).toBe(false)
})
При тестировании можно использовать stubs для снижения зависимости от стилей и поведения:
const wrapper = mount(MyButton, {
stubs: ['v-icon', 'v-btn'],
})
Это ускоряет тесты и позволяет сфокусироваться на логике компонента, а не на визуальном рендеринге Vuetify.
Vuetify часто использует внутренние свойства для управления
состоянием, например v-model и active-class.
Проверка изменений состояния выполняется через реактивные свойства:
import MySwitch from '@/components/MySwitch.vue'
test('изменение состояния переключателя', async () => {
const wrapper = mountVuetifyComponent(MySwitch, {
propsData: { value: false }
})
const switchInput = wrapper.findComponent({ name: 'VSwitch' })
switchInput.vm.$emit('change', true)
await wrapper.vm.$nextTick()
expect(wrapper.emitted('input')[0]).toEqual([true])
})
Vuetify-компоненты часто тестируют в связке с Jest, так как он поддерживает асинхронные тесты и мокирование модулей. Для покрытия тестами рекомендуется:
findComponent вместо find для
Vuetify-компонентов.nextTick после изменения props или
событий.mountVuetifyComponent).Эти практики позволяют писать стабильные и предсказуемые юнит-тесты для компонентов Vuetify, избегая ошибок из-за особенностей стилизации и внутренней логики компонентов.