diff --git a/src/__tests__/renderHookToSnapshotStream.test.tsx b/src/__tests__/renderHookToSnapshotStream.test.tsx index 85d2bcec4..95179a6cc 100644 --- a/src/__tests__/renderHookToSnapshotStream.test.tsx +++ b/src/__tests__/renderHookToSnapshotStream.test.tsx @@ -4,10 +4,6 @@ import {EventEmitter} from 'node:events' import {test, expect} from '@jest/globals' import {renderHookToSnapshotStream} from '@testing-library/react-render-stream' import * as React from 'react' -import {withDisabledActWarnings} from '../__testHelpers__/withDisabledActWarnings.js' - -// @ts-expect-error this is not defined anywhere -globalThis.IS_REACT_ACT_ENVIRONMENT = false const testEvents = new EventEmitter<{ rerenderWithValue: [unknown] @@ -19,7 +15,7 @@ function useRerenderEvents(initialValue: unknown) { onChange => { const cb = (value: unknown) => { lastValueRef.current = value - withDisabledActWarnings(onChange) + onChange() } testEvents.addListener('rerenderWithValue', cb) return () => { diff --git a/src/__tests__/renderToRenderStream.test.tsx b/src/__tests__/renderToRenderStream.test.tsx index 5f93680c5..d5b3ee348 100644 --- a/src/__tests__/renderToRenderStream.test.tsx +++ b/src/__tests__/renderToRenderStream.test.tsx @@ -7,9 +7,6 @@ import { import {userEvent as baseUserEvent} from '@testing-library/user-event' import * as React from 'react' -// @ts-expect-error this is not defined anywhere -globalThis.IS_REACT_ACT_ENVIRONMENT = false - const userEvent = userEventWithoutAct(baseUserEvent) function CounterForm({ diff --git a/src/disableActEnvironment.ts b/src/disableActEnvironment.ts new file mode 100644 index 000000000..a3f2050ed --- /dev/null +++ b/src/disableActEnvironment.ts @@ -0,0 +1,22 @@ +const dispose: typeof Symbol.dispose = + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + Symbol.dispose ?? Symbol.for('nodejs.dispose') + +/** + * Temporarily disable act warnings. + * + * https://github.com/reactwg/react-18/discussions/102 + */ +export function disableActEnvironment(): {cleanup: () => void} & Disposable { + const anyThis = globalThis as any as {IS_REACT_ACT_ENVIRONMENT?: boolean} + const prevActEnv = anyThis.IS_REACT_ACT_ENVIRONMENT + anyThis.IS_REACT_ACT_ENVIRONMENT = false + + function cleanup() { + anyThis.IS_REACT_ACT_ENVIRONMENT = prevActEnv + } + return { + cleanup, + [dispose]: cleanup, + } +} diff --git a/src/expect/__tests__/renderStreamMatchers.test.tsx b/src/expect/__tests__/renderStreamMatchers.test.tsx index 614150fa4..ea19ced1b 100644 --- a/src/expect/__tests__/renderStreamMatchers.test.tsx +++ b/src/expect/__tests__/renderStreamMatchers.test.tsx @@ -7,7 +7,6 @@ import { } from '@testing-library/react-render-stream' import * as React from 'react' import {getExpectErrorMessage} from '../../__testHelpers__/getCleanedErrorMessage.js' -import {withDisabledActWarnings} from '../../__testHelpers__/withDisabledActWarnings.js' const testEvents = new EventEmitter<{ rerender: [] @@ -16,7 +15,7 @@ const testEvents = new EventEmitter<{ function useRerender() { const [, rerender] = React.useReducer(c => c + 1, 0) React.useEffect(() => { - const cb = () => void withDisabledActWarnings(rerender) + const cb = () => void rerender() testEvents.addListener('rerender', cb) return () => { diff --git a/src/pure.ts b/src/pure.ts index f99e9c590..5514e7816 100644 --- a/src/pure.ts +++ b/src/pure.ts @@ -19,5 +19,7 @@ export type {SnapshotStream} from './renderHookToSnapshotStream.js' export type {Assertable} from './assertable.js' -export {renderWithoutAct, cleanup} from './renderStream/renderWithoutAct.js' +export {renderWithoutAct, cleanup} from './renderWithoutAct.js' export {userEventWithoutAct} from './useWithoutAct.js' +export {disableActEnvironment} from './disableActEnvironment.js' +export {withDisabledActEnvironment} from './withDisabledActEnvironment.js' diff --git a/src/renderHookToSnapshotStream.tsx b/src/renderHookToSnapshotStream.tsx index 2b9599fb8..7d938271c 100644 --- a/src/renderHookToSnapshotStream.tsx +++ b/src/renderHookToSnapshotStream.tsx @@ -1,4 +1,4 @@ -import {RenderHookOptions} from '@testing-library/react' +import {type RenderHookOptions} from '@testing-library/react' import React from 'rehackt' import {createRenderStream} from './renderStream/createRenderStream.js' import {type NextRenderOptions} from './renderStream/createRenderStream.js' diff --git a/src/renderStream/createRenderStream.tsx b/src/renderStream/createRenderStream.tsx index 68f8ea9dc..c374db05b 100644 --- a/src/renderStream/createRenderStream.tsx +++ b/src/renderStream/createRenderStream.tsx @@ -2,12 +2,12 @@ import * as React from 'rehackt' import {RenderOptions} from '@testing-library/react' import {Assertable, markAssertable} from '../assertable.js' +import {disableActEnvironment} from '../disableActEnvironment.js' +import {renderWithoutAct, RenderWithoutActAsync} from '../renderWithoutAct.js' import {RenderInstance, type Render, type BaseRender} from './Render.js' import {type RenderStreamContextValue} from './context.js' import {RenderStreamContextProvider} from './context.js' -import {disableActWarnings} from './disableActWarnings.js' import {syncQueries, type Queries, type SyncQueries} from './syncQueries.js' -import {renderWithoutAct, RenderWithoutActAsync} from './renderWithoutAct.js' export type ValidSnapshot = // eslint-disable-next-line @typescript-eslint/no-invalid-void-type @@ -299,7 +299,7 @@ export function createRenderStream< // In many cases we do not control the resolution of the suspended // promise which results in noisy tests when the profiler due to // repeated act warnings. - const disabledActWarnings = disableActWarnings() + const disabledAct = disableActEnvironment() let error: unknown @@ -317,7 +317,7 @@ export function createRenderStream< if (!(error && error instanceof WaitForRenderTimeoutError)) { iteratorPosition++ } - disabledActWarnings.cleanup() + disabledAct.cleanup() } }, stream), getCurrentRender() { diff --git a/src/renderStream/disableActWarnings.ts b/src/renderStream/disableActWarnings.ts deleted file mode 100644 index 99b8cd65e..000000000 --- a/src/renderStream/disableActWarnings.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Temporarily disable act warnings. - * - * https://github.com/reactwg/react-18/discussions/102 - */ -export function disableActWarnings() { - const anyThis = globalThis as any as {IS_REACT_ACT_ENVIRONMENT?: boolean} - const prevActEnv = anyThis.IS_REACT_ACT_ENVIRONMENT - anyThis.IS_REACT_ACT_ENVIRONMENT = false - - return { - cleanup: () => { - anyThis.IS_REACT_ACT_ENVIRONMENT = prevActEnv - }, - } -} diff --git a/src/renderStream/renderWithoutAct.tsx b/src/renderWithoutAct.tsx similarity index 93% rename from src/renderStream/renderWithoutAct.tsx rename to src/renderWithoutAct.tsx index d098eedcd..76b50538f 100644 --- a/src/renderStream/renderWithoutAct.tsx +++ b/src/renderWithoutAct.tsx @@ -5,9 +5,10 @@ import { Queries, type RenderOptions, type RenderResult, -} from '@testing-library/react' +} from '@testing-library/react/pure.js' import React from 'react' -import {SyncQueries} from './syncQueries.js' +import {SyncQueries} from './renderStream/syncQueries.js' +import {withDisabledActEnvironment} from './withDisabledActEnvironment.js' // Ideally we'd just use a WeakMap where containers are keys and roots are values. // We use two variables so that we can bail out in constant time when we render with a new container (most common use case) @@ -32,8 +33,6 @@ function renderRoot( root: ReturnType }, ): RenderResult { - // @ts-expect-error this is not defined anywhere - globalThis.IS_REACT_ACT_ENVIRONMENT = false root.render( WrapperComponent ? React.createElement(WrapperComponent, null, ui) : ui, ) @@ -164,14 +163,16 @@ export function renderWithoutAct( } function createConcurrentRoot(container: ReactDOMClient.Container) { - const root = ReactDOMClient.createRoot(container) + const root = withDisabledActEnvironment(() => + ReactDOMClient.createRoot(container), + ) return { render(element: React.ReactNode) { - root.render(element) + withDisabledActEnvironment(() => root.render(element)) }, unmount() { - root.unmount() + withDisabledActEnvironment(() => root.unmount()) }, } } diff --git a/src/__testHelpers__/withDisabledActWarnings.ts b/src/withDisabledActEnvironment.ts similarity index 52% rename from src/__testHelpers__/withDisabledActWarnings.ts rename to src/withDisabledActEnvironment.ts index ee76a9411..d8c9def59 100644 --- a/src/__testHelpers__/withDisabledActWarnings.ts +++ b/src/withDisabledActEnvironment.ts @@ -1,7 +1,7 @@ -import {disableActWarnings} from '../renderStream/disableActWarnings.js' +import {disableActEnvironment} from './disableActEnvironment.js' -export function withDisabledActWarnings(cb: () => T): T { - const disabledActWarnings = disableActWarnings() +export function withDisabledActEnvironment(cb: () => T): T { + const disabledActWarnings = disableActEnvironment() let result: T try { result = cb()