Вложенные списки

Для работы с Vue Test Utils необходимо убедиться, что проект использует Vue 3 или Vue 2 в зависимости от версии библиотеки. Установка производится через npm или yarn:

npm install @vue/test-utils --save-dev

Для тестирования компонентов часто используется Jest:

npm install jest @vue/vue3-jest --save-dev

После установки необходимо настроить трансформеры для Jest, чтобы корректно обрабатывались .vue файлы:

{
  "transform": {
    "^.+\\.vue$": "@vue/vue3-jest",
    "^.+\\.js$": "babel-jest"
  }
}

Монтирование компонентов

Основной функцией Vue Test Utils является mount, которая создаёт полноценный экземпляр компонента:

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

const wrapper = mount(MyComponent);

Ключевые моменты при монтировании:

  • mount создаёт полный рендер компонента, включая дочерние компоненты.
  • shallowMount рендерит только текущий компонент, заменяя дочерние заглушками, что ускоряет тестирование и изолирует компонент.
import { shallowMount } from '@vue/test-utils';

const wrapper = shallowMount(MyComponent);

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

Пропсы передаются через объект props при монтировании:

const wrapper = mount(MyComponent, {
  props: { title: 'Тестовая компонента' }
});

Состояние компонента (data) можно изменять через методы setData и setProps:

await wrapper.setData({ counter: 5 });
await wrapper.setProps({ title: 'Новый заголовок' });

Это позволяет имитировать пользовательские действия и проверять реакцию компонента.


Поиск элементов и взаимодействие с DOM

Для поиска элементов используются методы find и findAll, принимающие CSS-селекторы или компоненты:

const button = wrapper.find('button');
const items = wrapper.findAll('.list-item');

Основные методы взаимодействия с DOM:

  • trigger(eventType) — имитация событий, например клика:
await button.trigger('click');
  • text() — получение текстового содержимого элемента.
  • html() — получение HTML-разметки элемента.
  • classes() — получение списка CSS-классов.

Тестирование вложенных компонентов

Вложенные компоненты можно тестировать через полный mount или использовать заглушки (stubs) для изоляции:

const wrapper = mount(ParentComponent, {
  global: {
    stubs: {
      ChildComponent: true
    }
  }
});

Особенности работы с вложенными компонентами:

  1. Доступ к дочерним элементам через findComponent:
const childWrapper = wrapper.findComponent({ name: 'ChildComponent' });
  1. Проверка передачи пропсов в дочерние компоненты:
expect(childWrapper.props('title')).toBe('Заголовок');
  1. Триггер событий на дочерних компонентах:
await childWrapper.vm.$emit('submit', { id: 1 });

Это позволяет проверять взаимодействие между родительским и дочерним компонентом без прямого вмешательства в внутреннюю логику дочернего компонента.


Работа с реактивностью и асинхронными обновлениями

Vue Test Utils автоматически отслеживает реактивные изменения, но при асинхронных операциях рекомендуется использовать nextTick:

import { nextTick } from 'vue';

await wrapper.setData({ counter: 10 });
await nextTick();

expect(wrapper.text()).toContain('10');

При работе с промисами внутри компонентов можно использовать flushPromises:

import flushPromises from 'flush-promises';

await flushPromises();

Это гарантирует завершение всех асинхронных операций перед проверкой результатов.


Мока и глобальные плагины

Для тестирования компонентов с использованием Vuex, Vue Router или других глобальных зависимостей используется опция global:

import { createStore } from 'vuex';

const store = createStore({
  state: { count: 0 },
  mutations: { increment: (state) => state.count++ }
});

const wrapper = mount(MyComponent, {
  global: { plugins: [store] }
});

Также можно мокать глобальные методы и компоненты:

const wrapper = mount(MyComponent, {
  global: {
    mocks: { $t: (msg) => msg },
    stubs: { RouterLink: true }
  }
});

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

Vue Test Utils позволяет тестировать события компонента через методы emitted и trigger:

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

expect(wrapper.emitted()).toHaveProperty('submit');
expect(wrapper.emitted('submit')[0]).toEqual([{ id: 1 }]);
  • emitted() возвращает объект всех событий, которые компонент сгенерировал.
  • emitted('eventName') возвращает массив всех вызовов конкретного события.

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

Для передачи слотов при монтировании используется опция slots:

const wrapper = mount(MyComponent, {
  slots: {
    default: '<span>Контент слота</span>',
    header: '<h1>Заголовок</h1>'
  }
});

expect(wrapper.html()).toContain('Контент слота');
expect(wrapper.find('h1').exists()).toBe(true);

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


Использование snapshot-тестов

Snapshot-тестирование фиксирует текущую разметку компонента:

expect(wrapper.html()).toMatchSnapshot();

Особенности snapshot-тестов:

  • Позволяют быстро обнаруживать визуальные изменения.
  • Требуют внимательности при тестировании динамических или асинхронных компонентов.
  • Лучше использовать совместно с выборочным тестированием ключевых элементов через find.

Организация тестов

Рекомендуется разделять тесты по категориям:

  1. Тесты структуры DOM: проверка наличия элементов и классов.
  2. Тесты пропсов и состояния: проверка реакции компонента на изменения данных.
  3. Тесты событий: проверка эмита событий и взаимодействия с пользователем.
  4. Тесты слотов и дочерних компонентов: проверка передачи и отображения контента.

Структурированный подход упрощает поддержку тестов и делает их более читаемыми.