В Vue.js компоненты часто взаимодействуют между собой через
кастомные события. При тестировании компонентов важно
уметь эмулировать эти события и проверять, как
компонент реагирует на них. Библиотека Vue Test Utils
предоставляет мощные средства для работы с событиями, включая методы
trigger, emit и возможности проверки вызова
событий.
В Vue компонент может генерировать событие с помощью метода
this.$emit. Событие имеет название и может
передавать аргументы:
export default {
methods: {
sendMessage() {
this.$emit('message-sent', 'Hello, Vue!');
}
}
}
В тестах необходимо проверить, что событие было вызвано и переданы корректные данные.
trigger для
событий DOMМетод trigger используется для эмуляции
DOM-событий на элементе компонента. Он принимает
название события и объект с параметрами
события:
import { mount } from '@vue/test-utils';
import ButtonComponent from '@/components/ButtonComponent.vue';
const wrapper = mount(ButtonComponent);
// Эмулируем клик по кнопке
await wrapper.find('button').trigger('click');
trigger автоматически инициирует события на
уровне DOM, а если компонент внутри обработчика использует
$emit, событие будет вызвано.
Vue Test Utils предоставляет метод emitted(), который
возвращает объект с событиями, сгенерированными компонентом:
const wrapper = mount(ButtonComponent);
// Триггер клика
await wrapper.find('button').trigger('click');
// Проверка вызова события
expect(wrapper.emitted()['message-sent']).toBeTruthy();
// Проверка количества вызовов
expect(wrapper.emitted()['message-sent'].length).toBe(1);
// Проверка переданных аргументов
expect(wrapper.emitted()['message-sent'][0]).toEqual(['Hello, Vue!']);
Ключевые моменты:
wrapper.emitted() возвращает объект, где ключи
— названия событий, а значения — массивы вызовов.Иногда необходимо эмулировать событие, исходящее от дочернего компонента, чтобы проверить реакцию родителя:
const Child = {
template: '<button @click="$emit(\'child-click\', 42)">Click</button>'
};
const Parent = {
components: { Child },
template: '<Child @child-click="handleClick"/>',
methods: {
handleClick(value) {
this.$emit('parent-receive', value);
}
}
};
const wrapper = mount(Parent);
// Эмулируем событие на дочернем компоненте
await wrapper.findComponent(Child).vm.$emit('child-click', 42);
// Проверка реакции родителя
expect(wrapper.emitted()['parent-receive'][0]).toEqual([42]);
Особенности:
vm.$emit позволяет напрямую триггерить
событие компонента.findComponent обеспечивает поиск вложенного компонента
внутри тестируемого компонента.trigger и vm.$emit поддерживают передачу
параметров события, включая объект события для DOM:
await wrapper.find('input').trigger('input', {
target: { value: 'Vue Test' }
});
expect(wrapper.emitted().input[0]).toEqual(['Vue Test']);
Таким образом, можно имитировать ввод текста, фокус, нажатие клавиш и другие пользовательские действия.
Многие события могут вызывать асинхронные действия в
компоненте (например, обновление состояния через
nextTick):
import { nextTick } from 'vue';
await wrapper.find('button').trigger('click');
await nextTick();
expect(wrapper.emitted()['message-sent']).toBeTruthy();
Использование await nextTick() гарантирует, что все
реактивные изменения завершены перед проверкой событий.
Тестирование сложных компонентов требует проверки последовательности событий:
await wrapper.find('button').trigger('click');
await wrapper.find('input').trigger('input', { target: { value: 'Test' } });
expect(wrapper.emitted()['message-sent'][0]).toEqual(['Click']);
expect(wrapper.emitted().input[0]).toEqual(['Test']);
Vue Test Utils позволяет отслеживать любое количество событий одновременно, что упрощает проверку логики взаимодействия компонентов.
trigger подходит для DOM-событий
(click, input, focus и
т.д.).
vm.$emit удобен для кастомных событий
компонентов.
Использовать wrapper.emitted() для проверки:
Для асинхронных реакций использовать
await nextTick().
Эти возможности делают Vue Test Utils универсальным инструментом для проверки взаимодействия компонентов через события, обеспечивая детальный контроль над логикой и передаваемыми данными.