2
2
3
3
## What is this library?
4
4
5
- This library allows you to make render-per- render assertions on your React
6
- components and hooks. This is usually not necessary, but can be highly
7
- beneficial when testing hot code paths.
5
+ This library allows you to make committed- render-to-committed- render assertions
6
+ on your React components and hooks. This is usually not necessary, but can be
7
+ highly beneficial when testing hot code paths.
8
8
9
9
## Who is this library for?
10
10
@@ -36,7 +36,7 @@ test('iterate through renders with DOM snapshots', async () => {
36
36
const {takeRender , render } = createRenderStream ({
37
37
snapshotDOM: true ,
38
38
})
39
- const utils = render (< Counter / > )
39
+ const utils = await render (< Counter / > )
40
40
const incrementButton = utils .getByText (' Increment' )
41
41
await userEvent .click (incrementButton)
42
42
await userEvent .click (incrementButton)
@@ -63,31 +63,27 @@ test('iterate through renders with DOM snapshots', async () => {
63
63
In every place you would call
64
64
65
65
``` js
66
- const renderStream = createRenderStream (options)
67
- const utils = renderStream . render (< Component / > , options)
66
+ const { takeRender , render } = createRenderStream (options)
67
+ const utils = await render (< Component / > , options)
68
68
```
69
69
70
70
you can also call
71
71
72
72
``` js
73
- const renderStream = renderToRenderStream (< Component / > , combinedOptions)
74
- // if required
75
- const utils = await renderStream .renderResultPromise
73
+ const {takeRender , utils } = await renderToRenderStream (
74
+ < Component / > ,
75
+ combinedOptions,
76
+ )
76
77
```
77
78
78
- This might be shorter (especially in cases where you don't need to access
79
- ` utils ` ), but keep in mind that the render is executed ** asynchronously** after
80
- calling ` renderToRenderStream ` , and that you need to ` await renderResultPromise `
81
- if you need access to ` utils ` as returned by ` render ` .
82
-
83
79
### ` renderHookToSnapshotStream `
84
80
85
81
Usage is very similar to RTL's ` renderHook ` , but you get a ` snapshotStream `
86
82
object back that you can iterate with ` takeSnapshot ` calls.
87
83
88
84
``` jsx
89
85
test (' `useQuery` with `skip`' , async () => {
90
- const {takeSnapshot , rerender } = renderHookToSnapshotStream (
86
+ const {takeSnapshot , rerender } = await renderHookToSnapshotStream (
91
87
({skip}) => useQuery (query, {skip}),
92
88
{
93
89
wrapper : ({children}) => < Provider client= {client}> {children}< / Provider> ,
@@ -105,7 +101,7 @@ test('`useQuery` with `skip`', async () => {
105
101
expect (result .data ).toEqual ({hello: ' world 1' })
106
102
}
107
103
108
- rerender ({skip: true })
104
+ await rerender ({skip: true })
109
105
{
110
106
const snapshot = await takeSnapshot ()
111
107
expect (snapshot .loading ).toBe (false )
@@ -146,7 +142,7 @@ test('`useTrackRenders` with suspense', async () => {
146
142
}
147
143
148
144
const {takeRender , render } = createRenderStream ()
149
- render (< App / > )
145
+ await render (< App / > )
150
146
{
151
147
const {renderedComponents } = await takeRender ()
152
148
expect (renderedComponents).toEqual ([App, LoadingComponent])
@@ -179,7 +175,7 @@ test('custom snapshots with `replaceSnapshot`', async () => {
179
175
const {takeRender, replaceSnapshot, render} = createRenderStream <{
180
176
value: number
181
177
}>()
182
- const utils = render (<Counter />)
178
+ const utils = await render (<Counter />)
183
179
const incrementButton = utils .getByText (' Increment' )
184
180
await userEvent .click (incrementButton )
185
181
{
@@ -215,16 +211,14 @@ test('assertions in `onRender`', async () => {
215
211
)
216
212
}
217
213
218
- const {takeRender, replaceSnapshot, renderResultPromise} =
219
- renderToRenderStream <{
220
- value: number
221
- }>({
222
- onRender(info ) {
223
- // you can use `expect` here
224
- expect (info .count ).toBe (info .snapshot .value + 1 )
225
- },
226
- })
227
- const utils = await renderResultPromise
214
+ const {takeRender, replaceSnapshot, utils} = await renderToRenderStream <{
215
+ value: number
216
+ }>({
217
+ onRender(info ) {
218
+ // you can use `expect` here
219
+ expect (info .count ).toBe (info .snapshot .value + 1 )
220
+ },
221
+ })
228
222
const incrementButton = utils .getByText (' Increment' )
229
223
await userEvent .click (incrementButton )
230
224
await userEvent .click (incrementButton )
@@ -247,7 +241,7 @@ This library adds to matchers to `expect` that can be used like
247
241
248
242
``` tsx
249
243
test (' basic functionality' , async () => {
250
- const {takeRender} = renderToRenderStream (<RerenderingComponent />)
244
+ const {takeRender} = await renderToRenderStream (<RerenderingComponent />)
251
245
252
246
await expect (takeRender ).toRerender ()
253
247
await takeRender ()
@@ -285,17 +279,45 @@ await expect(snapshotStream).toRerender()
285
279
> [!TIP]
286
280
>
287
281
> If you don't want these matchers not to be automatically installed, you can
288
- > import from ` @testing- library/ react- render- stream` instead.
282
+ > import from ` @testing- library/ react- render- stream/ pure` instead.
283
+ > Keep in mind that if you use the ` / pure` import, you have to call the
284
+ > ` cleanup` export manually after each test.
285
+
286
+ ## Usage side-by side with ` @testing- library/ react` or other tools that set ` IS_REACT_ACT_ENVIRONMENT ` or use ` act`
287
+
288
+ This library is written in a way if should not be used with ` act` , and it will
289
+ throw an error if ` IS_REACT_ACT_ENVIRONMENT ` is ` true ` .
290
+
291
+ React Testing Library usually sets ` IS_REACT_ACT_ENVIRONMENT ` to ` true `
292
+ globally, and wraps some helpers like ` userEvent .click ` in ` act` calls.
293
+
294
+ To use this library side-by-side with React Testing Library, we ship the
295
+ ` disableActEnvironment` helper to undo these changes temporarily.
296
+
297
+ It returns a ` Disposable` and can be used together with the ` using` keyword to
298
+ automatically clean up once the scope is left:
289
299
290
- ## A note on ` act` .
300
+ ` ` ` ts
301
+ test (' my test' , () => {
302
+ using _disabledAct = disableActEnvironment ()
291
303
292
- You might want to avoid using this library with ` act` , as ` act`
293
- [can end up batching multiple renders](https://github.com/facebook/react/issues/30031#issuecomment-2183951296)
294
- into one in a way that would not happen in a production application.
304
+ // your test code here
295
305
296
- While that is convenient in a normal test suite, it defeats the purpose of this
297
- library.
306
+ // as soon as this scope is left, the environment will be cleaned up
307
+ })
308
+ ```
298
309
299
- Keep in mind that tools like ` userEvent .click ` use ` act` internally. Many of
300
- those calls would only trigger one render anyways, so it can be okay to use
301
- them, but avoid this for longer-running actions inside of ` act` calls.
310
+ If you cannot use ` using ` , you can also manually call the returned ` cleanup `
311
+ function:
312
+
313
+ ``` ts
314
+ test (' my test' , () => {
315
+ const {cleanup} = disableActEnvironment ()
316
+
317
+ try {
318
+ // your test code here
319
+ } finally {
320
+ cleanup ()
321
+ }
322
+ })
323
+ ```
0 commit comments