# Mastering Vite Application Testing with Vitest: A simple guide to prevent  headaches

## Introduction

Vite, a modern front-end build tool, has been gaining popularity due to its fast and lean development experience. Paired with Vitest, a testing framework designed specifically for Vite, you can create a robust testing environment for your applications. In this blog post, we'll explore how to master Vite application testing with Vitest, complete with tips, tricks, and examples.

## What is Vite and Vitest?

[Vite](https://vitejs.dev/) (French for "fast") is a next-generation front-end build tool created by Evan You, the creator of Vue.js. It offers a faster and leaner development experience for modern web projects.

[Vitest](https://vitest.dev/), on the other hand, is a testing framework designed specifically for Vite. It provides a fast, scalable, and easy-to-use testing solution for Vite applications.

## Setting Up Your Vite Project

Before we dive into testing, let's set up a simple Vite project. Here's how you can create a new Vite project using the command line:

```bash
pnpm create vite
```

This command will provide some quick questions to generate a new project. This is the configuration I selected for the project:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1688959199209/41c3ecb9-9d59-4ffd-9f72-8b3bf3c708ab.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Pro tip: I use <code>pnpm</code> as my package manager. It is way more performant than the classic <code>npm</code>. Since there could be different opinions between developer preferences, I'll just let a <a target="_blank" rel="noopener noreferrer nofollow" href="https://pnpm.io/feature-comparison" style="pointer-events: none">comparison table</a> within the features of each package manager - pick the one you like the most 😜</div>
</div>

## Installing and Configuring Vitest

To install Vitest, run the following command in your project directory:

```bash
pnpm add -D vitest
```

Next, add these two `vitest` scripts to your `package.json`:

```bash
"scripts": {
  ...
  "test": "vitest",
  "coverage": "vitest run --coverage"
}
```

Now, you can run your tests using `pnpm run test`.

Since Vitest is a unit testing framework for Vite, as you might have guessed by now, it integrates seamlessly with it. As stated on their website, Vitest can:

> **Reuse Vite's config, transformers, resolvers, and plugins - consistent across your app and tests.**

In other words, this is all we need to begin creating Unit Tests for our project.

However, why stop here? Let's enhance our current toolkit with another fantastic tool!

For creating our tests, we will integrate [Testing Library](https://testing-library.com/), a very handy set of utilities that, as they state:

> The Testing Library family of libraries is a very light-weight solution for testing without all the implementation details. The main utilities it provides involve querying for nodes similarly to how users would find them. In this way, testing-library helps ensure your tests give you confidence in your UI code.

So, let's install it:

```bash
pnpm add -D jsdom @testing-library/react
```

as you can see we are also installing `jsdom`:

To effectively test React components, it is essential to replicate the DOM functionality in the test environment. JSDom aids in establishing this environment for testing, making it necessary to install it as a development dependency alongside the testing library, which provides utilities for querying nodes similarly to user interactions, ensuring confidence in your UI code.

## Writing Your First Test

Let's write a simple component for greeting a user:

```javascript
// src/components/greeting.jsx
import PropTypes from 'prop-types'

export function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>
}

Greeting.propTypes = {
  name: PropTypes.string.isRequired,
}
```

Here's how you can write a test for this component using Vitest & Testing Library:

```javascript
// src/components/greeting.test.jsx
import { describe, it, expect } from 'vitest'
import { render, screen } from '@testing-library/react'
import { Greeting } from './greeting'

describe('<Greeting />', () => {
  it('greets the user', () => {
    render(<Greeting name="John" />)
    expect(screen.getByText(/John/i)).toBeDefined()
  })
})
```

So, let's explain what's going on here:

* you can think of `describe` as a wrapper for your tests, it creates a context for whatever it's happening inside.
    
* `it` is an alias for `test` and it contains the expectation for what you are testing. It is composed of the name of the test and a function.
    
* `render` it's a function from Testing Library that allows rendering a React component - in this case, we passed a hard-coded name "John"
    
* `expect` it is used to create assertions - like to check if there is a text with the word "John" painted on the screen
    

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Pro tip: Note that the test file extension ends in <code>jsx</code> This is because we are rendering a JSX component under the hood by using the <code>render</code> function from Testing Library</div>
</div>

Now, you can run this test using `pnpm run test`. If everything is set up correctly, you should see a passing test in your console.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1688963269924/5058b67c-f8d6-44c5-8bdd-e5bed135c473.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Pro tip: Vitest by default is executed in watch mode, meaning that if you only want to run your tests once, you need to run them like <code>vitest run</code></div>
</div>

Let's then update our scripts in the `package.json` file:

```json
...
"scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview",
    "test": "vitest run",
    "test:dev": "vitest",
    "coverage": "vitest run --coverage"
},
...
```

Now, we have a script for just one run and another for a testing developing experience.

## Checking coverage

If you saw in the scripts there is a third one called `coverage`, this is another great utility that provides Vitest that we are gonna be covering here. Nevertheless, right now since they have migrated from the [c8](https://github.com/bcoe/c8) to [v8](https://v8.dev/blog/javascript-code-coverage) coverage library, once you run the script `pnpm run coverage` you'll get this message in the terminal:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1688965225874/8c069d2a-ca7d-4a9f-99d6-3079388d95e9.png align="center")

Simply respond with "yes" and the switch will be made automatically for you. Afterward, run the script once more and you'll receive the report.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1688965343371/f24ec616-5abc-4964-90ee-2e0ad74ea8ec.png align="center")

This will generate a folder with a UI that you can open in the browser.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1688966358818/39e83261-2f58-4a45-8c86-4588eee1f438.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1688966383746/4afbaea4-e68b-4ed3-b978-18febe7f1d08.png align="center")

## Vitest UI

Another amazing tool I want to share is the Vitest UI library, which allows you to view and interact with your tests. This is completely optional, and as you'll see, it needs to be installed separately, but trust me, it's worth it.

```bash
npm i -D @vitest/ui
```

Now, let's update again our `package.json` file and add `"test:ui": "vitest --ui"`

```bash
...
  "test": "vitest run",
  "test:dev": "vitest",
  "test:ui": "vitest --ui",
  "coverage": "vitest run --coverage"
},
...
```

that's it, if you run it, you'll get this:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1688965987350/3cd5a1ba-dcea-4c10-a7c9-27d4759046b9.png align="center")

a complete playground that provides you with:

* test's code
    
* a convenient module graph
    
* a console to watch errors
    
* search capacity
    
* dark mode switch 😎
    

## Tips and Tricks

Here are some tips and tricks for mastering Vitest:

1. **Use Descriptive Test Names**: Descriptive test names can make it easier to understand what a test is doing and why it might be failing.
    
2. **Group Related Tests**: You can group related tests using `describe` blocks. This can make your tests easier to read and manage.
    
3. **Take Advantage of Vitest's Features**: Vitest comes with several features designed to make testing easier, such as parallel test execution and automatic retries for flaky tests. Be sure to take advantage of these features.
    
4. **Keep Your Tests Small and Focused**: Each test should focus on a single piece of functionality. Smaller, more focused tests are easier to understand and debug.
    
5. **Use Mocks and Stubs Sparingly**: While mocks and stubs can be useful, they can also make your tests more complex and harder to maintain. Use them sparingly and only when necessary.
    

## Bonus

As usual, I’ll let you with the fully configured [Github repository](https://github.com/aiherrera/testing-vite) with the example used in this article for you to check & try out.

I plan to add more examples over time!🧑‍💻

## Last Thoughts

In conclusion, Vite and Vitest offer a powerful combination for developing and testing modern web applications. With the right knowledge and techniques, you can create robust, reliable tests for your Vite applications. Happy testing!

Hope you enjoyed this article, if so, consider giving it a like 👍🏻 and Stay Awesome!
