Skip to content

Commit 3848abd

Browse files
content(react-test): first draft
1 parent 747290f commit 3848abd

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
---
2+
title: How to test a React app with Node Test Runner
3+
description: Drastically simplify and speed up testing your React app by switching to Node Test Runner.
4+
date: 2025-02-12
5+
authors: AugustinMauroy
6+
category: use-cases
7+
---
8+
9+
## Introduction
10+
11+
Testing is a crucial part of software development, ensuring that your application behaves as expected. With the [Node.js Test Runner](https://nodejs.org/en/learn/test-runner/introduction), you can seamlessly integrate testing into your [React](https://react.dev) application. This guide will walk you through the process of setting up and running tests for a React app using the Node.js Test Runner.
12+
13+
Note that this article is design for nodej.js `^22.14.0` and `^23.6`.
14+
15+
> I really recommend you to read the [Node.js Test Runner guides](https://nodejs.org/en/learn/test-runner/introduction) to understand how node.js test runner works.
16+
> This guide assumes you have a basic understanding of React and testing.
17+
18+
## Installing the Dependencies
19+
20+
First, you need to install the necessary dependencies. In addition to your React app dependencies, you will need the following:
21+
22+
```bash
23+
npm add --save-dev @testing-library/react @testing-library/dom jsdom global-jsdom
24+
```
25+
26+
> **Note**: The rest of the dependencies we will use come from Node.js.
27+
28+
## Writing the Component to Be Tested
29+
30+
Let's create a simple React component that we will test. This component will be a counter that increments a value when a button is clicked.
31+
32+
```tsx
33+
'use client';
34+
import { useState } from 'react';
35+
import styles from './index.module.css';
36+
import type { FC } from 'react';
37+
38+
const Counter: FC = () => {
39+
const [count, setCount] = useState(0);
40+
41+
return (
42+
<div className={styles.container}>
43+
<p className={styles.count}>{count}</p>
44+
<button onClick={() => setCount(count + 1)} className={styles.button}>
45+
Increment
46+
</button>
47+
</div>
48+
);
49+
};
50+
51+
export default Counter;
52+
```
53+
54+
<details>
55+
<summary>`index.module.css`</summary>
56+
57+
```css
58+
.container {
59+
@apply flex flex-col items-center justify-center;
60+
61+
.count {
62+
@apply text-4xl;
63+
}
64+
65+
.button {
66+
@apply px-4 py-2 bg-blue-500 text-white rounded-md;
67+
}
68+
}
69+
```
70+
</details>
71+
72+
## Registering Node.js Loaders
73+
74+
To handle TypeScript and CSS modules, you need to register the appropriate loaders. Create a file named `node-hooks/react-test.js` and add the following code:
75+
76+
> To understand what is a loader, check out [this post](/blog/post/how-to-use-nodejs-loader).
77+
78+
You'll need to register the loaders for TypeScript and CSS modules:
79+
80+
First let's install the loaders as dev dependencies:
81+
82+
```bash
83+
npm add -D @nodejs-loaders/tsx @nodejs-loaders/css-module
84+
```
85+
86+
Then, create the registration file:
87+
88+
```js
89+
import { register } from 'node:module';
90+
import jsdom from 'global-jsdom';
91+
92+
// Register the loaders
93+
register('@nodejs-loaders/tsx', import.meta.url);
94+
register('@nodejs-loaders/css-module', import.meta.url);
95+
96+
// Create a JSDOM environment
97+
jsdom(undefined, {
98+
// ⚠️ Failing to specify this will likely lead to many 🤬
99+
url: 'https://test.example.com',
100+
});
101+
```
102+
103+
> **NOTE:** You may need to use `@nodejs-loaders/alias` to allow Node.js to understand path aliases in your TypeScript files.
104+
105+
## Writing the Test
106+
107+
Now, let's write a test for the `Counter` component. Create a file named `index.test.tsx` in the same directory as your component:
108+
109+
```tsx
110+
import assert from 'node:assert/strict';
111+
import { describe, it } from 'node:test';
112+
import { render, fireEvent, screen } from '@testing-library/react';
113+
import Counter from './index.ts'; // ⚠️ We need to import the file with the .ts extension
114+
115+
describe('Counter', () => {
116+
it('should increment the count when the button is clicked', () => {
117+
const { unmount } = render(<Counter />);
118+
119+
const button = screen.getByRole('button', { name: /increment/i });
120+
const count = screen.getByText('0');
121+
122+
assert.strictEqual(count.textContent, '0');
123+
124+
fireEvent.click(button);
125+
126+
assert.strictEqual(count.textContent, '1');
127+
128+
// ⚠️ It's a good idea to unmount the component to prevent it spilling over into the DOM of other tests
129+
unmount();
130+
});
131+
});
132+
```
133+
134+
### Structure of a Test File
135+
136+
A typical test file structure includes:
137+
138+
1. **Imports**: Import the necessary modules and components.
139+
2. **Test Suite**: Define a test suite using `describe`.
140+
3. **Test Case**: Define individual test cases using `it`.
141+
4. **Render the Component**: Render the component to be tested.
142+
5. **Perform Actions**: Simulate user interactions or other actions.
143+
6. **Assertions**: Make assertions to verify the expected behavior.
144+
7. **Unmount the Component**: Clean up by unmounting the component.
145+
146+
## Running the Test
147+
148+
To run the test, use the following command:
149+
150+
```bash
151+
node --test --import=./node-hooks/react-test.js **/*.test.tsx
152+
```
153+
154+
You can also add a script to your `package.json` to simplify running the tests:
155+
156+
```json fileName="package.json"
157+
{
158+
"scripts": {
159+
"test:unit": "node --test --import=./node-hooks/react-test.js **/*.test.tsx",
160+
"test:watch": "node --test --watch --import=./node-hooks/react-test.js **/*.test.tsx"
161+
}
162+
}
163+
```
164+
165+
> **Note**: You can add more patterns to the glob pattern to test more files. For example, `**/*.test.ts` to test all TypeScript files.
166+
167+
And then to call the script you can use `--run`:
168+
169+
```bash
170+
node --run test:unit # or node --run test:watch
171+
```
172+
173+
## Conclusion
174+
175+
Testing your React app with the Node.js Test Runner is a straightforward process. By following the steps outlined in this guide, you can ensure that your components behave as expected. Happy testing!

0 commit comments

Comments
 (0)