Тестирование v-show директивы

Директива v-show используется для условного отображения элементов в DOM, изменяя их свойство display без удаления из DOM. В отличие от v-if, который полностью добавляет или удаляет элемент, v-show оставляет элемент в дереве, управляя только стилями. Это накладывает особенности на тестирование, так как проверка наличия элемента через стандартные методы типа find() всегда будет успешной. Основной задачей становится проверка видимости элемента.

Основы работы с v-show в тестах

v-show управляет элементом через CSS-свойство display. В Vue Test Utils можно получить доступ к этому свойству через:

wrapper.find('селектор').element.style.display

Если директива установлена в true, значение display должно быть пустым ('') или соответствовать дефолтному стилю. Если falsedisplay: none.

Пример простого компонента с v-show

<template>
  <div>
    <p v-show="isVisible">Секретный текст</p>
    <button @click="toggle">Переключить видимость</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isVisible: false
    }
  },
  methods: {
    toggle() {
      this.isVisible = !this.isVisible;
    }
  }
}
</script>

В данном компоненте <p> элемент изначально скрыт. Тест должен проверить начальное состояние и реакцию на изменение isVisible.

Тестирование через Vue Test Utils

  1. Монтирование компонента
import { mount } from '@vue/test-utils'
import MyComponent from '@/components/MyComponent.vue'

const wrapper = mount(MyComponent)
  1. Проверка начального состояния v-show
const paragraph = wrapper.find('p')
expect(paragraph.isVisible()).toBe(false)

Метод isVisible() автоматически учитывает display: none, visibility: hidden и другие CSS-свойства, влияющие на видимость элемента. Это предпочтительный способ для проверки v-show.

  1. Изменение состояния и проверка реакции
wrapper.vm.toggle()
await wrapper.vm.$nextTick()

expect(paragraph.isVisible()).toBe(true)

Важно использовать await wrapper.vm.$nextTick(), так как изменения реактивных данных асинхронны и DOM обновляется только после следующего тика.

Альтернативные способы проверки

Можно напрямую проверять стиль элемента:

expect(paragraph.element.style.display).toBe('none')
wrapper.vm.toggle()
await wrapper.vm.$nextTick()
expect(paragraph.element.style.display).toBe('')

Однако этот подход менее устойчив к изменениям CSS и менее декларативен по сравнению с isVisible().

Тестирование сложных условий

Если v-show зависит от вычисляемого свойства или нескольких условий:

<p v-show="isVisible && userLoggedIn">Доступный контент</p>

Тест должен учитывать все комбинации:

wrapper.setData({ isVisible: true, userLoggedIn: false })
await wrapper.vm.$nextTick()
expect(wrapper.find('p').isVisible()).toBe(false)

wrapper.setData({ userLoggedIn: true })
await wrapper.vm.$nextTick()
expect(wrapper.find('p').isVisible()).toBe(true)

Методы setData и setProps позволяют изменять реактивные данные и свойства компонента для проверки различных сценариев.

Проверка реакции на события

Если изменение v-show связано с событием пользователя, например кликом, важно моделировать событие:

const button = wrapper.find('button')
await button.trigger('click')
expect(wrapper.find('p').isVisible()).toBe(true)

Использование trigger() вместе с await гарантирует корректное обновление DOM.

Тестирование в сочетании с CSS и transition

v-show часто комбинируется с transition. В этом случае isVisible() учитывает анимацию только после завершения перехода, если тест использует реальные DOM-объекты. Для ускорения тестирования и исключения зависимостей от анимации можно отключить transition:

import { mount } from '@vue/test-utils'
import MyComponent from '@/components/MyComponent.vue'

const wrapper = mount(MyComponent, {
  global: {
    stubs: {
      transition: false
    }
  }
})

Практические рекомендации

  • Использовать isVisible() для декларативной проверки видимости, а не напрямую style.display.
  • Всегда использовать await wrapper.vm.$nextTick() после изменения реактивных данных.
  • Проверять все логические ветки при комбинировании нескольких условий в v-show.
  • Симулировать события пользователя через trigger() для динамических сценариев.
  • Отключать transition при необходимости ускорить тесты и убрать влияние CSS-анимаций.

Тестирование v-show требует внимания к DOM и реактивности, но с использованием isVisible(), setData и trigger() создаются устойчивые и понятные тесты, отражающие поведение компонента в реальных условиях.