// Tutorial //

How to Test Your Vue Components Using the Jest Testing Framework

Published on March 21, 2020
Default avatar
By Parthiv Mohan
Developer and author at DigitalOcean.
How to Test Your Vue Components Using the Jest Testing Framework

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Introduction

Jest is a popular JavaScript testing framework that comes packed with a lot of goodies for developers. If you’re completely unfamiliar with how Jest works in general, I recommend you start with this introduction. Once you understand the basics of Jest, you’re ready to jump right in and see how it can be used to test your Vue apps.

Setup and Installing Dependencies

If you don’t have the Vue CLI installed on your machine already, start by running either:

  1. npm install -g @vue/cli

or, if you prefer Yarn:

  1. yarn global add @vue/cli

Now you will be able to run the vue command from the command line. Let’s create a Vue app called alligator-test.

  1. vue create alligator-test

Choose the default preset at the prompt (hit the enter key). After that, run the following command to add our testing dependencies (@vue/cli-plugin-unit-jest and @vue/test-utils):

  1. npm install @vue/cli-plugin-unit-jest @vue/test-utils

Next, modify your project’s package.json file to have an entry in scripts which says "test": "jest".

Then, create a file jest.config.js with the following content:

jest.config.js
module.exports = {
  preset: '@vue/cli-plugin-unit-jest'
}

Now, open the alligator-test directory in your code editor of choice.

Coding Up a Simple App

Let’s make some changes to the default files that the vue-cli creates for us.

Delete the src/components directory and modify App.vue as such:

App.vue
<template>
  <div id="app">
      <div>
        <h3>Let us test your arithmetic.</h3>
        <p>What is the sum of the two numbers?</p>
        <div class="inline">
          <p>{{ x1 }} + {{ x2 }} =</p> <input v-model="guess"> <button v-on:click="check">Check Answer</button>
        </div>
        <button v-on:click="refresh">Refresh</button>
        <p>{{message}}</p>
      </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      x1: Math.ceil(Math.random() * 100),
      x2: Math.ceil(Math.random() * 100),
      guess: "",
      message: ""
    }
  },
  methods: {
    check() {
      if (this.x1 + this.x2 === parseInt(this.guess)) {
        this.message = "SUCCESS!"
      } else {
        this.message = "TRY AGAIN"
      }
    },
    refresh() {
      this.x1 = Math.ceil(Math.random() * 100);
      this.x2 = Math.ceil(Math.random() * 100);
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.inline * {
  display: inline-block;
}
img {
  height: 350px;
}
</style>

Take a look through the code and see if you can figure out what the app does.

Then go ahead and run npm run serve from the root directory of your project.

Now you head over to localhost:8080 in your browser and see the working app.

Try making a few guesses! Hopefully, you can pass the test before we get to writing our tests.

Testing the App with Jest

Create a folder called __tests__ in the root directory of your project, which is standard jest convention.

Inside __tests__, create a file called app.spec.js. By default jest will catch any test files (searching recursively through folders) in your project that are named *.spec.js or *.test.js.

At the top of app.spec.js we’re going to import the following from @vue/test-utils as well as our App component itself:

import { mount } from '@vue/test-utils'
import App from './../src/App.vue'

Let’s write our first test.

describe('App', () => {
  // Inspect the raw component options
  it('has data', () => {
    expect(typeof App.data).toBe('function')
  })
})

Run npm test in your Terminal – the test should pass! This is a pretty basic test which checks if the data for our component is a function. The way we wrote it back in the coding phase of this tutorial, we indeed defined it as a function.

Let’s add another describe block to our test file.

describe('Mounted App', () => {
  const wrapper = mount(App);

  test('does a wrapper exist', () => {
    expect(wrapper.exists()).toBe(true)
  })
})

This time we are mounting the component, which gives us back a wrapper. A wrapper is a mock Vue instance.

Warning: Since publication isVueInstance has been deprecated. The test for “is a Vue instance” has been rewritten to “does a wrapper exist”.

We can use it to validate whether certain values are present using Jest’s expect function. We can write tests like this:

it('renders the correct markup', () => {
  expect(wrapper.html()).toContain('What is the sum of the two numbers?')
})

And this:

// it's also easy to check for the existence of elements
it('has a button', () => {
  expect(wrapper.find('button').exists()).toBe(true)
})

Warning: Since publication contains has been deprecated. wrapper.contains() has been replaced with wrapper.find().

These tests all pass! Let’s write some tests for the app’s more Vue-specific functionality.

it('renders correctly with different data', async () => {
  wrapper.setData({ x1: 5, x2: 10 })
  await wrapper.vm.$nextTick()
  expect(wrapper.text()).toContain('10')
})

setData allows you to set the component’s data. Since those variables were initialized in data, they are reactive. When we are mocking our component however, we must call $nextTick() on wrapper.vm, which is the component underlying the wrapper. Then, we can find that our reactive properties are updated.

Finally, we’re going to test whether our app gives the correct output according to what we intend it to do – test addition!

it('button click without correct sum', () => {
  expect(wrapper.vm.message).toBe("")
  const button = wrapper.find('button')
  button.trigger('click')
  expect(wrapper.vm.message).toBe('TRY AGAIN')
})

wrapper.find returns a wrapper for the button element (though there are 2 buttons on our page, the one that we want is the first button on the page so it gets grabbed). x1 and x2 are set from our previous test. But guess, the variable that is connected to the input element via v-model, is not. So, when the button for submission is clicked, the correct sum has not been entered. Hence we expect the message to be TRY AGAIN. When you run npm test the test should pass.

it('button click with correct sum', () => {
  wrapper.setData({ guess: "15" })
  const button = wrapper.find('button')
  button.trigger('click')
  expect(wrapper.vm.message).toBe('SUCCESS!')
})

On the other hand, when we set the sum to be correct, wrapper.vm.message will say ‘SUCCESS!’

Conclusion

I hope this tutorial was useful to you in seeing how to get started with testing Vue.js with Jest! Good luck out there. Test your app!

From this point, if you’re interested in diving deeper into what Jest can do, I’d recommend reading up on Snapshot testing.


Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.

Sign up
About the authors
Default avatar
Developer and author at DigitalOcean.

Still looking for an answer?

Was this helpful?
3 Comments

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

I’m new to Jest and trying to get it working with Vue was proving to be a nightmare. This tutorial is the first one I’ve found that actually works with Jest and ES6+ modules. Very much appreciated.

So awesome you updated this to accomodate isVueIntance() deprecation REALLY FAST!

Thank you for this tutorial.