UNPKG

@testing-library/react-render-stream

Version:
1 lines 56.7 kB
{"version":3,"sources":["../src/pure.ts","../src/renderStream/createRenderStream.tsx","../src/assertable.ts","../src/renderWithoutAct.tsx","../src/disableActEnvironment.ts","../src/renderStream/Render.tsx","../src/renderStream/context.tsx","../src/renderStream/syncQueries.ts","../src/renderStream/useTrackRenders.ts","../src/renderHookToSnapshotStream.tsx"],"sourcesContent":["export type {\n NextRenderOptions,\n RenderStream,\n RenderStreamWithRenderFn,\n RenderStreamOptions,\n} from './renderStream/createRenderStream.js'\nexport {\n createRenderStream,\n WaitForRenderTimeoutError,\n} from './renderStream/createRenderStream.js'\nexport {useTrackRenders} from './renderStream/useTrackRenders.js'\n\nexport type {SyncScreen} from './renderStream/Render.js'\n\nexport {renderHookToSnapshotStream} from './renderHookToSnapshotStream.js'\nexport type {SnapshotStream} from './renderHookToSnapshotStream.js'\n\nexport type {Assertable} from './assertable.js'\n\nexport {\n cleanup,\n type RenderWithoutActAsync as AsyncRenderFn,\n} from './renderWithoutAct.js'\nexport {\n disableActEnvironment,\n type DisableActEnvironmentOptions,\n} from './disableActEnvironment.js'\n","import * as React from 'rehackt'\n\nimport {type RenderOptions} from '@testing-library/react/pure.js'\nimport {Assertable, markAssertable} from '../assertable.js'\nimport {\n renderWithoutAct,\n type RenderWithoutActAsync,\n} from '../renderWithoutAct.js'\nimport {RenderInstance, type Render, type BaseRender} from './Render.js'\nimport {type RenderStreamContextValue} from './context.js'\nimport {RenderStreamContextProvider} from './context.js'\nimport {syncQueries, type Queries, type SyncQueries} from './syncQueries.js'\n\nexport type ValidSnapshot =\n // eslint-disable-next-line @typescript-eslint/no-invalid-void-type\n void | (object & {/* not a function */ call?: never})\n\nexport interface NextRenderOptions {\n timeout?: number\n}\n\ninterface ReplaceSnapshot<Snapshot> {\n (newSnapshot: Snapshot): void\n (updateSnapshot: (lastSnapshot: Readonly<Snapshot>) => Snapshot): void\n}\n\ninterface MergeSnapshot<Snapshot> {\n (partialSnapshot: Partial<Snapshot>): void\n (\n updatePartialSnapshot: (\n lastSnapshot: Readonly<Snapshot>,\n ) => Partial<Snapshot>,\n ): void\n}\n\nexport interface RenderStream<\n Snapshot extends ValidSnapshot,\n Q extends Queries = SyncQueries,\n> {\n // Allows for partial updating of the snapshot by shallow merging the results\n mergeSnapshot: MergeSnapshot<Snapshot>\n // Performs a full replacement of the snapshot\n replaceSnapshot: ReplaceSnapshot<Snapshot>\n /**\n * An array of all renders that have happened so far.\n * Errors thrown during component render will be captured here, too.\n */\n renders: Array<\n | Render<Snapshot, Q>\n | {phase: 'snapshotError'; count: number; error: unknown}\n >\n /**\n * Peeks the next render from the current iterator position, without advancing the iterator.\n * If no render has happened yet, it will wait for the next render to happen.\n * @throws {WaitForRenderTimeoutError} if no render happens within the timeout\n */\n peekRender: (options?: NextRenderOptions) => Promise<Render<Snapshot, Q>>\n /**\n * Iterates to the next render and returns it.\n * If no render has happened yet, it will wait for the next render to happen.\n * @throws {WaitForRenderTimeoutError} if no render happens within the timeout\n */\n takeRender: Assertable &\n ((options?: NextRenderOptions) => Promise<Render<Snapshot, Q>>)\n /**\n * Returns the total number of renders.\n */\n totalRenderCount: () => number\n /**\n * Returns the current render.\n * @throws {Error} if no render has happened yet\n */\n getCurrentRender: () => Render<Snapshot, Q>\n /**\n * Waits for the next render to happen.\n * Does not advance the render iterator.\n */\n waitForNextRender: (\n options?: NextRenderOptions,\n ) => Promise<Render<Snapshot, Q>>\n}\n\nexport interface RenderStreamWithRenderFn<\n Snapshot extends ValidSnapshot,\n Q extends Queries = SyncQueries,\n> extends RenderStream<Snapshot, Q> {\n render: RenderWithoutActAsync\n}\n\nexport type RenderStreamOptions<\n Snapshot extends ValidSnapshot,\n Q extends Queries = SyncQueries,\n> = {\n onRender?: (\n info: BaseRender & {\n snapshot: Snapshot\n replaceSnapshot: ReplaceSnapshot<Snapshot>\n mergeSnapshot: MergeSnapshot<Snapshot>\n },\n ) => void\n snapshotDOM?: boolean\n initialSnapshot?: Snapshot\n /**\n * This will skip renders during which no renders tracked by\n * `useTrackRenders` occured.\n */\n skipNonTrackingRenders?: boolean\n queries?: Q\n}\n\nexport class WaitForRenderTimeoutError extends Error {\n constructor() {\n super('Exceeded timeout waiting for next render.')\n this.name = 'WaitForRenderTimeoutError'\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n\nexport function createRenderStream<\n Snapshot extends ValidSnapshot = void,\n Q extends Queries = SyncQueries,\n>({\n onRender,\n snapshotDOM = false,\n initialSnapshot,\n skipNonTrackingRenders,\n queries = syncQueries as any as Q,\n}: RenderStreamOptions<Snapshot, Q> = {}): RenderStreamWithRenderFn<\n Snapshot,\n Q\n> {\n // creating the object first and then assigning in all the properties\n // allows keeping the object instance for reference while the members are\n // created, which is important for the `markAssertable` function\n const stream = {} as any as RenderStreamWithRenderFn<Snapshot, Q>\n\n let nextRender: Promise<Render<Snapshot, Q>> | undefined,\n resolveNextRender: ((render: Render<Snapshot, Q>) => void) | undefined,\n rejectNextRender: ((error: unknown) => void) | undefined\n function resetNextRender() {\n nextRender = undefined\n resolveNextRender = undefined\n rejectNextRender = undefined\n }\n const snapshotRef = {current: initialSnapshot}\n const replaceSnapshot: ReplaceSnapshot<Snapshot> = snap => {\n if (typeof snap === 'function') {\n if (!initialSnapshot) {\n throw new Error(\n 'Cannot use a function to update the snapshot if no initial snapshot was provided.',\n )\n }\n snapshotRef.current = snap(\n typeof snapshotRef.current === 'object'\n ? // \"cheap best effort\" to prevent accidental mutation of the last snapshot\n {...snapshotRef.current}\n : snapshotRef.current!,\n )\n } else {\n snapshotRef.current = snap\n }\n }\n\n const mergeSnapshot: MergeSnapshot<Snapshot> = partialSnapshot => {\n replaceSnapshot(snapshot => ({\n ...snapshot,\n ...(typeof partialSnapshot === 'function'\n ? partialSnapshot(snapshot)\n : partialSnapshot),\n }))\n }\n\n const renderStreamContext: RenderStreamContextValue = {\n renderedComponents: [],\n }\n\n const profilerOnRender: React.ProfilerOnRenderCallback = (\n id,\n phase,\n actualDuration,\n baseDuration,\n startTime,\n commitTime,\n ) => {\n if (\n skipNonTrackingRenders &&\n renderStreamContext.renderedComponents.length === 0\n ) {\n return\n }\n\n const renderBase = {\n id,\n phase,\n actualDuration,\n baseDuration,\n startTime,\n commitTime,\n count: stream.renders.length + 1,\n }\n try {\n /*\n * The `onRender` function could contain `expect` calls that throw\n * `JestAssertionError`s - but we are still inside of React, where errors\n * might be swallowed.\n * So we record them and re-throw them in `takeRender`\n * Additionally, we reject the `waitForNextRender` promise.\n */\n onRender?.({\n ...renderBase,\n replaceSnapshot,\n mergeSnapshot,\n snapshot: snapshotRef.current!,\n })\n\n const snapshot = snapshotRef.current as Snapshot\n const domSnapshot = snapshotDOM\n ? window.document.body.innerHTML\n : undefined\n const render = new RenderInstance(\n renderBase,\n snapshot,\n domSnapshot,\n renderStreamContext.renderedComponents,\n queries,\n )\n renderStreamContext.renderedComponents = []\n stream.renders.push(render)\n resolveNextRender?.(render)\n } catch (error) {\n stream.renders.push({\n phase: 'snapshotError',\n count: stream.renders.length,\n error,\n })\n rejectNextRender?.(error)\n } finally {\n resetNextRender()\n }\n }\n\n let iteratorPosition = 0\n function Wrapper({children}: {children: React.ReactNode}) {\n return (\n <RenderStreamContextProvider value={renderStreamContext}>\n <React.Profiler id=\"test\" onRender={profilerOnRender}>\n {children}\n </React.Profiler>\n </RenderStreamContextProvider>\n )\n }\n\n const render: RenderWithoutActAsync = (async (\n ui: React.ReactNode,\n options?: RenderOptions<any, any, any>,\n ) => {\n const ret = await renderWithoutAct(ui, {\n ...options,\n wrapper: props => {\n const ParentWrapper = options?.wrapper ?? React.Fragment\n return (\n <ParentWrapper>\n <Wrapper>{props.children}</Wrapper>\n </ParentWrapper>\n )\n },\n })\n if (stream.renders.length === 0) {\n await stream.waitForNextRender()\n }\n const origRerender = ret.rerender\n ret.rerender = async function rerender(rerenderUi: React.ReactNode) {\n const previousRenderCount = stream.renders.length\n try {\n return await origRerender(rerenderUi)\n } finally {\n // only wait for the next render if the rerender was not\n // synchronous (React 17)\n if (previousRenderCount === stream.renders.length) {\n await stream.waitForNextRender()\n }\n }\n }\n return ret\n }) as unknown as RenderWithoutActAsync // TODO\n\n Object.assign<typeof stream, typeof stream>(stream, {\n replaceSnapshot,\n mergeSnapshot,\n renders: new Array<\n | Render<Snapshot, Q>\n | {phase: 'snapshotError'; count: number; error: unknown}\n >(),\n totalRenderCount() {\n return stream.renders.length\n },\n async peekRender(options: NextRenderOptions = {}) {\n try {\n if (iteratorPosition < stream.renders.length) {\n const peekedRender = stream.renders[iteratorPosition]\n\n if (peekedRender.phase === 'snapshotError') {\n throw peekedRender.error\n }\n\n return peekedRender\n }\n return await stream\n .waitForNextRender(options)\n .catch(rethrowWithCapturedStackTrace(stream.peekRender))\n } finally {\n /** drain microtask queue */\n await new Promise<void>(resolve => {\n setTimeout(() => {\n resolve()\n }, 0)\n })\n }\n },\n takeRender: markAssertable(async function takeRender(\n options: NextRenderOptions = {},\n ) {\n let error: unknown\n\n try {\n return await stream.peekRender({\n ...options,\n })\n } catch (e) {\n if (e instanceof Object) {\n Error.captureStackTrace(e, stream.takeRender)\n }\n error = e\n throw e\n } finally {\n if (!(error && error instanceof WaitForRenderTimeoutError)) {\n iteratorPosition++\n }\n }\n }, stream),\n getCurrentRender() {\n // The \"current\" render should point at the same render that the most\n // recent `takeRender` call returned, so we need to get the \"previous\"\n // iterator position, otherwise `takeRender` advances the iterator\n // to the next render. This means we need to call `takeRender` at least\n // once before we can get a current render.\n const currentPosition = iteratorPosition - 1\n\n if (currentPosition < 0) {\n throw new Error(\n 'No current render available. You need to call `takeRender` before you can get the current render.',\n )\n }\n\n const currentRender = stream.renders[currentPosition]\n\n if (currentRender.phase === 'snapshotError') {\n throw currentRender.error\n }\n return currentRender\n },\n waitForNextRender({timeout = 1000}: NextRenderOptions = {}) {\n if (!nextRender) {\n nextRender = Promise.race<Render<Snapshot, Q>>([\n new Promise<Render<Snapshot, Q>>((resolve, reject) => {\n resolveNextRender = resolve\n rejectNextRender = reject\n }),\n new Promise<Render<Snapshot, Q>>((_, reject) =>\n setTimeout(() => {\n const error = new WaitForRenderTimeoutError()\n Error.captureStackTrace(error, stream.waitForNextRender)\n reject(error)\n resetNextRender()\n }, timeout),\n ),\n ])\n }\n return nextRender\n },\n render,\n })\n return stream\n}\n\nfunction rethrowWithCapturedStackTrace(constructorOpt: Function | undefined) {\n return function catchFn(error: unknown) {\n if (error instanceof Object) {\n Error.captureStackTrace(error, constructorOpt)\n }\n throw error\n }\n}\n","import {type RenderStream} from './renderStream/createRenderStream.js'\n\nexport const assertableSymbol = Symbol.for(\n '@testing-library/react-render-stream:assertable',\n)\n\n/**\n * A function or object that can be used in assertions, like e.g.\n ```ts\n expect(assertable).toRerender()\n expect(assertable).not.toRerender()\n expect(assertable).toRenderExactlyTimes(3)\n ```\n */\nexport type Assertable = {\n [assertableSymbol]: RenderStream<any, any>\n}\n\nexport function markAssertable<T extends {}>(\n assertable: T,\n stream: RenderStream<any, any>,\n): T & Assertable {\n return Object.assign(assertable, {\n [assertableSymbol]: stream,\n })\n}\n","import * as ReactDOMClient from 'react-dom/client'\nimport * as ReactDOM from 'react-dom'\nimport {type RenderOptions} from '@testing-library/react/pure.js'\nimport {\n BoundFunction,\n getQueriesForElement,\n prettyDOM,\n prettyFormat,\n type Queries,\n} from '@testing-library/dom'\nimport React from 'react'\nimport {SyncQueries} from './renderStream/syncQueries.js'\nimport {\n disableActEnvironment,\n DisableActEnvironmentOptions,\n} from './disableActEnvironment.js'\n\n// Ideally we'd just use a WeakMap where containers are keys and roots are values.\n// We use two variables so that we can bail out in constant time when we render with a new container (most common use case)\n\nconst mountedContainers: Set<import('react-dom').Container> = new Set()\nconst mountedRootEntries: Array<{\n container: import('react-dom').Container\n root: ReturnType<typeof createConcurrentRoot>\n}> = []\n\nexport type AsyncRenderResult<\n Q extends Queries = SyncQueries,\n Container extends ReactDOMClient.Container = HTMLElement,\n BaseElement extends ReactDOMClient.Container = Container,\n> = {\n container: Container\n baseElement: BaseElement\n debug: (\n baseElement?:\n | ReactDOMClient.Container\n | Array<ReactDOMClient.Container>\n | undefined,\n maxLength?: number | undefined,\n options?: prettyFormat.OptionsReceived | undefined,\n ) => void\n rerender: (rerenderUi: React.ReactNode) => Promise<void>\n unmount: () => void\n asFragment: () => DocumentFragment\n} & {[P in keyof Q]: BoundFunction<Q[P]>}\n\nfunction renderRoot(\n ui: React.ReactNode,\n {\n baseElement,\n container,\n queries,\n wrapper: WrapperComponent,\n root,\n }: Pick<RenderOptions<Queries>, 'queries' | 'wrapper'> & {\n baseElement: ReactDOMClient.Container\n container: ReactDOMClient.Container\n root: ReturnType<typeof createConcurrentRoot>\n },\n): AsyncRenderResult<{}, any, any> {\n root.render(\n WrapperComponent ? React.createElement(WrapperComponent, null, ui) : ui,\n )\n\n return {\n container,\n baseElement,\n debug: (el = baseElement, maxLength, options) =>\n Array.isArray(el)\n ? // eslint-disable-next-line no-console\n el.forEach(e =>\n console.log(prettyDOM(e as Element, maxLength, options)),\n )\n : // eslint-disable-next-line no-console,\n console.log(prettyDOM(el as Element, maxLength, options)),\n unmount: () => {\n root.unmount()\n },\n rerender: async rerenderUi => {\n renderRoot(rerenderUi, {\n container,\n baseElement,\n root,\n wrapper: WrapperComponent,\n })\n // Intentionally do not return anything to avoid unnecessarily complicating the API.\n // folks can use all the same utilities we return in the first place that are bound to the container\n },\n asFragment: () => {\n /* istanbul ignore else (old jsdom limitation) */\n if (typeof document.createRange === 'function') {\n return document\n .createRange()\n .createContextualFragment((container as HTMLElement).innerHTML)\n } else {\n const template = document.createElement('template')\n template.innerHTML = (container as HTMLElement).innerHTML\n return template.content\n }\n },\n ...getQueriesForElement<Queries>(baseElement as HTMLElement, queries),\n }\n}\n\nexport type RenderWithoutActAsync = {\n <\n Q extends Queries = SyncQueries,\n Container extends ReactDOMClient.Container = HTMLElement,\n BaseElement extends ReactDOMClient.Container = Container,\n >(\n this: any,\n ui: React.ReactNode,\n options: Pick<\n RenderOptions<Q, Container, BaseElement>,\n 'container' | 'baseElement' | 'queries' | 'wrapper'\n >,\n ): Promise<AsyncRenderResult<Q, Container, BaseElement>>\n (\n this: any,\n ui: React.ReactNode,\n options?:\n | Pick<RenderOptions, 'container' | 'baseElement' | 'wrapper'>\n | undefined,\n ): Promise<\n AsyncRenderResult<\n SyncQueries,\n ReactDOMClient.Container,\n ReactDOMClient.Container\n >\n >\n}\n\nexport const renderWithoutAct =\n _renderWithoutAct as unknown as RenderWithoutActAsync\n\nasync function _renderWithoutAct(\n ui: React.ReactNode,\n {\n container,\n baseElement = container,\n queries,\n wrapper,\n }: Pick<\n RenderOptions<SyncQueries>,\n 'container' | 'baseElement' | 'wrapper' | 'queries'\n > = {},\n): Promise<AsyncRenderResult<{}>> {\n if (!baseElement) {\n // default to document.body instead of documentElement to avoid output of potentially-large\n // head elements (such as JSS style blocks) in debug output\n baseElement = document.body\n }\n if (!container) {\n container = baseElement.appendChild(document.createElement('div'))\n }\n\n let root: ReturnType<typeof createConcurrentRoot>\n // eslint-disable-next-line no-negated-condition -- we want to map the evolution of this over time. The root is created first. Only later is it re-used so we don't want to read the case that happens later first.\n if (!mountedContainers.has(container)) {\n root = (\n ReactDOM.version.startsWith('16') || ReactDOM.version.startsWith('17')\n ? createLegacyRoot\n : createConcurrentRoot\n )(container)\n mountedRootEntries.push({container, root})\n // we'll add it to the mounted containers regardless of whether it's actually\n // added to document.body so the cleanup method works regardless of whether\n // they're passing us a custom container or not.\n mountedContainers.add(container)\n } else {\n mountedRootEntries.forEach(rootEntry => {\n // Else is unreachable since `mountedContainers` has the `container`.\n // Only reachable if one would accidentally add the container to `mountedContainers` but not the root to `mountedRootEntries`\n /* istanbul ignore else */\n if (rootEntry.container === container) {\n root = rootEntry.root\n }\n })\n }\n\n return renderRoot(ui, {\n baseElement,\n container,\n queries,\n wrapper,\n root: root!,\n })\n}\n\nfunction createLegacyRoot(container: ReactDOMClient.Container) {\n return {\n render(element: React.ReactNode) {\n ReactDOM.render(element as unknown as React.ReactElement, container)\n },\n unmount() {\n ReactDOM.unmountComponentAtNode(container)\n },\n }\n}\n\nfunction createConcurrentRoot(container: ReactDOMClient.Container) {\n const anyThis = globalThis as any as {IS_REACT_ACT_ENVIRONMENT?: boolean}\n if (anyThis.IS_REACT_ACT_ENVIRONMENT) {\n throw new Error(`Tried to create a React root for a render stream inside a React act environment.\nThis is not supported. Please use \\`disableActEnvironment\\` to disable the act environment for this test.`)\n }\n const root = ReactDOMClient.createRoot(container)\n\n return {\n render(element: React.ReactNode) {\n if (anyThis.IS_REACT_ACT_ENVIRONMENT) {\n throw new Error(`Tried to render a render stream inside a React act environment.\n This is not supported. Please use \\`disableActEnvironment\\` to disable the act environment for this test.`)\n }\n root.render(element)\n },\n unmount() {\n root.unmount()\n },\n }\n}\n\nexport function cleanup() {\n if (!mountedRootEntries.length) {\n // nothing to clean up\n return\n }\n\n // there is a good chance this happens outside of a test, where the user\n // has no control over enabling or disabling the React Act environment,\n // so we do it for them here.\n\n const disabledAct = disableActEnvironment({\n preventModification: false,\n adjustTestingLibConfig: false,\n } satisfies /* ensure that all possible options are passed here in case we add more in the future */ Required<DisableActEnvironmentOptions>)\n try {\n for (const {root, container} of mountedRootEntries) {\n root.unmount()\n\n if (container.parentNode === document.body) {\n document.body.removeChild(container)\n }\n }\n mountedRootEntries.length = 0\n mountedContainers.clear()\n } finally {\n disabledAct.cleanup()\n }\n}\n","import {getConfig} from '@testing-library/dom'\n\nconst dispose: typeof Symbol.dispose =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n Symbol.dispose ?? Symbol.for('nodejs.dispose')\n\nexport interface DisableActEnvironmentOptions {\n /**\n * If `true`, all modifications of values set by `disableActEnvironment`\n * will be prevented until `cleanup` is called.\n *\n * @default true\n */\n preventModification?: boolean\n\n /**\n * If `true`, will change the configuration of the testing library to\n * prevent auto-wrapping e.g. `userEvent` calls in `act`.\n *\n * @default true\n */\n adjustTestingLibConfig?: boolean\n}\n\n/**\n * Helper to temporarily disable a React 18+ act environment.\n *\n * By default, this also adjusts the configuration of @testing-library/dom\n * to prevent auto-wrapping of user events in `act`, as well as preventing\n * all modifications of values set by this method until `cleanup` is called\n * or the returned `Disposable` is disposed of.\n *\n * Both of these behaviors can be disabled with the option, of the defaults\n * can be changed for all calls to this method by modifying\n * `disableActEnvironment.defaultOptions`.\n *\n * This returns a disposable and can be used in combination with `using` to\n * automatically restore the state from before this method call after your test.\n *\n * @example\n * ```ts\n * test(\"my test\", () => {\n * using _disabledAct = disableActEnvironment();\n *\n * // your test code here\n *\n * // as soon as this scope is left, the environment will be cleaned up\n * })\n * ```\n *\n * If you can not use the explicit resouce management keyword `using`,\n * you can also manually call `cleanup`:\n *\n * @example\n * ```ts\n * test(\"my test\", () => {\n * const { cleanup } = disableActEnvironment();\n *\n * try {\n * // your test code here\n * } finally {\n * cleanup();\n * }\n * })\n * ```\n *\n * For more context on what `act` is and why you shouldn't use it in renderStream tests,\n * https://github.com/reactwg/react-18/discussions/102 is probably the best resource we have.\n */\nexport function disableActEnvironment({\n preventModification = disableActEnvironment.defaultOptions\n .preventModification,\n adjustTestingLibConfig = disableActEnvironment.defaultOptions\n .adjustTestingLibConfig,\n}: DisableActEnvironmentOptions = {}): {cleanup: () => void} & Disposable {\n const typedGlobal = globalThis as any as {IS_REACT_ACT_ENVIRONMENT?: boolean}\n const cleanupFns: Array<() => void> = []\n\n // core functionality\n {\n const previous = typedGlobal.IS_REACT_ACT_ENVIRONMENT\n cleanupFns.push(() => {\n Object.defineProperty(typedGlobal, 'IS_REACT_ACT_ENVIRONMENT', {\n value: previous,\n writable: true,\n configurable: true,\n })\n })\n Object.defineProperty(\n typedGlobal,\n 'IS_REACT_ACT_ENVIRONMENT',\n getNewPropertyDescriptor(false, preventModification),\n )\n }\n\n if (adjustTestingLibConfig) {\n const config = getConfig()\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const {asyncWrapper, eventWrapper} = config\n cleanupFns.push(() => {\n Object.defineProperty(config, 'asyncWrapper', {\n value: asyncWrapper,\n writable: true,\n configurable: true,\n })\n Object.defineProperty(config, 'eventWrapper', {\n value: eventWrapper,\n writable: true,\n configurable: true,\n })\n })\n\n Object.defineProperty(\n config,\n 'asyncWrapper',\n getNewPropertyDescriptor<typeof asyncWrapper>(\n fn => fn(),\n preventModification,\n ),\n )\n Object.defineProperty(\n config,\n 'eventWrapper',\n getNewPropertyDescriptor<typeof eventWrapper>(\n fn => fn(),\n preventModification,\n ),\n )\n }\n\n function cleanup() {\n while (cleanupFns.length > 0) {\n cleanupFns.pop()!()\n }\n }\n return {\n cleanup,\n [dispose]: cleanup,\n }\n}\n\n/**\n * Default options for `disableActEnvironment`.\n *\n * This can be modified to change the default options for all calls to `disableActEnvironment`.\n */\ndisableActEnvironment.defaultOptions = {\n preventModification: true,\n adjustTestingLibConfig: true,\n} satisfies Required<DisableActEnvironmentOptions> as Required<DisableActEnvironmentOptions>\n\nfunction getNewPropertyDescriptor<T>(\n value: T,\n preventModification: boolean,\n): PropertyDescriptor {\n return preventModification\n ? {\n configurable: true,\n enumerable: true,\n get() {\n return value\n },\n set() {},\n }\n : {\n configurable: true,\n enumerable: true,\n writable: true,\n value,\n }\n}\n","import {screen, getQueriesForElement, Screen} from '@testing-library/dom'\nimport {JSDOM, VirtualConsole} from 'jsdom'\nimport {\n BoundSyncFunctions,\n type Queries,\n type SyncQueries,\n} from './syncQueries.js'\n\nexport interface BaseRender {\n id: string\n phase: 'mount' | 'update' | 'nested-update'\n actualDuration: number\n baseDuration: number\n startTime: number\n commitTime: number\n /**\n * The number of renders that have happened so far (including this render).\n */\n count: number\n}\n\nexport type SyncScreen<Q extends Queries = SyncQueries> =\n BoundSyncFunctions<Q> & Pick<Screen, 'debug' | 'logTestingPlaygroundURL'>\n\nexport interface Render<Snapshot, Q extends Queries = SyncQueries>\n extends BaseRender {\n /**\n * The snapshot, as returned by the `takeSnapshot` option of `createRenderStream`.\n */\n snapshot: Snapshot\n /**\n * A DOM snapshot of the rendered component, if the `snapshotDOM`\n * option of `createRenderStream` was enabled.\n */\n readonly domSnapshot: HTMLElement\n /**\n * Returns a callback to receive a `screen` instance that is scoped to the\n * DOM snapshot of this `Render` instance.\n * Note: this is used as a callback to prevent linter errors.\n * @example\n * ```diff\n * const { withinDOM } = RenderedComponent.takeRender();\n * -expect(screen.getByText(\"foo\")).toBeInTheDocument();\n * +expect(withinDOM().getByText(\"foo\")).toBeInTheDocument();\n * ```\n */\n withinDOM: () => SyncScreen<Q>\n\n renderedComponents: Array<string | React.ComponentType>\n}\n\nexport class RenderInstance<Snapshot, Q extends Queries = SyncQueries>\n implements Render<Snapshot, Q>\n{\n id: string\n phase: 'mount' | 'update' | 'nested-update'\n actualDuration: number\n baseDuration: number\n startTime: number\n commitTime: number\n count: number\n public snapshot: Snapshot\n private stringifiedDOM: string | undefined\n public renderedComponents: Array<string | React.ComponentType>\n private queries: Q\n\n constructor(\n baseRender: BaseRender,\n snapshot: Snapshot,\n stringifiedDOM: string | undefined,\n renderedComponents: Array<string | React.ComponentType>,\n queries: Q,\n ) {\n this.snapshot = snapshot\n this.stringifiedDOM = stringifiedDOM\n this.renderedComponents = renderedComponents\n this.id = baseRender.id\n this.phase = baseRender.phase\n this.actualDuration = baseRender.actualDuration\n this.baseDuration = baseRender.baseDuration\n this.startTime = baseRender.startTime\n this.commitTime = baseRender.commitTime\n this.count = baseRender.count\n this.queries = queries\n }\n\n private _domSnapshot: HTMLElement | undefined\n get domSnapshot() {\n if (this._domSnapshot) return this._domSnapshot\n if (!this.stringifiedDOM) {\n throw new Error(\n 'DOM snapshot is not available - please set the `snapshotDOM` option',\n )\n }\n\n const virtualConsole = new VirtualConsole()\n virtualConsole.on('jsdomError', (error: any) => {\n throw error\n })\n\n const snapDOM = new JSDOM(this.stringifiedDOM, {\n runScripts: 'dangerously',\n virtualConsole,\n })\n const document = snapDOM.window.document\n const body = document.body\n const script = document.createElement('script')\n script.type = 'text/javascript'\n script.text = `\n ${errorOnDomInteraction.toString()};\n ${errorOnDomInteraction.name}();\n `\n body.appendChild(script)\n body.removeChild(script)\n\n return (this._domSnapshot = body)\n }\n\n get withinDOM(): () => SyncScreen<Q> {\n const snapScreen = Object.assign(\n getQueriesForElement<Q>(\n this.domSnapshot,\n this.queries,\n ) as any as BoundSyncFunctions<Q>,\n {\n debug: (\n ...[dom = this.domSnapshot, ...rest]: Parameters<typeof screen.debug>\n ) => screen.debug(dom, ...rest),\n logTestingPlaygroundURL: (\n ...[dom = this.domSnapshot, ...rest]: Parameters<\n typeof screen.logTestingPlaygroundURL\n >\n ) => screen.logTestingPlaygroundURL(dom, ...rest),\n },\n )\n return () => snapScreen\n }\n}\n\nexport function errorOnDomInteraction() {\n const events: Array<keyof DocumentEventMap> = [\n 'auxclick',\n 'blur',\n 'change',\n 'click',\n 'copy',\n 'cut',\n 'dblclick',\n 'drag',\n 'dragend',\n 'dragenter',\n 'dragleave',\n 'dragover',\n 'dragstart',\n 'drop',\n 'focus',\n 'focusin',\n 'focusout',\n 'input',\n 'keydown',\n 'keypress',\n 'keyup',\n 'mousedown',\n 'mouseenter',\n 'mouseleave',\n 'mousemove',\n 'mouseout',\n 'mouseover',\n 'mouseup',\n 'paste',\n 'pointercancel',\n 'pointerdown',\n 'pointerenter',\n 'pointerleave',\n 'pointermove',\n 'pointerout',\n 'pointerover',\n 'pointerup',\n 'scroll',\n 'select',\n 'selectionchange',\n 'selectstart',\n 'submit',\n 'toggle',\n 'touchcancel',\n 'touchend',\n 'touchmove',\n 'touchstart',\n 'wheel',\n ]\n function warnOnDomInteraction() {\n throw new Error(`\n DOM interaction with a snapshot detected in test.\n Please don't interact with the DOM you get from \\`withinDOM\\`,\n but still use \\`screen\\` to get elements for simulating user interaction.\n `)\n }\n events.forEach(event => {\n document.addEventListener(event, warnOnDomInteraction)\n })\n}\n","import * as React from 'rehackt'\n\nexport interface RenderStreamContextValue {\n renderedComponents: Array<React.ComponentType | string>\n}\n\nconst RenderStreamContext = React.createContext<\n RenderStreamContextValue | undefined\n>(undefined)\n\nexport function RenderStreamContextProvider({\n children,\n value,\n}: {\n children: React.ReactNode\n value: RenderStreamContextValue\n}) {\n const parentContext = useRenderStreamContext()\n\n if (parentContext) {\n throw new Error('Render streams should not be nested in the same tree')\n }\n\n return (\n <RenderStreamContext.Provider value={value}>\n {children}\n </RenderStreamContext.Provider>\n )\n}\n\nexport function useRenderStreamContext() {\n return React.useContext(RenderStreamContext)\n}\n","import {queries} from '@testing-library/dom'\n\nexport type {Queries} from '@testing-library/dom'\n\ntype OriginalQueries = typeof queries\n\nexport type SyncQueries = {\n [K in keyof OriginalQueries as K extends `${'find'}${string}`\n ? never\n : K]: OriginalQueries[K]\n}\n\nexport const syncQueries = Object.fromEntries(\n Object.entries(queries).filter(\n ([key]) => key.startsWith('get') || key.startsWith('query'),\n ),\n) as any as SyncQueries\n\nexport type BoundFunction<T> = T extends (\n container: HTMLElement,\n ...args: infer P\n) => infer R\n ? (...args: P) => R\n : never\n\nexport type BoundSyncFunctions<Q> = Q extends typeof syncQueries\n ? {\n getByLabelText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.GetByText<T>>>\n ): ReturnType<queries.GetByText<T>>\n getAllByLabelText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByText<T>>>\n ): ReturnType<queries.AllByText<T>>\n queryByLabelText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.QueryByText<T>>>\n ): ReturnType<queries.QueryByText<T>>\n queryAllByLabelText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByText<T>>>\n ): ReturnType<queries.AllByText<T>>\n getByPlaceholderText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.GetByBoundAttribute<T>>>\n ): ReturnType<queries.GetByBoundAttribute<T>>\n getAllByPlaceholderText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByBoundAttribute<T>>>\n ): ReturnType<queries.AllByBoundAttribute<T>>\n queryByPlaceholderText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.QueryByBoundAttribute<T>>>\n ): ReturnType<queries.QueryByBoundAttribute<T>>\n queryAllByPlaceholderText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByBoundAttribute<T>>>\n ): ReturnType<queries.AllByBoundAttribute<T>>\n getByText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.GetByText<T>>>\n ): ReturnType<queries.GetByText<T>>\n getAllByText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByText<T>>>\n ): ReturnType<queries.AllByText<T>>\n queryByText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.QueryByText<T>>>\n ): ReturnType<queries.QueryByText<T>>\n queryAllByText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByText<T>>>\n ): ReturnType<queries.AllByText<T>>\n getByAltText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.GetByBoundAttribute<T>>>\n ): ReturnType<queries.GetByBoundAttribute<T>>\n getAllByAltText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByBoundAttribute<T>>>\n ): ReturnType<queries.AllByBoundAttribute<T>>\n queryByAltText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.QueryByBoundAttribute<T>>>\n ): ReturnType<queries.QueryByBoundAttribute<T>>\n queryAllByAltText<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByBoundAttribute<T>>>\n ): ReturnType<queries.AllByBoundAttribute<T>>\n getByTitle<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.GetByBoundAttribute<T>>>\n ): ReturnType<queries.GetByBoundAttribute<T>>\n getAllByTitle<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByBoundAttribute<T>>>\n ): ReturnType<queries.AllByBoundAttribute<T>>\n queryByTitle<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.QueryByBoundAttribute<T>>>\n ): ReturnType<queries.QueryByBoundAttribute<T>>\n queryAllByTitle<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByBoundAttribute<T>>>\n ): ReturnType<queries.AllByBoundAttribute<T>>\n getByDisplayValue<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.GetByBoundAttribute<T>>>\n ): ReturnType<queries.GetByBoundAttribute<T>>\n getAllByDisplayValue<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByBoundAttribute<T>>>\n ): ReturnType<queries.AllByBoundAttribute<T>>\n queryByDisplayValue<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.QueryByBoundAttribute<T>>>\n ): ReturnType<queries.QueryByBoundAttribute<T>>\n queryAllByDisplayValue<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByBoundAttribute<T>>>\n ): ReturnType<queries.AllByBoundAttribute<T>>\n getByRole<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.GetByRole<T>>>\n ): ReturnType<queries.GetByRole<T>>\n getAllByRole<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByRole<T>>>\n ): ReturnType<queries.AllByRole<T>>\n queryByRole<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.QueryByRole<T>>>\n ): ReturnType<queries.QueryByRole<T>>\n queryAllByRole<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByRole<T>>>\n ): ReturnType<queries.AllByRole<T>>\n getByTestId<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.GetByBoundAttribute<T>>>\n ): ReturnType<queries.GetByBoundAttribute<T>>\n getAllByTestId<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByBoundAttribute<T>>>\n ): ReturnType<queries.AllByBoundAttribute<T>>\n queryByTestId<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.QueryByBoundAttribute<T>>>\n ): ReturnType<queries.QueryByBoundAttribute<T>>\n queryAllByTestId<T extends HTMLElement = HTMLElement>(\n ...args: Parameters<BoundFunction<queries.AllByBoundAttribute<T>>>\n ): ReturnType<queries.AllByBoundAttribute<T>>\n } & {\n [P in keyof Q]: BoundFunction<Q[P]>\n }\n : {\n [P in keyof Q]: BoundFunction<Q[P]>\n }\n","import React from 'rehackt'\nimport {useRenderStreamContext} from './context.js'\n\nfunction resolveR18HookOwner(): React.ComponentType | undefined {\n /* eslint-disable @typescript-eslint/no-unsafe-member-access */\n return (React as any).__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\n ?.ReactCurrentOwner?.current?.elementType\n}\n\nfunction resolveR19HookOwner(): React.ComponentType | undefined {\n /* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call */\n return (\n React as any\n ).__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE?.A?.getOwner()\n .elementType\n}\n\nexport function useTrackRenders({name}: {name?: string} = {}) {\n const component = name ?? resolveR18HookOwner() ?? resolveR19HookOwner()\n\n if (!component) {\n throw new Error(\n 'useTrackRenders: Unable to determine component. Please ensure the hook is called inside a rendered component or provide a `name` option.',\n )\n }\n\n const ctx = useRenderStreamContext()\n\n if (!ctx) {\n throw new Error(\n 'useTrackRenders: A Render Stream must be created and rendered to track component renders',\n )\n }\n\n React.useLayoutEffect(() => {\n ctx.renderedComponents.unshift(component)\n })\n}\n","import {type RenderHookOptions} from '@testing-library/react/pure.js'\nimport React from 'rehackt'\nimport {createRenderStream} from './renderStream/createRenderStream.js'\nimport {type NextRenderOptions} from './renderStream/createRenderStream.js'\nimport {Render} from './renderStream/Render.js'\nimport {Assertable, assertableSymbol, markAssertable} from './assertable.js'\n\nexport interface SnapshotStream<Snapshot, Props> extends Assertable {\n /**\n * An array of all renders that have happened so far.\n * Errors thrown during component render will be captured here, too.\n */\n renders: Array<\n | Render<{value: Snapshot}, never>\n | {phase: 'snapshotError'; count: number; error: unknown}\n >\n /**\n * Peeks the next render from the current iterator position, without advancing the iterator.\n * If no render has happened yet, it will wait for the next render to happen.\n * @throws {WaitForRenderTimeoutError} if no render happens within the timeout\n */\n peekSnapshot(options?: NextRenderOptions): Promise<Snapshot>\n /**\n * Iterates to the next render and returns it.\n * If no render has happened yet, it will wait for the next render to happen.\n * @throws {WaitForRenderTimeoutError} if no render happens within the timeout\n */\n takeSnapshot: Assertable &\n ((options?: NextRenderOptions) => Promise<Snapshot>)\n /**\n * Returns the total number of renders.\n */\n totalSnapshotCount(): number\n /**\n * Returns the current render.\n * @throws {Error} if no render has happened yet\n */\n getCurrentSnapshot(): Snapshot\n /**\n * Waits for the next render to happen.\n * Does not advance the render iterator.\n */\n waitForNextSnapshot(options?: NextRenderOptions): Promise<Snapshot>\n rerender: (rerenderCallbackProps: VoidOptionalArg<Props>) => Promise<void>\n unmount: () => void\n}\n\n/**\n * if `Arg` can be `undefined`, replace it with `void` to make type represent an optional argument in a function argument position\n */\ntype VoidOptionalArg<Arg> = Arg extends any // distribute members of a potential `Props` union\n ? undefined extends Arg\n ? // eslint-disable-next-line @typescript-eslint/no-invalid-void-type\n void\n : Arg\n : Arg\n\nexport async function renderHookToSnapshotStream<ReturnValue, Props = void>(\n renderCallback: (props: Props) => ReturnValue,\n {initialProps, ...renderOptions}: RenderHookOptions<Props> = {},\n): Promise<SnapshotStream<ReturnValue, Props>> {\n const {render, ...stream} = createRenderStream<{value: ReturnValue}, never>()\n\n const HookComponent: React.FC<{arg: Props}> = props => {\n stream.replaceSnapshot({value: renderCallback(props.arg)})\n return null\n }\n\n const {rerender: baseRerender, unmount} = await render(\n <HookComponent arg={initialProps!} />,\n renderOptions,\n )\n\n function rerender(rerenderCallbackProps: VoidOptionalArg<Props>) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n return baseRerender(<HookComponent arg={rerenderCallbackProps as any} />)\n }\n\n return {\n [assertableSymbol]: stream,\n renders: stream.renders,\n totalSnapshotCount: stream.totalRenderCount,\n async peekSnapshot(options) {\n return (await stream.peekRender(options)).snapshot.value\n },\n takeSnapshot: markAssertable(async function takeSnapshot(options) {\n return (await stream.takeRender(options)).snapshot.value\n }, stream),\n getCurrentSnapshot() {\n return stream.getCurrentRender().snapshot.value\n },\n async waitForNextSnapshot(options) {\n return (await stream.waitForNextRender(options)).snapshot.value\n },\n rerender,\n unmount,\n }\n}\n"],"mappings":"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