To test my Vue.js apps I use vue-test-utils which contains all the utilities you need for testing Vue components.

The easiest way to get started is by using the Vue.js CLI. If you don’t have it installed already, just run npm install -g @vue/cli in your terminal.

Create your first app

Once you installed the Vue.js CLI, in terminal run vue create hello-world to create a new Vue app. Here you will get a couple of options like below:

Vue CLI v3.2.1
? Please pick a preset: 
  default (babel, eslint) 
❯ Manually select features 

Make sure you select “Manually select features”.

Next you will get the following options:

? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to inver
t selection)
 ◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◯ Router
 ◯ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
 ◉ Unit Testing
 ◯ E2E Testing

For this example project I chose: Babel, Linter / Formatter and Unit Testing. This should be enough but you can choose any other options you want.

Next you will get the following options:

? Pick a linter / formatter config: (Use arrow keys)
❯ ESLint with error prevention only 
  ESLint + Airbnb config 
  ESLint + Standard config 
  ESLint + Prettier 

I chose the first option “ESLint with error prevention only”.

Next you will get the following options:

? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)
 ◉ Lint on save
 ◯ Lint and fix on commit

Again, I chose the first option “Lint on save”.

Next you will get the following options:

? Pick a unit testing solution: 
  Mocha + Chai 
❯ Jest 

Select “Jest” and press enter.

Next you will get the following options:

? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? 
❯ In dedicated config files 
  In package.json

I chose the first option again “In dedicated config files”.

Next you will get the following question:

? Save this as a preset for future projects? (y/N) 

If you think you will reuse these settings for other projects you can press the “y” then enter. That should be it. Your new project will now be created.

Let’s start testing

If you open your project you will see there is a sample test file already tests/unit/example.spec.js which should look something like this:

import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'

describe('HelloWorld.vue', () => {
  it('renders props.msg when passed', () => {
    const msg = 'new message'
    const wrapper = shallowMount(HelloWorld, {
      propsData: { msg }
    })
    expect(wrapper.text()).toMatch(msg)
  })
})

To run your test, in terminal run npm run test:unit. Let’s create a new simple component and create a new test for it. I’ll name it HeroMessage

<template>
  <div :style="heroStyles">{{message}}</div>
</template>

<script>
  export default {
    data() {
      return {
        heroStyles: {
          fontSize: this.fontSize
        }
      };
    },
    props: ['heroStyles', message']
  };
</script>

The above component will take 2 props, the message and the font size. Now let’s create a unit test file HeroMessage.spec.js to test that inside tests/unit folder.

First thing we need to import Vue and the component we want to test:

import Vue from 'vue';
import HeroMessage from '@/components/HeroMessage.vue';

Next we’ll need to create a function that will mount the component and pass some values to the props.

const mountComponent =  (Component, propsData) => {
  const Constructor = Vue.extend(Component);
  const vm = new Constructor({ propsData}).$mount();
  return vm.$el;
}

If you already have some experience with Jest, from here should look very familiar. We will need to create a describe which will contain a list of tests. Each test will be created using the it function.

describe('HeroMessage.vue', () => {
  it('should test if the right font size is set', () => {
  });

  it('should test the message is rendered', () => {
  });
});

Now we created 2 empty tests. Let’s add some code in the first test. Since we already created a function that mounts a component this will be very easy:

it('should test if the right font size is set', () => {
  const heroData = mountComponent(HeroMessage, { fontSize: '12px' });
  const heroStyle = heroData.style.getPropertyValue('fontSize');
  expect(heroStyle).toEqual({ fontSize: '12px' });
});

Testing the message is almost the same:

it('should test the message is rendered', () => {
  const heroData = mountComponent(HeroMessage, { message: 'Hello world!' });
  const heroMessage = heroData.textContent;
  expect(heroMessage).toEqual('Hello world!');
});

Here is the complete test file:

import Vue from 'vue';import HeroMessage from '@/components/HeroMessage.vue';

const mountComponent =  (Component, propsData) => {
  const Constructor = Vue.extend(Component);
  const vm = new Constructor({ propsData}).$mount();
  return vm.$el;
}

describe('HeroMessage.vue', () => {
  it('should test if the right font size is set', () => {
    const heroData = mountComponent(HeroMessage, { fontSize: '12px' });
    const heroStyle = heroData.style.getPropertyValue('fontSize');
    expect(heroStyle).toEqual({ fontSize: '12px' });
  });

  it('should test the message is rendered', () => {
    const heroData = mountComponent(HeroMessage, { message: 'Hello world!' });
    const heroMessage = heroData.textContent;
    expect(heroMessage).toEqual('Hello world!');
  });
});