test-renderer 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +189 -0
- package/dist/index.cjs +868 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +114 -0
- package/dist/index.d.ts +114 -0
- package/dist/index.js +834 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
package/README.md
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Universal Test Renderer for React
|
|
2
|
+
|
|
3
|
+
A lightweight, JavaScript-only replacement for the deprecated React Test Renderer.
|
|
4
|
+
|
|
5
|
+
## Why Use It?
|
|
6
|
+
|
|
7
|
+
- **Pure JavaScript Testing** - Test React components in Jest or Vitest without browser or native dependencies
|
|
8
|
+
- **Universal** - Can be used to simulate React Native or any other React renderer
|
|
9
|
+
- **React 19 Ready** - Modern alternative as React Test Renderer is now deprecated
|
|
10
|
+
- **Lightweight** - Minimal dependencies and small bundle size
|
|
11
|
+
- **Type-safe** - Written in TypeScript with full type definitions
|
|
12
|
+
- **Flexible Configuration** - Customizable reconciler options for different use cases
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -D test-renderer
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Basic Usage
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { act } from "react";
|
|
24
|
+
import { createRoot } from "test-renderer";
|
|
25
|
+
|
|
26
|
+
test("renders a component", async () => {
|
|
27
|
+
const renderer = createRoot();
|
|
28
|
+
|
|
29
|
+
// Use `act` in async mode to allow resolving all scheduled React updates
|
|
30
|
+
await act(async () => {
|
|
31
|
+
renderer.render(<div>Hello!</div>);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
expect(renderer.container).toMatchInlineSnapshot(`
|
|
35
|
+
<>
|
|
36
|
+
<div>
|
|
37
|
+
Hello!
|
|
38
|
+
</div>
|
|
39
|
+
</>
|
|
40
|
+
`);
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## API Reference
|
|
45
|
+
|
|
46
|
+
### `createRoot(options?)`
|
|
47
|
+
|
|
48
|
+
Creates a new test renderer instance.
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
const renderer = createRoot(options);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Returns a `Root` object with:
|
|
55
|
+
|
|
56
|
+
- `render(element)` - Render a React element. Must be called within `act()`.
|
|
57
|
+
- `unmount()` - Unmount and clean up. Must be called within `act()`.
|
|
58
|
+
- `container` - A wrapper `HostElement` that contains the rendered element(s). Use this to query and inspect the rendered tree.
|
|
59
|
+
|
|
60
|
+
### `RootOptions`
|
|
61
|
+
|
|
62
|
+
| Option | Type | Description |
|
|
63
|
+
| -------------------- | ---------------------------- | ----------------------------------------------------------------- |
|
|
64
|
+
| `textComponents` | `string[]` | Element types that can contain text (for React Native simulation) |
|
|
65
|
+
| `createNodeMock` | `(element) => object` | Create mock objects for refs |
|
|
66
|
+
| `identifierPrefix` | `string` | Prefix for `useId()` generated IDs |
|
|
67
|
+
| `isStrictMode` | `boolean` | Enable React Strict Mode |
|
|
68
|
+
| `onCaughtError` | `(error, errorInfo) => void` | Called when Error Boundary catches an error |
|
|
69
|
+
| `onUncaughtError` | `(error, errorInfo) => void` | Called for uncaught errors |
|
|
70
|
+
| `onRecoverableError` | `(error, errorInfo) => void` | Called when React recovers from errors |
|
|
71
|
+
|
|
72
|
+
### `HostElement`
|
|
73
|
+
|
|
74
|
+
The rendered element wrapper with a DOM-like API:
|
|
75
|
+
|
|
76
|
+
| Property/Method | Description |
|
|
77
|
+
| ------------------------------- | ---------------------------------------- |
|
|
78
|
+
| `type` | Element type (e.g., `"div"`, `"span"`) |
|
|
79
|
+
| `props` | Element props object |
|
|
80
|
+
| `children` | Array of child elements and text strings |
|
|
81
|
+
| `parent` | Parent element or `null` |
|
|
82
|
+
| `toJSON()` | Convert to JSON for snapshots |
|
|
83
|
+
| `queryAll(predicate, options?)` | Find all matching descendant elements |
|
|
84
|
+
|
|
85
|
+
## Querying Elements
|
|
86
|
+
|
|
87
|
+
Use `queryAll()` to find elements in the rendered tree:
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
const renderer = createRoot();
|
|
91
|
+
await act(async () => {
|
|
92
|
+
renderer.render(
|
|
93
|
+
<div>
|
|
94
|
+
<button data-testid="btn-1">First</button>
|
|
95
|
+
<button data-testid="btn-2">Second</button>
|
|
96
|
+
</div>,
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Find all buttons
|
|
101
|
+
const buttons = renderer.container.queryAll((el) => el.type === "button");
|
|
102
|
+
expect(buttons).toHaveLength(2);
|
|
103
|
+
|
|
104
|
+
// Find by props
|
|
105
|
+
const btn1 = renderer.container.queryAll((el) => el.props["data-testid"] === "btn-1");
|
|
106
|
+
expect(btn1[0].children).toContain("First");
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Query Options
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
queryAll(predicate, {
|
|
113
|
+
includeSelf: false, // Include the element itself in results
|
|
114
|
+
matchDeepestOnly: false, // Only return deepest matches (exclude ancestors)
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## React Native Simulation
|
|
119
|
+
|
|
120
|
+
Use `textComponents` to simulate React Native's text rendering rules:
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
import { createElement } from "react";
|
|
124
|
+
|
|
125
|
+
const renderer = createRoot({
|
|
126
|
+
textComponents: ["Text", "RCTText"],
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// This works - text inside Text component
|
|
130
|
+
await act(async () => {
|
|
131
|
+
renderer.render(createElement("Text", null, "Hello!"));
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// This throws - text outside Text component
|
|
135
|
+
await act(async () => {
|
|
136
|
+
renderer.render(<View>Hello!</View>); // Error!
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Mocking Refs
|
|
141
|
+
|
|
142
|
+
Use `createNodeMock` to provide mock objects for refs:
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
const renderer = createRoot({
|
|
146
|
+
createNodeMock: (element) => {
|
|
147
|
+
if (element.type === "input") {
|
|
148
|
+
return {
|
|
149
|
+
focus: jest.fn(),
|
|
150
|
+
value: "",
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return {};
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
await act(async () => {
|
|
158
|
+
renderer.render(<input ref={inputRef} />);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// inputRef.current is now the mock object
|
|
162
|
+
inputRef.current.focus();
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Error Handling
|
|
166
|
+
|
|
167
|
+
Handle React errors with custom callbacks:
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
const renderer = createRoot({
|
|
171
|
+
onCaughtError: (error, errorInfo) => {
|
|
172
|
+
// Called when an Error Boundary catches an error
|
|
173
|
+
console.log("Caught:", error.message);
|
|
174
|
+
console.log("Component stack:", errorInfo.componentStack);
|
|
175
|
+
},
|
|
176
|
+
onUncaughtError: (error, errorInfo) => {
|
|
177
|
+
// Called for uncaught render errors
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Key Differences from React Test Renderer
|
|
183
|
+
|
|
184
|
+
- Works at host component level only (no composite components)
|
|
185
|
+
- Expost all reconciler configuration options
|
|
186
|
+
|
|
187
|
+
## License
|
|
188
|
+
|
|
189
|
+
MIT
|