by Edd Yerburgh

Vue Test Utils and Jest: how to write simple unit tests for Vue components

In this tutorial I’m going to show you how to test Vue components.

We’re going to write unit tests and snapshot tests with Jest and Vue Test Utils. All without Webpack.

This tutorial is for users familiar with unit testing. If you’re new to unit testing check out my article on unit testing Vue components for beginners.

Setup

I’ve made a simple starter project. Git clone it into a directory:

git clone https://github.com/eddyerburgh/vue-unit-test-starter.git

cd into it and install the dependencies:

cd vue-unit-test-starter && npm install

When the dependencies are installed, run the development server:

npm run dev

Now we can get back to the code.

One thing to talk about is aliases. Aliases are a way to use shorthand notation to import files. Instead of long import statements like the one below:

import someModule from '../../../../../src/components/someModule'

You can use a shorthand notation, or alias. a common alias is the @ symbol, which resolves to the src directory:

import someModule from '@/components/someModule'

Note: You can set any alias you want, but the vue-cli projects use @ to refer to the src directory.

In vue-cli projects, Webpack is used to add the functionality. This is great, but we aren’t using Webpack to run our tests. We need another way to resolve aliases.

That’s where babel comes in. There’s a plugin — babel-plugin-module-resolver — that resolves aliases in babel. You can see it in the .babelrc. It’s only used in the test environment, because when you run the dev or production build, Webpack does the alias resolving.

Check out this file:

Ok, now you’ve got an overview of the project, it’s time to add Jest.

Jest

Jest is a test framework. It’s one of the fastest testing frameworks for Vue single file components (SFCs).

As well as running tests, Jest comes with a load of other features out the box, like mocks, code coverage and snapshot testing.

First thing to do is install Jest:

npm install --save-dev jest

To test SFCs, you need to compile them into JavaScript before you run the tests. If you try and run an uncompiled SFC, you’ll get a syntax error.

Jest doesn’t compile .vue files out the box. You need to tell it to compile them. You do this by adding a jest field to the package.json.

Add the code below to your package.json.

"jest": {    "moduleFileExtensions": [      "js",      "json",      "vue"    ],    "transform": {      "^.+\\.js$": "<rootDir>/node_modules/babel-jest",      ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"    }  }

You’ll see a moduleFileExtensions field. This tells Jest to run files with a .vue extension, as well as .js and .json.

There’s also a transform field. This tells Jest how to compile files before running them. It matches all .js files, and compiles with babel-jest. All .vue files are compiled with vue-jest.

These are custom transforms built for Jest. babel-jest, compiles JavaScript. vue-jest takes .vue files and compiles them into JavaScript.

You need to install both packages:

npm install --save-dev babel-jest vue-jest

Ok cool, now you should add a smoke test, to make sure everything’s working.

In src/components create a __tests__ directory. Add a MessageToggle.spec.js file. So the full file path will be src/components/__tests__/MessageToggle.spec.js.

Copy the code below into the file:

Jest runs all .js files in __tests__ directory automatically. It even adds a test environment variable, so all your test script does is run Jest.

In the scripts field of your package.json add the unit script:

"unit": "jest"

Now run the script:

npm run unit

Great, first passing test ?.

Now you’re going to write more complicated tests using Vue Test Utils.

Vue Test Utils

Vue Test Utils is in beta at the moment, but you can use it now without a problem. The API is pretty much finalized.

Install it:

npm install --save-dev @vue/test-utils

Now you’re going to replace the test in MessageToggle.spec.js with tests using Vue Test Utils.

Copy the code below into src/components/__tests__/MessageToggle.spec.js

Here, we can use the mount function to return a wrapper object. the wrapper contains some helper methods, like text, that help assert components. You can see a full list in the docs.

Ok, let’s add a more complicated test that performs an action on the Messagetoggle component. Copy the code below into MessageToggle.spec.js:

This time, we’re clicking a button (#toggle-message) in MessageToggle and checking that the <;p> tag text has changed correctly.

Now run the test script:

npm run unit

Woop, passing tests! ?

Vue Test Utils abstracts away the Vue internals. So all you need to do is learn the Vue Test Utils API.

Now you’re going to write a test for the List component. The List component takes props, luckily Vue Test Utils gives us a way to pass props when mounting the component.

Create a file /src/components/__tests__/List.spec.js, and paste in the code below

This time you’ll notice we use the shallow function. This is the same as mount, except it only renders the component one level deep. Generally, it’s best to use shallow.

Now you’ve written some unit tests, it’s time to look at snapshot testing.

Snapshot testing

Jest has this great feature called snapshot testing.

Snapshot testing basically takes a copy of your component tree as a string, and then compares against it each time you run your tests. If the rendered component HTML changes, the test fails.

Let’s add a snapshot test to Messag.spec.js.

You need to render the component to a string using the vue-server-renderer. The string returned isn’t very pretty, so you should add jest-serializer-vue to prettify your snapshots.

npm install --save-dev vue-server-renderer jest-serializer-vue

You also need to tell Jest to use the serializer. Add a snapshotSerializers field inside the jest field in yourpackage.json:

"snapshotSerializers": [    "<rootDir>/node_modules/jest-serializer-vue"]

Now update List.spec.js to include a snapshot test:

This test shallow mounts the component, and renders it to an HTML string with vue-server-renderer.

Now run your tests:

npm run unit

You’ll see some new output about a snapshot being saved. go have a look in src/components/__tests__/__snapshots__/List.spec.js.snap:

// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`List.vue has same HTML structure 1`] = `<ul>    <li>        list item one    </li>    <li>        list item two    </li></ul>`;

Cool, a snapshot. ?

Now if the markup of List.vue changes, Jest will warn you the snapshot changed when you run your tests.

Conclusion

Now you’ve set up unit tests and snapshot tests with Jest and Vue Test Utils.

I skipped over a few concepts. You can look at the finished repository on GitHub if your project didn’t work correctly.

Jest has loads more features to make testing easier.

Vue Test Utils also has a lot more methods — check out the docs.

Unit testing Vue components has never been easier, so get out there and write some tests!

If you learned something from this article, share and give a ? to get the word out!