How to Test Your Vue Project with Jest and Nightwatch

Testing is a vital part of the development cycle and a part of life for programmers and developers. Nobody likes bugs in their code, but they're incredibly annoying when you think your project is done and ready for deployment. But inevitably, someone will find a way to break your code: a certain function has an unforeseen edge case that doesn't work, going to pages in an unpredicted sequence can result in weird outputs, etc.

Of course, one of the best ways to unearth bugs in your code is to get people to test it over and over again, but even before that phase, there are a lot of ways to find problems in your project. That's what I'll be talking about in this article.

For this article, I'll assume that you have some familiarity with Vue.js or any other MVC like React. If you don't, you can easily learn more about components and other things on the Vue website. In this tutorial, I'm going to demonstrate how you can test your Vue project with Jest and Nightwatch.

Table of Contents

  1. Unit Testing with Jest
  2. Snapshot Tests with Jest
  3. Using Nightwatch for E2E Test
  4. Conclusion

Alright. Let's finally get into it.


Unit Testing in Vue with Jest

Unit testing, simply put, is the method of isolating individual parts of your code and seeing if they work as expected.

For example, if we have a method that takes an array and returns the lowest value, then our unit test will pass it a hard-coded array and expect a certain value to be returned. Unit testing is a good way to catch corner cases and bugs.

In Vue.js, there are several things we might want to unit test like:

  • Components requiring certain lifecycle hooks
  • Components passing/accessing props
  • The text output of components
  • The value of a component's data

To conduct these tests, Vue has great built-in options for working with Jest - a popular JS unit testing software.

Jest uses assertions that expect a certain response. For example, with Jest, if we wanted to test a sum(int a, int b) function, we would write.

expect(sum(1, 2)).toBe(3);

However, testing entire components can get a lot tricker. First, we have to wrap our tests in a describe test runner (you can learn more about this in the Jest docs).

Then, we can start declaring our tests. The following is an example of a test that ensures that a Vue component, Component.vue renders what we expect it to.

Our component Component.vue is going to look like this:

<template>
    <div>
        <h1>Hello World!</h1>
    </div>
</template>

To be able to test it, we'll have to write the following test:

import Vue from 'vue'
import Component from "@/components/Component.vue"

describe("Component.vue", () => {
  it("renders the proper default message", () => {
   const Constructor = Vue.extend(Component)
    const vm = new Constructor().$mount()
    // we expect the default output to be "Hello World!"
    expect(vm.$el.textContent).toBe('Hello World!')
  })
})

We can do similar operations for a lot of other tests such as checking styles, computed properties, data values, etc. I won't go into too much detail because a lot of these are easily found with a quick Google Search. Just remember the following format for Jest unit tests.

  1. Import Vue and the components you are testing
  2. Use a describe to wrap your unit tests for each component
  3. Describe each test with an it function that describes the test and performs it.
  4. Use expect and toBe to determine if you get the right output for your services.

To run your Jest test, first, we have to make sure that Jest is installed in your project. Run the following command:

npm install --save-dev jest

Then, in your package.json file, add the following script:

{
  "scripts": {
    "test": "jest"
  }
}

Now that we're all set up, we can run the tests using the line npm test - this will call jest and run all of your tests.

That's the basics of unit testing in Vue, if you want to know a little bit more about it, the Vue docs are a great resource for all developers.

Snapshot Tests with Jest

Another great use for Jest is to do snapshot tests - making sure your UI does not change unexpectedly. The way they work is simple: store a snapshot file that contains the expected UI component, and when you run the test, it will compare the current build of your project to that snapshot.

If they're not equal, either something went wrong or you need to update the snapshot of your project to the current version.

The syntax for snapshot tests, since they also are built-in with Jest, is similar to unit tests. Let's get into an example.

Let's say we have a component called HelloWorld.vue that we don't want to unexpectedly change. This can be anything, but let's just use the following example.

<template>
    <div>
        {{Hello World!}}
    </div>
</template>
<script>
    export default {
        data () {
            return {
                msg: 'Hello World!'
            }
        }
    }
</script>

Our test file will look like this. Note that this can be incorporated into the same file as our unit tests from the previous section.

import Vue from 'vue'
import HelloWorld from "@/components/HelloWorld.vue"

const Constructor = Vue.extend(HelloWorld)
const vm = new Constructor().$mount()

describe("HelloWorld.vue", () => {
  it('should match the snapshot', () => {
    expect(vm.$el).toMatchSnapshot()
  })
})

This creates and mounts a component, which gives us access to its HTML via the $el property.

The first time we run the test, Jest sees that we don't have a snapshot yet, so it creates one. Then, on any future tests, it will compare the current build to the snapshot that we have stored.

If they match, they test passes; if they don't, the test fails and you'll see the differences between the two.

Sometimes, however, we'll need to update the snapshot to include a more recent version of our file. There are two ways to do this.

  1. We can run the command jest --updateSnapshot
  2. In watch mode, we can use the inline commands and press 'U' to update failed screenshot tests.

Using Nightwatch for E2E Test in Vue

First off, what are E2E tests? End to End tests check on an application's entire flow from, you guessed it, end to end/start to finish.

They encompass all of the actions a user might perform on a website: clicking, typing, everything. The purpose of E2E tests is to simulate actions a real user might perform.

E2E tests are useful when you have multiple features that were developed independently but are dependent on each other to run properly. When unit tests simply aren't enough to test your project, E2E tests come to the rescue.

Tools like Nightwatch, which we'll be using here, help mimic a user's typing and clicking on a website to ensure that things are happening as expected. While Nightwatch is not Vue specific (it runs on Node.js) - it's still a great tool for testing Vue apps.

Writing E2E tests is a lot more time consuming because we have to get into the mind of a user and what steps (in order) they'll take to navigate our project.

At the end, similar to in Jest, we use an assert to make sure the output is what it should be.

To add Nightwatch to your project, use the command npm install. Then, you can find the tests are located in a subdirectory within your project.

I think a great example of a test file comes from Nightwatch docs themselves. The following goes to Google, runs a search, and checks if the search bar has the correct input (which should be the text input).

module.exports = {
  'step one: navigate to google' : function (browser) {
    browser
      .url('http://www.google.com')
      .waitForElementVisible('body', 1000)
      .setValue('input[type=text]', 'nightwatch')
      .waitForElementVisible('input[name=btnK]', 1000)
  },
  'step two: click input' : function (browser) {
    browser
      .click('input[name=btnK]')
      .pause(1000)
      .assert.containsText('#main', 'Night Watch')
      .end();
  }
};

Now that we have a test, to run your test, just simply call nightwatch path/to/test.js in your Terminal.

As you can see, Nightwatch uses CSS selectors in order to interact with your site. This is a great way of seeing what will happen in different scenarios.

One benefit of running E2E tests is that it forces you to think about how people will use your site. Overall it's just a helpful tool for developers to think about their site from an end user's perspective.

Another nice thing about Nightwatch is that you can change the URLs to run on http://localhost:PORT so you don't have to upload your project to a dedicated server to conduct these tests.

Conclusion

Testing is a vital part of every development cycle. It helps catch bugs, gives developers more confidence in their code, and helps create a better product.

In this article, we've learned the basics of testing Vue components with unit, snapshot, and E2E testing. While this is only the basics of testing, it should be enough to get you started and you should also know where to go to find more (the docs).

Let me know if you have any questions and please share this tutorial with your Vue friends!

Matt Maribojoc's photo

Matt Maribojoc

Pittsburgh, PA

matt_maribojoc
Write your comment…

In Snapshot Tests with Jest example, I think, Template should have {{ msg }} not {{ Hello World! }}

Reply to this…