Using a test-driven approach to React development.
Following on from our React Basics guide, we will continue to use React and Vite.
To start using TDD, we're going to need some new tools:
- vitest a vite-friendly test runner analogous to jest
- React Testing Library enabling inspection of React output
Create the React App by following those instructions.
You should get to the part where you can run the React app with
npm run devand see this in your browser:
Once you can see the React skeleton app working, we can install the test tools.
Type
cd my-react-appand you can even double-check by typing pwd. If you are using Mac or Linux, that is. Windows generally shows the full path in the command prompt. Simply give it a quick check.
We need to add the test tools to the parent directory of our React app.
Install our test runner, vitest:
npm install vitest --save-devConfigure the project to use vitest and vite. Add the following to package.json of the React application:
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"test": "vitest"
},Most of this came from vite previously. The line we need to add is the final line "test": "vitest".
React Testing Library (RTL) allows our tests to introspect html output, simulate user events and intercept calls to external APIs.
Install RTL:
npm install @testing-library/react @testing-library/jest-dom --save-devWe will be testing outside of the browser. Our tests will access a simulated browser DOM (Document Object Model) to assert correctness of our React components. We will use jsdom as our 'virtual DOM'.
Install jsdom:
npm install jsdom --save-devReplace the contents of file vite.config.js with this:
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
test: {
environment: "jsdom",
globals: true,
setupFiles: ["@testing-library/jest-dom"],
},
});This instructs vite to use JSDOM as its virtual DOM, and use the setup files bundled with React testing Library.
Type the command:
npm run -- --testThe terminal output should have this as its last line:
No test files found, exiting with code 1That's exactly as we expect; we have yet to write our first test!
The setup is done and dusted. Make yourself a nice hot cup of tea, and mentally prepare for writing our first test. Oooh - exciting! I love me a good test in the morning.
Let's use the test framework to render the React <App /> component we already have. Find the file App.jsx, and write a new file in the same directory called App.spec.jsx.
Put this content into App.spec.jsx:
import { render, screen } from "@testing-library/react";
import App from "./App";
describe("App", () => {
it("renders headline", () => {
render(<App title="React" />);
screen.debug();
});
});Run this code by using the command:
npm run -- --testWhat do you see?
Here's what I get in my terminal:
This is what's contained in the JSDOM virtual DOM. It is the DOM as it will be rendered in our browser - when we finally use a browser.
It is pure, raw html.
Now ... that isn't quite what we were expecting, was it?
I mean, where's all the React stuff? Components and props and hooks and JavaScript? Not even a smidgen of JSX? What's going on?
There's an important TDD principle at work here.
Test observable behaviour, not implementation details
The React Testing library has the philosophy that we should test a web page as close to how a human user sees that page as possible.
As a result, we're not going to look into specific implementation details of React components in our tests. That only makes our tests brittle.
Instead, our tests will consider only:
- user-visible output
- simulating user actions, such as clicks
- simulating external HTTP web services
React Testing Library provides us with methods on the screen object to help us access visible data, much as a human would.
This approach promotes accessibility in our web pages - very important!
Let's write a test for a suitably dull exciting exercise component: the Quote of the Day.
Test-first Displaying Data

