I declare an event bus in my global app.js
like so:
window.Event = new Vue();
The component looks like
export default {
data() {
return {
hasError: false,
zip: '',
};
},
methods: {
setZip: function() {
this.hasError = false;
this.$emit('setZip', this.zip);
},
},
mounted() {
Event.$on('showErrors', (errors) => {
this.hasError = errors.zip ? true : false;
});
this.zip = this.editZip;
},
props: [
'editZip'
],
}
I unit test my components with ava
with the following helpers/setup.js
:
const browserEnv = require('browser-env');
const hook = require('vue-node');
const { join } = require('path');
// Setup a fake browser environment
browserEnv();
// Pass an absolute path to your webpack configuration to the hook function.
hook(join(__dirname, './webpack.config.js'));
The webpack.config.js
looks like:
module.exports = {
module: {
loaders: [
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.js', '.vue'],
},
};
When running the following test
import Vue from 'vue/dist/vue.js';
import test from 'ava';
import Zip from '../../resources/assets/js/components/Company/Zip.vue';
let vm;
test.beforeEach(t => {
let Z = Vue.extend(Zip);
vm = new Z({ propsData: {
editZip: 1220
}}).$mount();
});
test('that it renders a div with class form-group', t => {
t.is(vm.$el.className, 'form-group');
});
it passes, but the following error gets thrown:
[Vue warn]: Error in mounted hook: "TypeError: Event.$on is not a function"
(found in <Root>)
TypeError: Event.$on is not a function
at VueComponent.mounted (/mnt/c/code/leaflets/resources/assets/js/components/Company/City.vue:107:15)
at callHook (/mnt/c/code/leaflets/node_modules/vue/dist/vue.js:2530:21)
at mountComponent (/mnt/c/code/leaflets/node_modules/vue/dist/vue.js:2424:5)
at VueComponent.Vue$3.$mount (/mnt/c/code/leaflets/node_modules/vue/dist/vue.js:7512:10)
at VueComponent.Vue$3.$mount (/mnt/c/code/leaflets/node_modules/vue/dist/vue.js:9592:16)
at Test._ava2.default.beforeEach.t [as fn] (/mnt/c/code/leaflets/tests/js/CompanyCity.js:12:9)
at Test.callFn (/mnt/c/code/leaflets/node_modules/ava/lib/test.js:281:18)
at Test.run (/mnt/c/code/leaflets/node_modules/ava/lib/test.js:294:23)
at runNext (/mnt/c/code/leaflets/node_modules/ava/lib/sequence.js:58:44)
at Sequence.run (/mnt/c/code/leaflets/node_modules/ava/lib/sequence.js:90:10)
at Concurrent.run (/mnt/c/code/leaflets/node_modules/ava/lib/concurrent.js:41:37)
at runNext (/mnt/c/code/leaflets/node_modules/ava/lib/sequence.js:58:44)
at Sequence.run (/mnt/c/code/leaflets/node_modules/ava/lib/sequence.js:90:10)
at runNext (/mnt/c/code/leaflets/node_modules/ava/lib/sequence.js:58:44)
at Sequence.run (/mnt/c/code/leaflets/node_modules/ava/lib/sequence.js:90:10)
at Bluebird.try (/mnt/c/code/leaflets/node_modules/ava/lib/runner.js:214:48)
at tryCatcher (/mnt/c/code/leaflets/node_modules/bluebird/js/release/util.js:16:23)
at Function.Promise.attempt.Promise.try (/mnt/c/code/leaflets/node_modules/bluebird/js/release/method.js:39:29)
at Runner.run (/mnt/c/code/leaflets/node_modules/ava/lib/runner.js:214:22)
at process.on.options (/mnt/c/code/leaflets/node_modules/ava/lib/main.js:82:10)
at emitOne (events.js:96:13)
at process.emit (events.js:191:7)
at process.on.message (/mnt/c/code/leaflets/node_modules/ava/lib/process-adapter.js:14:10)
at emitTwo (events.js:106:13)
at process.emit (events.js:194:7)
at process.nextTick (internal/child_process.js:766:12)
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)
I can't figure out where to declare the window.Event = new Vue()
in my test, so that the tested component can access the Event
variable.
Unit tests are the smallest and most simple of tests - they make assertions on the smallest units of work, isolating each part of a single component. Snapshot tests save the markup of your Vue component, and compare to the new one generated each time the test runs.
An Event Bus is nothing but a global Vue instance that is imported by the components involved in communication and passing data. It makes use of the $on, $emit, and $off properties of the Vue object to emit out events and pass on data.
1. Component Testing with Vue Test Utils & Jest. Jest is a well-liked JavaScript testing framework that comes packed with many goodies for developers focusing on simplicity. It's one of the fastest testing frameworks for Vue single-file components.
End-to-end tests do not import any of your Vue application's code, but instead rely completely on testing your application by navigating through entire pages in a real browser. End-to-end tests validate many of the layers in your application.
First of all, I'd recommend to remove the global EventBus from the window object (if you can), as it's not often ideal to rely on global props that could get overwritten by some other parts of the code leading to undesired effects.
You can just create a event-bus.js
file and create the event bus in there:
import Vue from 'vue';
export const EventBus = new Vue();
Then you can just import that file from any other component that needs access to the event bus like
import {EventBus} from '/path/to/event-bus.js'
From there, you can use it exactly as you're currently using it.
However, if you have to keep your EventBus in the window object for some reason, you'll have to also mock it so you can test it.
First, when you call the browserEnv
function, you'll need to mock the window object by doing this:
browserEnv(['window']);
Then, window will be available as a global variable, but you will need to change the implementation of your component to explicitly grab the EventBus from the window object, like:
window.EventBus
You can also define it globally in your component like:
const { EventBus } = window
Let me know if this works.
Thanks,
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With