В Vue.js часто встречается необходимость управлять элементами,
которые изначально не отображаются на странице: модальные окна,
выпадающие списки, скрытые панели или компоненты с v-if и
v-show. Тестирование таких элементов требует понимания их
жизненного цикла и взаимодействия с DOM через Vue Test Utils.
v-if и
v-showv-if полностью добавляет или удаляет
элемент из DOM. v-show меняет только
CSS-свойство display, оставляя элемент в DOM постоянно.
Это ключевой момент для тестирования:
v-if нельзя найти в DOM до
того, как условие станет истинным.v-show всегда присутствуют,
но могут быть скрыты визуально.Пример:
<template>
<div>
<button @click="showModal = !showModal">Toggle Modal</button>
<div v-if="showModal" class="modal">Контент модалки</div>
<div v-show="showTooltip" class="tooltip">Подсказка</div>
</div>
</template>
<script>
export default {
data() {
return {
showModal: false,
showTooltip: false
}
}
}
</script>
wrapper.find() и
wrapper.findAll() находят элементы по
селекторам, но важно понимать, что они работают только с текущим
состоянием DOM.
v-if:import { mount } from '@vue/test-utils'
import Component from '@/components/Component.vue'
const wrapper = mount(Component)
expect(wrapper.find('.modal').exists()).toBe(false)
await wrapper.setData({ showModal: true })
expect(wrapper.find('.modal').exists()).toBe(true)
v-show:expect(wrapper.find('.tooltip').isVisible()).toBe(false)
await wrapper.setData({ showTooltip: true })
expect(wrapper.find('.tooltip').isVisible()).toBe(true)
Метод isVisible() учитывает CSS-свойство
display: none и скрытые родительские элементы, что
позволяет корректно тестировать визуальное состояние.
При тестировании пользовательских сценариев важно эмулировать события, которые открывают скрытые элементы.
Пример с модальным окном:
await wrapper.find('button').trigger('click')
expect(wrapper.find('.modal').isVisible()).toBe(true)
Vue Test Utils автоматически обрабатывает обновление реактивных
данных после trigger, поэтому await необходим
для корректного ожидания перерендеринга.
Скрытые элементы часто содержат динамический контент, который подгружается только после отображения компонента:
<div v-if="showModal">
<p>{{ modalText }}</p>
</div>
Тестирование:
await wrapper.setData({ showModal: true, modalText: 'Привет' })
expect(wrapper.find('.modal p').text()).toBe('Привет')
Важно сначала убедиться, что элемент появился в DOM, прежде чем проверять его содержимое.
Для библиотек UI, таких как Vuetify или Element Plus, скрытые
элементы могут рендериться вне корневого DOM-компонента (teleport). В
таких случаях обычные методы find() не найдут элемент.
Решения:
document.querySelector.attachTo: document.body при
монтировании:const wrapper = mount(Component, { attachTo: document.body })
Это позволяет тестировать модальные окна и всплывающие подсказки, которые рендерятся в теле документа.
Иногда достаточно проверить, применён ли CSS-класс, управляющий видимостью:
expect(wrapper.find('.modal').classes()).toContain('visible')
Метод classes() возвращает массив всех классов элемента,
что позволяет убедиться, что компонент находится в правильном состоянии
без необходимости учитывать фактическое отображение.
v-if и v-show, если видимость
зависит только от реактивных данных, а не от вычислений внутри
шаблона.await wrapper.vm.$nextTick() при асинхронных
изменениях состояния, если не используется trigger() или
setData().attachTo.isVisible() предпочтительнее
exists() для v-show, так как элемент
может существовать, но быть невидимым.Тщательное понимание различий между v-if и
v-show, методов поиска и проверки элементов, а также
особенностей сторонних UI-библиотек позволяет создавать надежные тесты
для любых скрытых элементов в Vue.