Создание обертки компонента (Wrapper)

В Vue Test Utils обёртка компонента (Wrapper) — это объект, представляющий смонтированный Vue-компонент в тестовой среде. Обёртка инкапсулирует экземпляр компонента, его DOM-представление, реактивное состояние и предоставляет API для взаимодействия с компонентом так, как это происходит в реальном приложении.

Wrapper создаётся в момент монтирования компонента и становится центральной точкой всех тестовых операций: поиска элементов, изменения данных, эмуляции событий, проверки реакций и побочных эффектов.


Роль Wrapper в архитектуре тестов

Обёртка выполняет несколько ключевых функций:

  • Контроль жизненного цикла компонента в тесте
  • Доступ к DOM без прямой работы с document
  • Интеракция с реактивностью Vue
  • Изоляция тестируемой логики от внешнего окружения

Wrapper не является просто ссылкой на DOM-узел. Это высокоуровневый интерфейс, связывающий Vue-экземпляр и его представление.


Создание Wrapper через mount и shallowMount

Основные способы создания обёртки:

import { mount, shallowMount } from '@vue/test-utils'

mount

mount полностью монтирует компонент, включая все дочерние компоненты.

const wrapper = mount(MyComponent)

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

  • создаётся реальное DOM-дерево
  • все дочерние компоненты рендерятся
  • подходит для интеграционных тестов

shallowMount

shallowMount заменяет дочерние компоненты заглушками.

const wrapper = shallowMount(MyComponent)

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

  • изолирует компонент
  • ускоряет выполнение тестов
  • упрощает проверку логики верхнего уровня

Выбор между mount и shallowMount напрямую влияет на структуру и сложность обёртки.


Структура Wrapper

Wrapper содержит несколько уровней доступа:

  • wrapper.vm — экземпляр Vue-компонента
  • wrapper.element — корневой DOM-элемент
  • wrapper.html() — HTML-представление
  • wrapper.props() / wrapper.props(‘name’)
  • wrapper.emitted()

Пример:

wrapper.vm.count
wrapper.element.tagName
wrapper.html()

wrapper.vm предоставляет прямой доступ к данным, computed-свойствам и методам компонента, но его использование должно быть осознанным: тесты, основанные только на vm, теряют связь с реальным пользовательским поведением.


Поиск элементов внутри Wrapper

Wrapper предоставляет мощный API для поиска узлов.

find

Возвращает DOMWrapper.

const button = wrapper.find('button')

Поддерживаются:

  • CSS-селекторы
  • классы
  • атрибуты
  • компоненты
wrapper.find('.submit')
wrapper.find('[data-test="title"]')

findAll

const items = wrapper.findAll('li')

Возвращает коллекцию обёрток.

findComponent

Для поиска дочерних компонентов:

wrapper.findComponent(ChildComponent)

или по имени:

wrapper.findComponent({ name: 'ChildComponent' })

Работа с DOMWrapper и ComponentWrapper

В Vue Test Utils существуют разные типы обёрток:

  • DOMWrapper — обёртка над HTML-элементом
  • VueWrapper — обёртка над Vue-компонентом

DOMWrapper ограничен DOM-операциями:

button.text()
button.attributes()
button.classes()

VueWrapper расширяет возможности:

childWrapper.props()
childWrapper.emitted()
childWrapper.vm

Чёткое понимание типа обёртки предотвращает ошибки при вызове методов.


Эмуляция пользовательских действий

Wrapper позволяет эмулировать события так, как если бы они были вызваны пользователем.

await wrapper.find('button').trigger('click')

Поддерживаются параметры событий:

await input.trigger('keydown.enter')
await input.trigger('input', { target: { value: 'test' } })

trigger автоматически вызывает обработчики и учитывает асинхронную реактивность Vue.


Обновление состояния и реактивность

Изменение данных через Wrapper:

await wrapper.setData({ count: 5 })

Изменение props:

await wrapper.setProps({ title: 'New title' })

После таких операций обёртка обновляет DOM, но только после ожидания следующего тика.

await wrapper.vm.$nextTick()

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


Проверка эмитируемых событий

Wrapper аккумулирует все события, отправленные через $emit.

wrapper.emitted()

Пример:

expect(wrapper.emitted('submit')).toBeTruthy()
expect(wrapper.emitted('submit')[0]).toEqual([{ value: 10 }])

Каждый вызов события сохраняется как массив аргументов, что делает проверку детальной и предсказуемой.


Работа со слотами через Wrapper

Слоты передаются при создании обёртки:

mount(MyComponent, {
  slots: {
    default: '<span>Content</span>'
  }
})

Проверка:

expect(wrapper.html()).toContain('Content')

Wrapper корректно рендерит как обычные, так и scoped-слоты, предоставляя доступ к их DOM-представлению.


Контроль окружения через global options

Wrapper может быть настроен через global:

mount(MyComponent, {
  global: {
    plugins: [store],
    mocks: {
      $t: () => 'translated'
    },
    stubs: {
      RouterLink: true
    }
  }
})

Это позволяет:

  • подменять плагины
  • мокать глобальные свойства
  • управлять зависимостями компонента

Обёртка сохраняет эти настройки на протяжении всего теста.


Уничтожение Wrapper

После завершения теста обёртка может быть уничтожена:

wrapper.unmount()

Это особенно важно при тестировании компонентов с подписками, таймерами или глобальными эффектами.


Типичные ошибки при работе с Wrapper

  • работа с DOM без ожидания асинхронных обновлений
  • чрезмерное использование wrapper.vm
  • тестирование внутренних деталей вместо поведения
  • смешивание DOMWrapper и VueWrapper API

Корректное использование обёртки позволяет строить устойчивые и поддерживаемые тесты, отражающие реальное поведение компонентов Vue.