Vue Test Utils has an API method called shallowMount()
that:
...creates a
Wrapper
that contains the mounted and rendered Vue component, but with stubbed child components.
I've searched the Vue Test Utils documentation website but failed to find a good explanation of how these stubbed child components behave.
A stub is where you replace an existing implementation of a custom component with a dummy component that doesn't do anything at all, which can simplify an otherwise complex test.
Finding child components is a little different to finding regular HTML elements. There two main ways to assert the presence of child Vue components: findComponent(Component) findComponent({ name: "ComponentName" })
Parent To Child Communication In Vue. To move data from a parent component to a child component in Vue we use something called props. ReactJS also uses a similar convention for sharing data. Props is short for “properties” and is referring to properties set from outside, such as from the parent component.
Components in Vue are composed of three parts; a template (which is like HTML), styles and JavaScript. These can be split into multiple files or the same .
What exactly are stubbed child components?
A stubbed child component is a replacement for a child component rendered by the component under test.
Imagine you have a ParentComponent
component that renders a ChildComponent
:
const ParentComponent = {
template: `
<div>
<button />
<child-component />
</div>
`,
components: {
ChildComponent
}
}
ChildComponent
renders a globally registered component and calls an injected instance method when it's mounted:
const ChildComponent = {
template: `<span><another-component /></span>`,
mounted() {
this.$injectedMethod()
}
}
If you use shallowMount
to mount the ParentComponent
, Vue Test Utils will render a stub of ChildComponent
in place of than the original ChildComponent
. The stub component does not render the ChildComponent
template, and it doesn't have the mounted
lifecycle method.
If you called html
on the ParentComponent
wrapper, you would see the following output:
const wrapper = shallowMount(ParentComponent)
wrapper.html() // <div><button /><child-component-stub /></div>
The stub looks a bit like this:
const Stub = {
props: originalComonent.props,
render(h) {
return h(tagName, this.$options._renderChildren)
}
}
Because the stub component is created with information from the original component, you can use the original component as a selector:
const wrapper = shallowMount(ParentComponent)
wrapper.find(ChildComponent).props()
Vue is unaware that it's rendering a stubbed component. Vue Test Utils sets it so that when Vue attempts to resolve the component, it will resolve with the stubbed component rather than the original.
Which parts of the Vue component lifecycle do they go through?
Stubs go through all parts of the Vue lifecycle.
Is there a way to pre-program their behavior?
Yes, you can create a custom stub and pass it using the stubs
mounting option:
const MyStub = {
template: '<div />',
methods: {
someMethod() {}
}
}
mount(TestComponent, {
stubs: {
'my-stub': MyStub
}
})
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