How to Test a Global Event Bus With Vue Test Utils? How to Test a Global Event Bus With Vue Test Utils? vue.js vue.js

How to Test a Global Event Bus With Vue Test Utils?


If component is using global EventBus, eg that's imported outside of given component and assigned to window.EventBus, then it's possible to use global Vue instance to redirect $on or $emit events to wrapper's vm instance. That way you can proceed writing tests as if component is emitting via this.$emit instead of EventBus.$emit:

it('clicking "Settings" button emits "openSettings"', () => {    global.EventBus = new Vue();    global.EventBus.$on('openSettings', (data) => {        wrapper.vm.$emit('openSettings', data);    });    // component emits `EventBus.$emit('openSettings')`    expect(wrapper.emitted('openSettings')).toBeTruthy(); // pass});


Well,

EvtBus.$on('coupon-applied', () => {    console.log('coupon was applied through event bus');});

This code in your spec file won't be called because the mounted wrp component is not using the same EvtBus you are importing in your spec file above.

What you require to test this is an npm package named inject-loader so that you can provide your own implementation(stub) of the EvtBus dependency of your coupon code component.

Somewhat like this

const couponCodeInjector = require('!!vue-loader?inject!src/views/CouponCode');const stubbedModules = {   '../EvtBus.js': {        $on : sandbox.spy((evtName, cb) => cb());     }};const couponCode = couponCodeInjector(stubbedModules);

and then in your unit test you can assert whether the stubbedModules['../EvtBus.js'].$on has been called or not when code.trigger('input');

PS: I haven't used vue-test-utils. So I don't know exactly how to the stubbing with this npm package.

But the main thing you need to do is to find a way to stub your EvtBus dependency in the CouponCode component in such a way that you can apply a spy on it and check whether that spy has been called or not.


Unit tests should focus on testing a single component in isolation. In this case, you want to test if the event is emitted, since that is the job of CouponCode.vue. Remember, unit tests should focus on testing the smallest units of code, and only test one thing at a time. In this case, we care that the event is emitted -- EventBus.test.js is where we test what happens when the event is emitted.

Noe that toBeTruthy is a function - you need (). expect(wrp.emitted('applied')).toBeTruthy is actually not passing, since you need () - at the moment, it is actually doing nothing -- no assertion is made.

What your assertion should look like is:

expect(wrp.emitted('applied')).toBeTruthy()

You can go one step further, and ensure it was only emitted once by doing something like expect(wrp.emitted().applied.length).toBe(1).

You then test InputBus in isolation, too. If you can post the code for that component, we can work through how to test it.

I worked on a big Vue app recently and contributed a lot to the main repo and documentation, so I'm happy to help out wherever I can.

Let me know if that helps or you need more guidance. If possible, post EventBus.vue as well.