Testing is one of the critical standards of any software component, we must test the software once it has been developed or even in the development phase. As developers, we usually delegate the software testing responsibility to the Quality Assurance Team, but it’s the responsibility of the developers as well to test their code. Developers must test their codes on multiple levels, starting with the writing of the first unit.
This allows the software to be stable from the base level. A strong base is always an essential component of a software project. Testing on the code level minimizes the redundant task of testing the entire flow when a single unit changes. It also tracks and tests all the dependent units/components that we might miss while testing manually. Apart from that it enables us to fearlessly change the code for future enhancements and upgrade the application continuously.
With concerns raised for development testing, as a Software Engineer working with React, it was finally time for me to dive into testing and build a stronger base for testing which was to be continued onto the quality assurance team. Starting out on testing, I first explored different libraries that can assist to make this process much smoother and came across these popular libraries that were being used to test React applications, Vitest, and React Testing libraries.
In this three part blog, I will explain the in and outs of React Testing using Vitest and React Testing Libraries. In this first part, I will focus on setting up and writing the first test.
Introduction of the libraries
Vitest
Vitest is a blazing-fast unit test framework powered by Vite. It is quite similar to the popular testing library Jest and provides a compatible API that allows you to use it as a drop-in replacement in most projects. Read more
Testing library / React
The testing-library family of packages helps you test UI components in a user-centric way.
The DOM Testing Library is a very lightweight solution for testing DOM nodes ( whether simulated with JSDOM as provided by default with Jest or in the browser).
React Testing Library builds on top of DOM Testing Library by adding APIs for working with React components.
Setup
While creating a React app you might have noticed that there is Jest library pre-installed. and the test script is already written. You can continue with the Jest as well, but if you want to follow along. You can replace Jest with Vitest.
Here I am using Vite to create the React app, which is a preferable and better approach to creating React applications.
-
Creating React app using Vite
yarn create vite
-
Adding required packages
yarn add -D vitest jsdom @testing-library/react @testing-library/jest-dom
- Adding the script to run tests
// package.json
{
"script":
{
...
"test": "vitest"
}
}
- Defining Vite Configuration
// vite.config.ts
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react-swc";
/\*\* @type {import('vite').UserConfig} */
// <https://vitejs.dev/config/>
export default defineConfig({
plugins: \[react()],
test: {
environment: "jsdom",
setupFiles: \["./tests/setup.ts"],
globals: true, // import vitest globally
// ...
},
});
- Setting up test configurations
// src/test/setup.ts
import { expect, afterEach } from "vitest";
import { cleanup } from "@testing-library/react";
// provides matchers for dom validations
import matchers from "@testing-library/jest-dom/matchers";
import { server } from "../src/mocks/server";
// Establish API mocking before all tests.
beforeAll(() => server.listen());
// Reset any request handlers that we may add during the tests,
// so they don't affect other tests.
afterEach(() => server.resetHandlers());
// Clean up after the tests are finished.
afterAll(() => server.close());
afterEach(() => {
cleanup();
});
expect.extend(matchers);
Now, you are almost ready to write your first test.
Writing your first test
Before jumping right away, first you must know some basics of writing a test in Vitest.
Starting with the filenames, the test can only be written in a specific file name format or specific folder. Supported filenames and folders are:
- app.test.ts / app.test.tsx
- app.sepc.ts / app.spec.tsx
- Or any file inside __test__
- Similarly for js and jsx
Tests can be grouped and even nested using the describe function, this makes it easier to identify and run a group of tests. Also, you must make sure that you add TS config for Vitest and testing-library/jest-dom.
{
"compilerOptions" : {
...
"types":\["vitest/globals", "@testing-library/jest-dom"]
},
"include": \["src", "tests"],
...
}
Writing a React component for testing
// Greetings.tsx
type propTypes = {
name: string;
}:
const Greeting = ({name} : propTypes) =>
<h1> Hello, {name} </h1>;
export default Greeting;
Writing test for the Greeting component
// Greeting.test.tsx
import { render, screen } from "@testing-library/react";
import { Greeting } from "./Greeting";
describe("Greeting", () => {
test("Should return a greeting message, Hello Kim", () => {
// renders Greeting Component in test env
render(<Greeting name="Kim" />);
// * queryByText is the DOM query function provided by @testing-library/react
// * grabs DOM element containing "hello kim"
const greetMsg = screen.queryByText(/hello kim/i);
// * toBeInTheDocument is extension assertion from @testing-library/jest-dom
// * assert whether an element is present in the document or not.
expect(greetMsg).toBeInTheDocument();
});
});
Test Code Explanation
Here we import render and screen from @testing-library/react, These provide us the base for rendering and grabbing the DOM element. Then we import the Greeting component that we created earlier.
We then describe the test using the describe function which has been imported from Vitest, but we don’t need to import it here as we have made Vitest globally available. Inside the description we write our test function, the first param is the description of what the test is for, and the second param is the actual function that is to be tested.
Then, we render the Component using the render function with the name props “Kim”, after that, we use one of the query functions to grab the DOM, in the above code we have used the queryByText function with /hello kim/i regex to query any element that contains the text “hello Kim”. Read more about query functions.
Now the test is an assertion whether the desired element is present in the document or not.
If the element is present the test passes else it fails. To check the required condition we use the expect function with validation for toBeInTheDocument, which is provided by jest-dom-matcher.
For the above code, the test must pass. It is always a good practice to check for the failed test as well. We can do that by changing the regex val or passing the name props with different values.
Queries
Available Queries in React Testing Library
- getBy… / getAllBy…
- queryBy… / queryAllBy…
- findBy… / findAllBy…
- Suffix: Role, LabelText, PlaceHolderText, Text, DisplayValue, AltText, Title, and TestId
- For Roles Check:
Some useful tips
💡 There is a useful Chrome extension called Testing Playground. Which helps to write the particular query for an element, within a given condition.
💡 You can add Vitest extension in VScode to view all the tests and their status
Final Words
Gurzu is a full-cycle Software development company. Since 2014, we have built softwares for many startups and enterprises from all around the world using Agile methodology. Our team of experienced developers, designer, test automation engineers can help to develop your next product.
Read more about our services here. Have a tech idea you want to turn into reality? Book a free consulting call.