Reputation: 1455
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.
Upvotes: 7
Views: 1851
Reputation: 2915
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,
Upvotes: 3