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 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