22
33## What is this library?
44
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.
88
99## Who is this library for?
1010
@@ -36,7 +36,7 @@ test('iterate through renders with DOM snapshots', async () => {
3636 const {takeRender , render } = createRenderStream ({
3737 snapshotDOM: true ,
3838 })
39- const utils = render (< Counter / > )
39+ const utils = await render (< Counter / > )
4040 const incrementButton = utils .getByText (' Increment' )
4141 await userEvent .click (incrementButton)
4242 await userEvent .click (incrementButton)
@@ -63,31 +63,27 @@ test('iterate through renders with DOM snapshots', async () => {
6363In every place you would call
6464
6565``` 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)
6868```
6969
7070you can also call
7171
7272``` 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+ )
7677```
7778
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-
8379### ` renderHookToSnapshotStream `
8480
8581Usage is very similar to RTL's ` renderHook ` , but you get a ` snapshotStream `
8682object back that you can iterate with ` takeSnapshot ` calls.
8783
8884``` jsx
8985test (' `useQuery` with `skip`' , async () => {
90- const {takeSnapshot , rerender } = renderHookToSnapshotStream (
86+ const {takeSnapshot , rerender } = await renderHookToSnapshotStream (
9187 ({skip}) => useQuery (query, {skip}),
9288 {
9389 wrapper : ({children}) => < Provider client= {client}> {children}< / Provider> ,
@@ -105,7 +101,7 @@ test('`useQuery` with `skip`', async () => {
105101 expect (result .data ).toEqual ({hello: ' world 1' })
106102 }
107103
108- rerender ({skip: true })
104+ await rerender ({skip: true })
109105 {
110106 const snapshot = await takeSnapshot ()
111107 expect (snapshot .loading ).toBe (false )
@@ -146,7 +142,7 @@ test('`useTrackRenders` with suspense', async () => {
146142 }
147143
148144 const {takeRender , render } = createRenderStream ()
149- render (< App / > )
145+ await render (< App / > )
150146 {
151147 const {renderedComponents } = await takeRender ()
152148 expect (renderedComponents).toEqual ([App, LoadingComponent])
@@ -179,7 +175,7 @@ test('custom snapshots with `replaceSnapshot`', async () => {
179175 const {takeRender, replaceSnapshot, render} = createRenderStream <{
180176 value: number
181177 }>()
182- const utils = render (<Counter />)
178+ const utils = await render (<Counter />)
183179 const incrementButton = utils .getByText (' Increment' )
184180 await userEvent .click (incrementButton )
185181 {
@@ -215,16 +211,14 @@ test('assertions in `onRender`', async () => {
215211 )
216212 }
217213
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+ })
228222 const incrementButton = utils .getByText (' Increment' )
229223 await userEvent .click (incrementButton )
230224 await userEvent .click (incrementButton )
@@ -247,7 +241,7 @@ This library adds to matchers to `expect` that can be used like
247241
248242``` tsx
249243test (' basic functionality' , async () => {
250- const {takeRender} = renderToRenderStream (<RerenderingComponent />)
244+ const {takeRender} = await renderToRenderStream (<RerenderingComponent />)
251245
252246 await expect (takeRender ).toRerender ()
253247 await takeRender ()
@@ -285,17 +279,45 @@ await expect(snapshotStream).toRerender()
285279> [!TIP]
286280>
287281> 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:
289299
290- ## A note on ` act` .
300+ ` ` ` ts
301+ test (' my test' , () => {
302+ using _disabledAct = disableActEnvironment ()
291303
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
295305
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+ ```
298309
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