DEV Community

Alex Jover
Alex Jover

Posted on • Originally published at vuedose.tips on

Hybrid Rendering: the secret way to smoothly test Vue.js components

Originally posted on VueDose.tips

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>
Enter fullscreen mode Exit fullscreen mode

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();
  });
});
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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();
  });
});

Enter fullscreen mode Exit fullscreen mode

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>

Enter fullscreen mode Exit fullscreen mode

Keep in mind that this won't work with shallowMount, since it already stubs all child components. So make sure to use mount.

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 ๐Ÿฆ„

Top comments (0)