Edd Yerburgh Software Engineer

How to unit test Vue components

It seems everybody’s using Vue.js nowadays, and it’s easy to see why. It’s fast, easy to learn and has amazing documentation. But how do we unit test Vue components?

Note: This tutorial assumes you’re familiar with unit testing, webpack, ES6, mocha, chai and karma. If you’re not, check out How to unit test Vue components for beginners.

Testing Vue Components

There’s a useful section on unit testing in the Vue docs. It goes over the basics of unit testing Vue components, and it’s worth checking out before we go further.

To test .vue components, you need to compile the files before running your tests. We can do this is with webpack and vue-loader.

If you’re using karma to run your tests, you can use the preProcessors option in the Karma configuration file. Have a look at this project to see a working example.

Alternatively, you can use mocha-webpack to compile your tests with webpack before running them with mocha. All you need to do is pass a webpack config to webpack-config in an npm script. For mount to work you need some browser methods, in Karma we have these methods available(since we’re running tests in the browser), but running tests in mocha we don’t. To solve this, you can use jsdom to add browser globals before running your test suite. Here’s a working example.

Now that’s taken care of, it’s time to test!

The basic idea is to create a Vue instance with the component and call the $mount method to render the instance in memory.

const vm = new Vue(MyComponent).$mount()

The Vue instance has as $el property which is a DOM node. You use this to make assertions by calling DOM node methods or accessing it’s properties.

expect(vm.$el.querySelector('.foo')).to.equal(true)
expect(vm.$el.querySelector('.foo').style.color).to.equal('red')

This works, but some common testing utilities (like dispatching a click) are quite verbose:

const foo = vm.$el.querySelector('.foo')
const eventObject = new window.Event(type)
foo.dispatchEvent(eventObject)
vm._watcher.run()

To make our lives easier, we can use a test utility library.

Testing Vue components using avoriaz

avoriaz is similar to enzyme (a react testing utils library). It shares methods like find, trigger and contains.

To get started, install avoriaz and chai in your project from npm.

npm install --save-dev avoriaz chai

Now, in your test file import mount from avoriaz and expect from chai:

import { mount } from 'avoriaz'
import { expect } from 'chai'

If you’ve set up your test environment using mocha-webpack or Karma then you’re ready to go. If you’re having trouble, git clone the avoriaz mocha example project, and run npm install to get the project up and running.

git clone git@github.com:eddyerburgh/avoriaz-mocha-example.git && cd avoriaz-mocha-example && npm install

Working? Run npm test to make sure everything is fine.

Now, time to test.

describe('Bar.vue', () => {
  it('renders a div with class bar', () => {
    const wrapper = mount(Bar)
    expect(wrapper.is('div')).to.equal(true)
    expect(wrapper.hasClass('bar')).to.equal(true)
  })
  it('renders 4 list elements inside .parent-ul', () => {
    const wrapper = mount(Bar)
    const listElements = wrapper.find('.parent-ul li')
    expect(listElements.length).to.equal(4)
  })
})

The find method returns an array of element wrappers. To see the full list of methods available to a wrapper, check out the docs.

The find method takes any CSS selector, or a Vue component as a parameter. So you can assert whether a Vue component was rendered or not.

Another useful method is trigger. This dispatches a DOM event on the wrapper element.

describe('Bar.vue', () => {
  it('renders h1 which changes text when button is clicked', () => {
    const expectedMessage = 'new message'
    const wrapper = mount(Foo)
    const button = wrapper.find('#change-message')[0]
    button.trigger('click')
    expect(wrapper.find('h1')[0].text()).to.equal(expectedMessage)
  })
})

For full examples, check out the mocha-webpack example project.

For a complete list of avoriaz methods, check out the docs.

If you have any questions, leave a comment and I’ll get back to you.