Setting Up Vitest, Testing Library, And jest-dom In Your Vite Project
Jan 6, 2023 · 4 min readThis will be a brief tutorial on how to setup Vitest, Testing Library, and jest-dom in your Vite Project.
Setup Vite Project
Before we can setup our testing tools, we first need a Vite project. We can scaffold a Vite project easily by running the command:
npm create vite@latestNext, you’ll be prompted for your project name, your front-end framework of choice, and whether you need Typescript or not.
In this project, let’s assume that we choose Svelte as our front-end framework and Typescript as our language of choice.
The steps are more or less the same regardless of what framework you’re using.
Install Vitest
The next step is to install Vitest using the command:
npm install --save-dev vitestWe also need to install jsdom to simulate the DOM for our frontend app.
npm install --save-dev jsdomNext, we need to tell Vitest to change our testing environment to jsdom. Create a file called vitest.config.ts or .js depending on your preferences, and pass the following code in.
import { defineConfig } from "vitest/config";import { svelte } from "@sveltejs/vite-plugin-svelte";
export default defineConfig({ plugins: [svelte({ hot: !process.env.VITEST })], test: { include: ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], environment: "jsdom", },});One thing to note about Vitest is that unlike Jest, globals are not enabled by default. This means that we have to explicitly import describe, test, expect, etc. on our test files like this:
import { describe, test, expect } from "vitest";But if you prefer, you can enable the test APIs globally like Jest. To enable globals support, we need to add the following line into our vitest.config.ts file.
import { defineConfig } from "vitest/config";import { svelte } from "@sveltejs/vite-plugin-svelte";
export default defineConfig({ plugins: [svelte({ hot: !process.env.VITEST })], test: { include: ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], globals: true, environment: "jsdom", },});If you’re using Typescript, we need to do one extra step to please the type checker. We need to add vitest/globals to compilerOptions in tsconfig.json.
{ "extends": "@tsconfig/svelte/tsconfig.json", "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "module": "ESNext", "resolveJsonModule": true, "allowJs": true, "checkJs": true, "isolatedModules": true, "moduleResolution": "node", "types": ["vitest/globals"] }, "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"], "references": [{ "path": "./tsconfig.node.json" }]}And finally, let’s add the following to our package.json file for convenience sake.
{ "scripts": { "test": "vitest run src", "test:watch": "vitest src" }}Now, we can run our tests with npm run test or npm run test:watch to run in watch mode.
Install Testing Library
Installing Vitest is enough to test our app. But Testing Library offers us a lot of utilities that’ll make our life easier.
For example, the render method save us the trouble of creating a container, appending it to the body, and cleaning up the container after test, etc.
Testing Library supports multiple framework. And since we’re assuming that this is a Svelte project, we’ll be using the Svelte Testing Library.
npm install --save-dev @testing-library/svelteInstall jest-dom
jest-dom is a really nice addition on top of Testing Library. It’s a custom matcher that’s really useful to test the state of the DOM.
Matcher is what you put after
expect. For example:expect(getByTestId('input')).toBeDisabled().toBeDisabled()is one of the useful matchers provided by jest-dom.
Install it by running:
npm install --save-dev @testing-library/jest-domNow, we can use the matchers by importing @testing-library/jest-dom at the start of our test files.
import "@testing-library/jest-dom";We can make our experience even better by extending the matcher with a Vitest setup file. The filename doesn’t matter, but let’s assume that the file name is ./src/tests/setup.ts. Inside the file, paste in the following code:
import { expect } from "vitest";import matchers from "@testing-library/jest-dom/matchers";
expect.extend(matchers);We also need to tell Vitest where to look for our setup file.
import { defineConfig } from "vitest/config";import { svelte } from "@sveltejs/vite-plugin-svelte";
export default defineConfig({ plugins: [svelte({ hot: !process.env.VITEST })], test: { include: ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], globals: true, environment: "jsdom", setupFiles: "./src/tests/setup.ts", },});Now, we don’t need to manually import @testing-library/jest-dom anymore in our test files.
One final thing before we end this tutorial.
In my case, Typescript couldn’t find the type definition for the matchers. So even though all my tests run just fine, I didn’t get auto completion for the matcher in my IDE and got a squiggly red line instead.
If you have the same issue, install the type definition for jest-dom.
If you’re not using Typescript, or don’t experience this issue, you can skip this step.
npm install --save-dev @types/testing-library__jest-domAnd update your tsconfig.json.
{ "extends": "@tsconfig/svelte/tsconfig.json", "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "module": "ESNext", "resolveJsonModule": true, "allowJs": true, "checkJs": true, "isolatedModules": true, "moduleResolution": "node", "types": ["vitest/globals", "@testing-library/jest-dom"] }, "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"], "references": [{ "path": "./tsconfig.node.json" }]}With that, everything should now work as expected 😁.
Wrap Up
That’s it, we’re done with our test setup. Now simply create your tests, and run it using the command:
npm run testHappy testing!