Reputation: 61
My component has the following computed code:
textButton() {
const key = this.$root.feature.name === //...
// ...
},
Right now I'm trying desperately to mock "root" in my test, but I just don't know how. Any tips?
Upvotes: 3
Views: 5456
Reputation: 171
For people having the same problem in Vue 3 and Vue Test Utils v2:
I recommend wrapping $root
accesses with component computed variables. So, replace this:
methods: {
textButton() {
const key = this.$root.feature.name === //...
// ...
},
}
with this:
computed: {
feature() {
return this.$root.feature;
}
},
methods: {
textButton() {
const key = this.feature.name === //...
// ...
},
}
And then, in test implementation, mock this computed variable before mounting:
import { shallowMount } from '@vue/test-utils';
import MyComponent from '<path here>';
MyComponent.computed.feature = jest.fn(() => { name: 'random feature name' });
const wrapper = shallowMount(MyComponent);
...
This way you won't need to mock $root
anymore.
Upvotes: 0
Reputation: 121
You may use a Vue Plugin inside the test to inject the mock data into localVue
so that your components can access it.
import {createLocalVue, shallow} from '@vue/test-utils';
const localVue = createLocalVue();
localVue.use((Vue) => {
Vue.prototype.feature = {
name: 'Fake news!'
};
});
let wrapper = shallow(Component, {
localVue
});
I had the same issues a while ago and I came to the conclusion that accessing this.$root
may be a sign that you have to further improve the way you communicate with components. Consider using the plugin structure to define globally available properties and methods not only inside the test for example. Mixins might be helpful as well.
Upvotes: 3
Reputation: 441
Solution from https://github.com/vuejs/vue-test-utils/issues/481#issuecomment-423716430:
You can set $root on the vm directly:
wrapper.vm.$root = { loading: true }
wrapper.vm.$forceUpdate()
Or you can pass in a parent component with the parentComponent mounting option. In VTU, the paren will be the $root:
const Parent = {
data() {
return {
loading: "asdas"
}
}
}
const wrapper = shallowMount(TestComponent, {
parentComponent: Parent
})
Upvotes: 5
Reputation: 945
There are two ways to accomplish this with vue-test-utils
.
One way, as mentioned above, is using the mocks
mounting option.
const wrapper = shallowMount(Foo, {
mocks: {
$root: {
feature: {
name: "Some Val"
}
}
}
})
But in your case, you probably want to use the computed mouting option, which is a bit cleaner than a deep object in mocks
.
const wrapper = shallowMount(Foo, {
computed: {
textButton: () => "Some Value"
}
})
Hopefully this helps!
If you are interested I am compiling a collection of simple guides on how to test Vue components here. It's under development, but feel free to ask make an issue if you need help with other related things to testing Vue components.
Upvotes: 4
Reputation: 437
Vue test utils provides you with the ability to inject mocks when you mount (or shallow mount) your component.
const $root = 'some test value or jasmine spy'
let wrapper = shallow(ComponentToTest, {
mocks: { $root }
})
That should then be easily testable. Hope that helps
Upvotes: 5