I'm running into this problem that I can't figure out and looking around can't seem to find anyone asking the same questions...
So, here's my working code:
main.js:
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
window.Vue = Vue
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
methods: {
greetings: function () {
return 'good morning'
}
},
render: h => h(App)
})
router/index.js:
import Vue from 'vue'
import Router from 'vue-router'
import Configurations from '@/components/Configurations'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/configs',
name: 'Configurations',
component: Configurations
}
]
})
App.vue:
<template>
<router-view></router-view>
</template>
<script>
export default {
name: "App"
};
</script>
Configurations.vue:
<template>
<span>{{greetings}}</span>
</template>
<script>
export default {
name: "configurations",
data() {
return {
greetings: ""
};
},
created: function() {
this.greetings = this.$root.greetings();
}
};
</script>
When I run this, it displays a page with the words "good morning" on it. Nothing else. As you can see, the greetings message is defined on the main.js file, because in this scenario I'd like a message to be displayed on all components, ie: a copyright note. So I set the message on the common ancestor to all my components.
From my understanding, to call a method from a "parent" component, you use this.$root.yourMethod() to call it.
Now, the problem is, that if I wish to run a unit-test for the Configurations component, I get an error which leads me to believe that the way I have things set up, I cannot test the this.$root.greetings() because something tells me the testing environment is unaware of the parent-child relationship between the components.
So, when I run:
cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run
Having the following test file set up:
Configurations.spec.js:
import Configurations from '@/components/Configurations'
import Vue from 'vue'
describe('Configurations.vue', () => {
it('should display a greetings message', () => {
const Constructor = Vue.extend(Configurations)
const ConfigurationsComponent = new Constructor().$mount()
expect(ConfigurationsComponent.greetings).to.not.be.undefined;
})
})
I get:
> 16 10 2018 09:28:35.184:INFO [karma]: Karma v1.7.1 server started at
> http://0.0.0.0:3000/ 16 10 2018 09:28:35.191:INFO [launcher]:
> Launching browser PhantomJS with unlimited concurrency 16 10 2018
> 09:28:35.204:INFO [launcher]: Starting browser PhantomJS 16 10 2018
> 09:28:40.977:INFO [PhantomJS 2.1.1 (Windows 8.0.0)]: Connected on
> socket WnDl-mQqmNZQOfyzAAAA with id 10303480 ERROR LOG: '[Vue warn]:
> Error in created hook: "TypeError: is not a constructor (evaluating
> 'this.$root.greetings()')"
(followed by more lines that stack-overflow won't let me post because they contain too many links)
Now, if I were to change
this.greetings = this.$root.greetings()
To:
this.greetings = "good morning";
In the Configurations.vue file, and then run the test command again, I'd get:
> 16 10 2018 09:48:43.174:INFO [karma]: Karma v1.7.1 server started at
> http://0.0.0.0:3000/ 16 10 2018 09:48:43.180:INFO [launcher]:
> Launching browser PhantomJS with unlimited concurrency 16 10 2018
> 09:48:43.555:INFO [launcher]: Starting browser PhantomJS 16 10 2018
> 09:48:49.228:INFO [PhantomJS 2.1.1 (Windows 8.0.0)]: Connected on
> socket o8BQ24wv1QX26SAZAAAA with id 53463701
>
> Configurations.vue
> √ should display a greetings message
>
> PhantomJS 2.1.1 (Windows 8.0.0): Executed 1 of 1 SUCCESS (0.024 secs / 0.017 secs)
>
> TOTAL: 1 SUCCESS
(followed by some other information that's irrelevant)
So, how can I run a unit-test for a component that contains calls to this.$root methods?
Any help is appreciated.
- Lucas