Javascript is required
Mokkapps LogoMichael Hoffmann

Vue Tip: Test Vue Components Using Vue Testing Library

Michael Hoffmann (Mokkapps) - Senior Frontend Developer (Freelancer)
Michael Hoffmann
Aug 19, 2022
2 min read
Vue Tip: Test Vue Components Using Vue Testing Library Image

Vue Testing Library is my preferred Vue.js testing library. It is built on top of @vue/test-utils, the official testing library for Vue.

If we write tests for our Vue components, we want them to be maintainable. Therefore, our tests should not include implementation details of our components.

The primary guiding principle of Vue Testing Library is:

The more your tests resemble the way your software is used, the more confidence they can give you.

So rather than dealing with instances of rendered Vue components, the tests will work with actual DOM nodes. The library provides methods to query the DOM the same way the user would. Users are looking for specific text or a button to click. They don't look for the nth child of a div with the class .button-container.

Let's take a look at a simple example:

<template>  <p>Times clicked: {{ count }}</p>  <button @click="increment">Increment</button></template><script setup>const count = ref(0)const increment = () => (count.value = count.value + 1)</script>
import { render, screen, fireEvent } from '@testing-library/vue'import Button from './Button'test('increments value on click', async () => {  // The `render` method renders the component into the document.  // It also binds to `screen` all the available queries to interact with  // the component.  render(Button)  // queryByText returns the first matching node for the provided text  // or returns null.  expect(screen.queryByText('Times clicked: 0')).toBeTruthy()  // getByText returns the first matching node for the provided text  // or throws an error.  const button = screen.getByText('increment')  // Click a couple of times.  await  await  expect(screen.queryByText('Times clicked: 2')).toBeTruthy()})

The byText query could be replaced by a more suitable query like getByRole, see Which query should I use?.


Installing jest-dom adds some useful assertions like .toBeInTheDocument(). In our example, we could then change the assertion to expect(screen.queryByText('Times clicked: 0')).toBeInTheDocument().

This test does not contain any implementation details of our Button component, so it's unlikely to break even under heavy refactoring.

If you liked this Vue tip, follow me on Twitter to get notified about new tips, blog posts, and more. Alternatively (or additionally), you can subscribe to my weekly Vue newsletter.