Скрытые элементы и их тестирование

В Vue.js часто встречается необходимость управлять элементами, которые изначально не отображаются на странице: модальные окна, выпадающие списки, скрытые панели или компоненты с v-if и v-show. Тестирование таких элементов требует понимания их жизненного цикла и взаимодействия с DOM через Vue Test Utils.


Различие между v-if и v-show

v-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() возвращает массив всех классов элемента, что позволяет убедиться, что компонент находится в правильном состоянии без необходимости учитывать фактическое отображение.


Важные моменты и лучшие практики

  1. Разделение логики отображения и данных — легче тестировать v-if и v-show, если видимость зависит только от реактивных данных, а не от вычислений внутри шаблона.
  2. Использование await wrapper.vm.$nextTick() при асинхронных изменениях состояния, если не используется trigger() или setData().
  3. Скрытые компоненты с Teleport требуют подключения к реальному DOM через attachTo.
  4. isVisible() предпочтительнее exists() для v-show, так как элемент может существовать, но быть невидимым.

Тщательное понимание различий между v-if и v-show, методов поиска и проверки элементов, а также особенностей сторонних UI-библиотек позволяет создавать надежные тесты для любых скрытых элементов в Vue.