Готовые компоненты для тестирования

Vue Test Utils (VTU) — официальная библиотека для тестирования компонентов Vue.js. Она предоставляет набор утилит для рендеринга компонентов, симуляции событий и проверки реактивного поведения. Основной элемент VTU — mount и shallowMount, которые создают экземпляр компонента для теста.

  • mount полностью рендерит компонент со всеми его дочерними компонентами.
  • shallowMount рендерит только сам компонент, заменяя дочерние компоненты заглушками. Это ускоряет тестирование и снижает сложность.

Пример базового использования:

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

const wrapper = mount(MyComponent)
expect(wrapper.text()).toContain('Привет, Vue!')

Взаимодействие с DOM

VTU предоставляет методы для работы с DOM-узлами компонента. Основные методы:

  • find(selector) — возвращает первый элемент, соответствующий селектору.
  • findAll(selector) — возвращает массив всех элементов, подходящих под селектор.
  • text() — извлекает текстовое содержимое элемента.
  • html() — возвращает HTML-разметку компонента.
  • attributes(name) — получает значение указанного атрибута.

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

const button = wrapper.find('button')
expect(button.text()).toBe('Нажми меня')
expect(button.attributes('disabled')).toBeUndefined()

Симуляция событий

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

  • trigger(event, options) — запускает событие на элементе.

Пример:

const button = wrapper.find('button')
button.trigger('click')
expect(wrapper.emitted('clicked')).toHaveLength(1)

emitted() возвращает объект с массивами вызовов событий, что позволяет проверять аргументы и количество срабатываний.


Работа с пропсами и состоянием

Компоненты Vue часто используют props для передачи данных и data/computed для управления состоянием. VTU поддерживает настройку этих значений при монтировании:

const wrapper = mount(MyComponent, {
  props: { title: 'Тестовый заголовок' },
  data() {
    return { count: 5 }
  }
})

expect(wrapper.props('title')).toBe('Тестовый заголовок')
expect(wrapper.vm.count).toBe(5)
  • wrapper.vm предоставляет доступ к экземпляру компонента, включая методы и вычисляемые свойства.
  • Изменение props после монтирования можно тестировать через setProps().
wrapper.setProps({ title: 'Новый заголовок' })
expect(wrapper.text()).toContain('Новый заголовок')

Тестирование слотов

Слоты позволяют вставлять пользовательский контент в компонент. VTU поддерживает передачу слотов через объект slots:

const wrapper = mount(MyComponent, {
  slots: { default: '<p>Слот-контент</p>' }
})

expect(wrapper.html()).toContain('<p>Слот-контент</p>')

Также можно тестировать именованные слоты:

const wrapper = mount(MyComponent, {
  slots: { header: '<h1>Заголовок</h1>' }
})

expect(wrapper.find('h1').text()).toBe('Заголовок')

Использование моков и зависимостей

Для компонентов, которые зависят от глобальных ресурсов, VTU предоставляет возможность мока:

  • global.mocks — подменяет глобальные объекты, например $router, $store.
  • global.stubs — подменяет дочерние компоненты заглушками.

Пример мока Vuex:

const storeMock = { dispatch: jest.fn() }
const wrapper = mount(MyComponent, {
  global: { mocks: { $store: storeMock } }
})

wrapper.vm.someAction()
expect(storeMock.dispatch).toHaveBeenCalledWith('someAction')

Асинхронное поведение

VTU поддерживает асинхронные операции с использованием nextTick или flushPromises:

import { nextTick } from 'vue'

wrapper.setData({ count: 10 })
await nextTick()
expect(wrapper.text()).toContain('10')

flushPromises полезен для тестирования промисов и API-запросов:

import flushPromises from 'flush-promises'

await wrapper.vm.fetchData()
await flushPromises()
expect(wrapper.text()).toContain('Данные загружены')

Проверка CSS-классов и стилей

VTU позволяет проверять динамические классы и стили:

expect(wrapper.classes()).toContain('active')
expect(wrapper.find('div').element.style.color).toBe('red')

Методы:

  • classes() — массив всех классов элемента.
  • hasClass(className) — проверка наличия конкретного класса.
  • element.style — доступ к инлайн-стилям.

Использование готовых компонентов для тестирования

Для ускорения тестирования можно создавать обёртки-компоненты (wrapper components), которые заранее подставляют пропсы, слоты и моки. Это уменьшает повторение кода и позволяет тестировать сложные UI-модули с минимальными усилиями.

Пример обёртки:

const TestButtonWrapper = {
  template: '<MyButton @clicked="onClick" :label="label" />',
  components: { MyButton },
  data() { return { label: 'Тест' } },
  methods: { onClick: jest.fn() }
}

const wrapper = mount(TestButtonWrapper)
wrapper.find('button').trigger('click')
expect(wrapper.vm.onClick).toHaveBeenCalled()

Такие компоненты особенно полезны при интеграционном тестировании и работе с библиотеками UI, где нужно проверять комбинацию нескольких готовых компонентов.


Логирование и дебаг

VTU предоставляет удобный метод wrapper.debug(), который выводит структуру компонента с вложенными элементами. Это облегчает поиск проблем при сложных шаблонах:

console.log(wrapper.debug())

Метод возвращает читаемую строку, показывающую компоненты, их props, слоты и текстовое содержимое.


Закрепление паттернов

  • Использовать shallowMount для юнит-тестов отдельных компонентов.
  • Использовать mount для интеграционных тестов с дочерними компонентами.
  • Моки, stubs и слоты позволяют изолировать тестируемый компонент от внешних зависимостей.
  • Асинхронные операции требуют nextTick или flushPromises для корректного ожидания обновлений.
  • Wrapper-компоненты ускоряют повторное тестирование сложных UI-блоков.

Эти подходы обеспечивают надежное покрытие и читаемость тестов при работе с Vue Test Utils.