Hybrid Rendering: the secret way to smoothly test Vue.js components
In the article Deep vs Shallow Rendering in Vue.js Tests I showed you how deep and shallow rendering works to create Vue.js tests.
Each of them have their own use case and it could depend in your way of testing and architecting as well.
But… why not having the best of both worlds? Let’s get into Hybrid Rendering.
The Hybrid Rendering consists on stubbing only part of the child components on a test.
For instance, taking back the example from the tip, let's add another component called FoodList
to the App
component:
<template>
<div>
<h3>User List</h3>
<UserList :users="['Rob Wesley']" />
<FoodList :foods="['Tomatoes', 'Carrots']" />
</div>
</template>
<script setup>
import UserList from "./UserList";
import FoodList from "./FoodList";
</script>
Assuming FoodList
has a similar implementation to UserList
, and we're using deep rendering, this test:
import { mount } from "@vue/test-utils";
import App from "@/App";
describe("App.vue", () => {
it("Deep renders the App component", () => {
const wrapper = mount(App);
expect(wrapper.html()).toMatchSnapshot();
});
});
will result in the following snapshot:
<div>
<h3>User List</h3>
<ul>
<li>
Rob Wesley
</li>
</ul>
<ul>
<li>
Tomatoes
</li>
<li>
Carrots
</li>
</ul>
</div>
Now, let's say that for whatsoever reason you want only to deep render UserList
, but not FoodList
.
In that case, you can use the stubs
option of the mount
method in order to indicate which components must be stubbed:
import { mount } from "@vue/test-utils";
import App from "@/App";
describe("App.vue", () => {
it("Hybrid renders the app component", () => {
const wrapper = mount(App, { stubs: ["FoodList"] });
expect(wrapper.html()).toMatchSnapshot();
});
});
Notice I'm stubbing FoodList
. That's the way to apply hybrid rendering in a test, or partial shallow/deep rendering if you're more comfortable with that name.
The generated snapshot in this case will be like:
<div>
<h3>User List</h3>
<ul>
<li>
Rob Wesley
</li>
</ul>
<foodlist-stub foods="Tomatoes,Carrots"></foodlist-stub>
</div>
Keep in mind that this won't work with shallowMount
, since it already stubs all child components. So make sure to use mount
. Learn more in the Stubs and Shallow Mount section on the official docs
Do you have any case in mind where this technique can be useful in your projects? Let me know on Twitter!
That's it for today's tip!
Stay cool 🦄
Related Articles
Deep vs Shallow Rendering in Vue.js Tests
A short article on how to use deep and shallow rendering in Vue.js and what I suggest to use most of the cases using vue test utils.
Mar 3, 2020
Quick Content Testing using Snapshots in Vue.js
Useful tip about how to use snapshot testing in Vue.js the right way and have consistent and coherent tests in your applications
May 28, 2019
Testing logic inside a Vue.js watcher
Tutorial on how to test the logic of a vue.js component watcher instead of testing the framework
Apr 14, 2019
Sponsors
VueDose is proudly supported by its sponsors. If you enjoy it, consider supporting it to ensure the project maintainability.