Tutorial

How to Test Your Vue Components Using the Jest Testing Framework

Published on March 21, 2020
author

Parthiv Mohan

How to Test Your Vue Components Using the Jest Testing Framework

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.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Parthiv Mohan

author

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.

Still looking for an answer?

Ask a questionSearch for more help

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.

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.