Popoola Temitope I'm a software developer and technical writer. I love learning about new technology and am always ready to share ideas with others.

A guide to Vitest automated testing with Vue components

6 min read 1710

A guide to Vitest automated testing with Vue components

When developing Vue applications, we use one or more components to ensure that our code is easy to read and maintain. Verifying whether a component is executing as expected without error is essential where application functionality and performance matter.

With Vue component testing, we can test our individual components to verify that they work correctly and that asynchronous operations are properly triggered. Component testing catches issues relating to components’ props, events, styles, classes, lifecycle hooks, and more.

There are many automated testing frameworks we can use for testing Vue components, such as Vitest, Jest, Cypress, etc., but the Vue team recommends using Vitest for testing Vue applications because of its unique features. Vitest is created and maintained by Vue and Vite team members.

In this tutorial, we’ll explore the Vitest framework, how to configure it, and how to use it for testing Vue components. We’ll also cover how to use snapshots and code coverage.

As a prerequisite for this tutorial, I’ll assume you have Node.js installed on your computer and are familiar with Vue.

Jump ahead:

What is Vitest?

Vitest is a super fast testing framework that requires little configuration. Because Vitest and Vite use the same configuration file, it is simple to integrate Vitest into a Vue application.

According to the Vitest team, “Vitest aims to position itself as the Test Runner of Choice for Vite projects, and as a solid alternative even for projects not using Vite.”

Vitest features

Vitest is compatible with the Jest API. If you are already familiar with Jest, you will know how to work with Vitest. Apart from the similarities Vitest shares with the Jest API, let’s look at some of the features that make it a better testing framework:

  • Vitest shares the same configuration file as Vite, and test configuration is done inside the vite.config.js file to ensure that the test environment is similar to the building environment
  • Vitest is compatible with most Jest APIs and libraries, making it easy to migrate from Jest to Vitest
  • Vitest supports HMR, which allows new changes to be reflected on the server whenever the test files are modified

Creating a Vue project

To understand how to run automated component testing in Vue, let’s set up a Vue program with the following commands:

npm create [email protected] vue-app -- --template vue
cd vue-app
npm install

Once the project installation is complete, run the command below to start the application:
npm run dev

Open http://127.0.0.1:5173/ the browser. You should see the app running successfully.

Vitest installation and configuration

Now, let’s install Vitest with the command below:

npm install -D vitest

After the installation, we need to add Vitest to the package.json file. In the package.json file, add the test script as follows:

// ...
"scripts": {
  // ...
   "test": "vitest"
 },
// ...

Next, open the vitest.config.js file and add the following code to it:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
 plugins: [vue()],
 test:{
   globals:true,
 }
})

Setting the globals property to true will allow the Vitest APIs to be accessible within the test files without importing them.

Installing Test Utils and happy-dom

Test Utils is a Vue testing library that provides methods for mounting and interacting with Vue components. Install Test tils with the command below:

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

In our component testing, we should be able to mock the DOM API. Vitest currently supports both happy-dom and jsdom. In this tutorial, we’ll make use of happy-dom. Run the command below to install happy-dom:

npm install happy-dom

After the installation, add –dom to the test script in the package.json file:

// …
"scripts": {
   // …
   "test": "vitest --dom" 
 },
// …

Also, we need to add happ``y``-dom to the vite.config.js file to make it globally available in our test files:

// …
 test:{
   // …
   environment: 'happy-dom',
 }
// …

Creating a Vue component

Let’s create a simple component called GuessAge.vue that enables users to enter their name and guess the age of the user based on the name entered using the Agify.io API.

Inside the src/components folder, create GuessAge.vue file and add the following code:

<template>
  <h1>{{ title }}</h1>
  <div class="card">
   <div style="width:400px;height:130px;margin-top:20px;border-style: dotted;" >
   <br>
    <span>Firstmame: {{firstname}}</span> <br>
    <span>Age: {{age}}</span> <br>

    </div><br><br>
     <label> Enter Firstname </label><br>
     <input type="text" v-model="search" style="font-size:20px;border-radius:10px;" placeholder=" Name ..."> <br> <br>
    <button type="button" @click="getAge">Guess Age</button>
    <br> <br> <br>
    <input type="radio" value="pop"> <label>Save my data</label>
  </div>
</template>
<script setup>
import { ref } from 'vue'
defineProps({
  title: String
})
</script>
<script>
export default {
    data() {
        return {
            search:"",
            firstname:"",
            age:"",
        }
    },
    computed: {
       getAge() {
        fetch('https://api.agify.io/?name='+ this.search)
        .then(response => response.json())
        .then(data => {
            this.age = data.age
            this.firstname = data.name
            this.search=""
        })
        }
    }
}
</script>

Testing Vue components and props

We need to create a test file for our component. As a naming convention, the test file name has to start with the component name and end with .spec.js or .test.js. Each component should have a test file when testing multiple components.

Now, inside the components folder, create a test file called GuessAge.spec.js. The file will contain a simple test script for our GuessAge component.

Let’s test the GuessAge component to see if it receives the correct props when mounting. We can test the value of the title prop at mount time by adding the following code to the GuessAge.spec.js file:

import {mount} from "@vue/test-utils";
import GuessAge from "../components/GuessAge.vue";
// import { expect, test } from "vitest";
test("mount component",async()=>{
   expect(GuessAge).toBeTruthy();

   const wrapper = mount(GuessAge,{
       props:{
          title:"Guess User Age App",
       },
   });
   expect(wrapper.text()).toContain("Guess User Age App");
})

We import mount from @vue/test-utils, which allows us to wrap our component into a special object called Wrapper, which gives us various test options.

You should import { expect, test } from "vitest"; if you set the value of globals to false in the Vite configuration file.

Run the command below to test the component in watch mode:

npm run test

Running command on watch mode

Using snapshot test cases

A snapshot is used to keep track of changes in the UI. A typical snapshot test case renders a UI component, takes a snapshot, and compares it to a reference snapshot file alongside the test. It compares the current state of your UI to the established snapshots. The test will fail if the current state does not match the established state.

To run a snapshot test and keep track of changes in your UI, add the code below to the test file (GuessAge.spec.js).



test('snapshot UI testing', () => {
   const wrapper = mount(GuessAge,{});
   expect(wrapper.text()).toMatchSnapshot()
  })

Since Vitest supports hot module reloading, you do not have to run the test command each time the test file is modified. Here’s what you should see in your terminal:

Testing click events

Mocking HTTP requests

When testing Vue components with HTTP requests, we first need to mock the network request; otherwise, the test will fail.

Mocking with Mock Service Worker (MSW) makes it easy to test HTTP requests by intercepting the requests made by your tests without changing any of the application code.

Install MSW using the command below:

npm install msw --save-dev

We must import the following two dependencies inside our test file(GuessAge.spec.js) to use MSW.

import { setupServer } from 'msw/node'
import { rest } from 'msw'

Let’s create an instance of the mock server that would intercept the HTTP requests by adding the following code to our test file(GuessAge.spec.js).

export const restHandlers = [
   rest.get('https://api.agify.io/', (req, res, ctx) => {
      return res(ctx.status(200), ctx.json([
         {
            age: 55,
            name: "tope"
         }
      ]))
   }),
]
const server = setupServer(...restHandlers)
// Start server before all tests
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
//  Close server after all tests
afterAll(() => server.close())
// Reset handlers after each test `important for test isolation`
afterEach(() => server.resetHandlers())

Testing click events

Let’s verify that when we click on the Guess Age button, the input tag is empty after fetching the user age.

test("Button clicked", async () => {
   expect(GuessAge).toBeTruthy();

   const wrapper = mount(GuessAge, {
      props: {
         title: "Guess User Age App",
      },
   });
   const ac = await wrapper.get("button").trigger("click")
   expect(wrapper.vm.search).toEqual("")
})

Here’s what you should see in the terminal:

Coverage testing with Vitest

To report and analyze code performance to ascertain how effective and well-written your code is, Vitest supports native code coverage via c8 and Istanbul.

To configure and run coverage testing, we need to add coverage to the vite.configure.js file as follows:

export default defineConfig({
  plugins: [vue()],
  test:{
    globals:true,
    coverage: {
      provider: 'istanbul'
    },
    environment: 'happy-dom',
  }
})

Also, we need to add coverage to the package.json file, add the coverage to the script as follows:

// ...
"scripts": {
  // ...
   "coverage": "vitest run --coverage"
 },
// ...

Now that we have configured the coverage testing, the next thing is to install Istanbul using the command below.

npm i -D @vitest/coverage-istanbul

The test files are run when the command below is executed, and Vitest will display the coverage report matrix on the terminal.

npm run coverage 

Conclusion

We have successfully written our automated tests for our Vue components using Vitest.


More great articles from LogRocket:


With automated testing, we can quickly and confidently prevent regressions in our Vue applications and ensure that we are pushing error-free code to production.

This tutorial taught us how to configure and use Vitest to test Vue components. You can learn more about Vitest and how to migrate from Jest to Vitest in their official docs.

Experience your Vue apps exactly how a user does

Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket. https://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.

The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.

Modernize how you debug your Vue apps - .

Popoola Temitope I'm a software developer and technical writer. I love learning about new technology and am always ready to share ideas with others.

Leave a Reply