В Vue.js глобальные события часто используются для взаимодействия
компонентов между собой, особенно при работе с событийной шиной
(event bus) или через родительские/дочерние компоненты. Для
корректного тестирования таких взаимодействий в Vue Test
Utils предусмотрены инструменты для имитации, прослушивания и
проверки глобальных событий.
Vue Test Utils позволяет подключать глобальные плагины, миксины и
компоненты через объект global при создании экземпляра
компонента:
import { mount } from '@vue/test-utils'
import MyComponent from '@/components/MyComponent.vue'
const wrapper = mount(MyComponent, {
global: {
plugins: [myEventBusPlugin],
mixins: [myGlobalMixin]
}
})
global.components и global.directives.Это важно для тестирования, если компонент ожидает глобальные обработчики событий или методы, которые обычно доступны во Vue-приложении.
$emit и $onДля проверки реакций на события используется комбинация методов Vue Test Utils и нативных Vue-свойств:
wrapper.vm.$emit('custom-event', { payload: 123 })
expect(wrapper.emitted('custom-event')).toBeTruthy()
expect(wrapper.emitted('custom-event')[0]).toEqual([{ payload: 123 }])
$emit позволяет программно вызвать событие на
экземпляре компонента.emitted() возвращает объект всех вызванных
событий, что позволяет проверять наличие события,
количество вызовов и переданные
данные.Для глобальных событий через шину (event bus) может
применяться мок:
const eventBus = {
$on: jest.fn(),
$emit: jest.fn(),
$off: jest.fn()
}
const wrapper = mount(MyComponent, {
global: {
provide: {
eventBus
}
}
})
wrapper.vm.$root.$emit('global-event', 42)
expect(eventBus.$emit).toHaveBeenCalledWith('global-event', 42)
provide/inject применяется для передачи глобальных
зависимостей и обработки событий между компонентами.В Vue 3 события часто вызываются в асинхронных обработчиках:
await wrapper.vm.$nextTick()
wrapper.vm.$emit('async-event', 'data')
await wrapper.vm.$nextTick()
expect(wrapper.emitted('async-event')[0]).toEqual(['data'])
$nextTick() гарантирует, что Vue завершил реактивные
обновления перед проверкой.watch, computed).Не все глобальные события проходят через $emit. События
DOM (например, click, input) обрабатываются
через trigger:
const button = wrapper.find('button')
await button.trigger('click')
expect(wrapper.emitted('button-click')).toBeTruthy()
trigger имитирует нативное событие на элементе.v-on) или плагины, корректно
реагируют.Правильное тестирование глобальных событий включает проверку их отписки при размонтировании компонента:
const wrapper = mount(MyComponent, {
global: {
provide: {
eventBus
}
}
})
wrapper.unmount()
expect(eventBus.$off).toHaveBeenCalled()
unmount() вызывает метод
beforeUnmount и завершает жизненный цикл компонента.$nextTick() или flushPromises при
промисах.import { mount } from '@vue/test-utils'
import ComponentA from '@/components/ComponentA.vue'
const mockBus = {
$on: jest.fn(),
$emit: jest.fn(),
$off: jest.fn()
}
describe('ComponentA - глобальные события', () => {
let wrapper
beforeEach(() => {
wrapper = mount(ComponentA, {
global: { provide: { eventBus: mockBus } }
})
})
afterEach(() => {
wrapper.unmount()
})
test('вызывает глобальное событие при действии', async () => {
await wrapper.find('button').trigger('click')
expect(mockBus.$emit).toHaveBeenCalledWith('global-event', expect.anything())
})
test('подписка и отписка от событий', () => {
expect(mockBus.$on).toHaveBeenCalledWith('another-event', expect.any(Function))
wrapper.unmount()
expect(mockBus.$off).toHaveBeenCalled()
})
})