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

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


Основные принципы тестирования v-if

  1. Проверка наличия элемента Когда условие директивы истинно, элемент должен присутствовать в DOM. Когда условие ложно, элемент отсутствует.

  2. Избегание тестирования внутренней реализации Тест должен проверять внешний результат (наличие или отсутствие элемента), а не внутренние детали компонента. Это делает тесты более устойчивыми к изменениям кода.

  3. Использование реактивных данных v-if часто зависит от состояния data или пропсов. Важно проверять реакцию компонента на изменение этих данных после монтирования.


Пример тестирования с использованием mount

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

describe('ComponentWithVIf', () => {
  it('отображает элемент, когда условие истинно', async () => {
    const wrapper = mount(ComponentWithVIf, {
      props: { show: true }
    })

    expect(wrapper.find('.conditional-element').exists()).toBe(true)
  })

  it('не отображает элемент, когда условие ложно', async () => {
    const wrapper = mount(ComponentWithVIf, {
      props: { show: false }
    })

    expect(wrapper.find('.conditional-element').exists()).toBe(false)
  })
})

Объяснение:

  • Метод mount создает полный экземпляр компонента и рендерит его DOM.
  • Метод find ищет элемент по селектору CSS.
  • Метод exists() проверяет присутствие элемента в DOM.

Тестирование динамического изменения состояния

it('реагирует на изменение props', async () => {
  const wrapper = mount(ComponentWithVIf, {
    props: { show: false }
  })

  expect(wrapper.find('.conditional-element').exists()).toBe(false)

  await wrapper.setProps({ show: true })

  expect(wrapper.find('.conditional-element').exists()).toBe(true)
})

Ключевой момент: использование await с асинхронными методами Vue Test Utils (setProps, setData) гарантирует, что DOM обновился перед проверкой.


Тестирование с v-if и v-else

Комбинация v-if и v-else позволяет рендерить альтернативные элементы. Тесты должны проверять обе ветви.

it('отображает альтернативный элемент при ложном условии', async () => {
  const wrapper = mount(ComponentWithVIf, {
    props: { show: false }
  })

  expect(wrapper.find('.conditional-element').exists()).toBe(false)
  expect(wrapper.find('.alternative-element').exists()).toBe(true)
})

Особенности:

  • v-else не может существовать без v-if перед ним, поэтому тестирование альтернативного элемента подразумевает проверку первоначального условия.

Проверка вложенных v-if

Вложенные условные блоки требуют проверки каждой комбинации условий:

it('правильно рендерит вложенные блоки', async () => {
  const wrapper = mount(ComponentWithVIf, {
    data() {
      return { outer: true, inner: false }
    }
  })

  expect(wrapper.find('.outer-element').exists()).toBe(true)
  expect(wrapper.find('.inner-element').exists()).toBe(false)

  await wrapper.setData({ inner: true })

  expect(wrapper.find('.inner-element').exists()).toBe(true)
})

Рекомендация: тестировать каждую комбинацию условий, чтобы исключить ошибки в логике рендеринга.


Советы по организации тестов

  • Отдельные тесты для каждой ветви условия. Каждое состояние v-if должно проверяться независимо.
  • Использование селекторов по классам или атрибутам. Избегать поиска по тексту, чтобы тесты оставались стабильными при изменении содержимого.
  • Проверка реактивного обновления. Всегда использовать асинхронные методы (setData, setProps) с await, чтобы убедиться, что Vue завершил перерисовку.

Частые ошибки

  1. Проверка до рендеринга Попытка проверить элемент сразу после mount без асинхронного обновления данных может давать неверные результаты.

  2. Пренебрежение альтернативными блоками (v-else) Иногда тестируют только v-if, игнорируя ветку v-else, что оставляет потенциальные ошибки невыявленными.

  3. Использование shallowMount без необходимости При v-if на дочерних компонентах shallowMount может скрывать элементы, создавая ложные негативные результаты.


Взаимодействие с другими директивами

v-if часто сочетается с v-for или v-show. Тестирование должно учитывать:

  • v-show оставляет элемент в DOM, меняется только display.
  • v-for в сочетании с v-if изменяет количество элементов в зависимости от массива и условия.

Пример проверки:

it('корректно рендерит список с фильтром', async () => {
  const wrapper = mount(ComponentWithVIf, {
    data() {
      return { items: [1, 2, 3], showEven: true }
    }
  })

  expect(wrapper.findAll('.item').length).toBe(2) // только 2 и 3
})

Тестирование v-if директивы с Vue Test Utils позволяет уверенно проверять условный рендеринг компонентов, гарантируя, что интерфейс корректно реагирует на изменения состояния и пропсов. Такой подход обеспечивает надежность приложения и минимизирует ошибки визуального отображения.