Getting Started with Vue Test Utils

Sep 14, 2020

Vue Test Utils is Vue's official library for testing Vue components from Node.js. For example, suppose you have a simple counter component:

const Vue = require('vue');

module.exports = Vue.component('App', {
  data: () => ({ count: 0 }),
  methods: {
    increment: function increment() {
      ++this.count;
    }
  },
  template: `
    <div>
      <span>{{count}}</span>
      <button @click="increment">Increment</button>
    </div>
  `
});

Here's how you can mount and interact with the above component using Vue Test Utils. Note that Vue Test Utils requires JSDom to work. The below example is a standalone script that you can run in Node.js, no test runners required.

// Make sure to put jsdom before `require('vue')`!
require('jsdom-global')();

const Vue = require('vue');
const { mount } = require('@vue/test-utils');

// Must be a component, **not** a Vue instance, otherwise you get:
// "Failed to mount component: template or render function not defined"
const component = Vue.component('App', {
  data: () => ({ count: 0 }),
  methods: {
    increment: function increment() {
      ++this.count;
    }
  },
  template: `
    <div>
      <span>{{count}}</span>
      <button @click="increment">Increment</button>
    </div>
  `
});

const wrapper = mount(component);

run().catch(err => console.log(err));

async function run() {
  wrapper.html(); // <div><span>0</span> <button>Increment</button></div>

  // Note that `trigger()` is an async function
  await wrapper.find('button').trigger('click');
  wrapper.html(); // <div><span>1</span> <button>Increment</button></div>
}

Testing with Mocha

Mocha is a minimal test framework, so you can easily port the above script into Mocha tests. Plus, Mocha makes it easy to clean up JSDom when your tests are done, so you don't have to worry about polluting your Node.js environment if you want to run Node tests.

const assert = require('assert');

describe('App', function() {
  let Vue;
  let mount;
  let cleanup;
  let wrapper;

  before(async function() {
    cleanup = require('jsdom-global')();
    Vue = require('vue');
    mount = require('@vue/test-utils').mount;
  });

  after(() => cleanup());

  beforeEach(function() {
    const component = Vue.component('App', {
      data: () => ({ count: 0 }),
      methods: {
        increment: function increment() {
          ++this.count;
        }
      },
      template: `
        <div>
          <span>{{count}}</span>
          <button @click="increment">Increment</button>
        </div>
      `
    });
    wrapper = mount(component);
  });

  it('increments when you click', async function() {
    assert.ok(wrapper.html().includes('<span>0</span'));

    await wrapper.find('button').trigger('click');
    assert.ok(wrapper.html().includes('<span>1</span'));
  });
});

Vue School has some of our favorite Vue video courses. Their Vue.js Master Class walks you through building a real world application, and does a great job of teaching you how to integrate Vue with Firebase. Check it out!


Did you find this tutorial useful? Say thanks by starring our repo on GitHub!

More Vue Tutorials