From fa7d1a0953ce793b76e2ab09cd3d63aad442ddaa Mon Sep 17 00:00:00 2001 From: Adam Thompson Date: Wed, 10 Sep 2025 13:24:51 -0400 Subject: [PATCH 1/5] Updates internal structure of RTL overrides --- packages/testing-lib/rollup.config.mjs | 13 +-- .../src/ReactTestingLibrary/act.ts | 21 +++++ .../src/ReactTestingLibrary/index.ts | 11 +++ .../src/ReactTestingLibrary/renderHook.ts | 50 +++++++++++ .../renderHookServer/index.ts | 22 +++++ .../renderHookServer.types.ts | 10 +++ .../renderHookServer/renderHookServer17.tsx | 32 +++++++ .../renderHookServer/renderHookServer18.tsx | 89 +++++++++++++++++++ .../utils/getReactVersion.ts | 5 ++ .../ReactTestingLibrary/utils/isReact17.ts | 5 ++ .../src/ReactTestingLibrary/utils/types.ts | 11 +++ packages/testing-lib/src/index.ts | 6 +- packages/testing-lib/src/waitForState.ts | 4 +- .../waitForTransition/waitForTransition.ts | 4 +- 14 files changed, 272 insertions(+), 11 deletions(-) create mode 100644 packages/testing-lib/src/ReactTestingLibrary/act.ts create mode 100644 packages/testing-lib/src/ReactTestingLibrary/index.ts create mode 100644 packages/testing-lib/src/ReactTestingLibrary/renderHook.ts create mode 100644 packages/testing-lib/src/ReactTestingLibrary/renderHookServer/index.ts create mode 100644 packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer.types.ts create mode 100644 packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer17.tsx create mode 100644 packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer18.tsx create mode 100644 packages/testing-lib/src/ReactTestingLibrary/utils/getReactVersion.ts create mode 100644 packages/testing-lib/src/ReactTestingLibrary/utils/isReact17.ts create mode 100644 packages/testing-lib/src/ReactTestingLibrary/utils/types.ts diff --git a/packages/testing-lib/rollup.config.mjs b/packages/testing-lib/rollup.config.mjs index faec1f5d06..58aecafbb7 100644 --- a/packages/testing-lib/rollup.config.mjs +++ b/packages/testing-lib/rollup.config.mjs @@ -3,10 +3,11 @@ import { esmConfig, umdConfig } from '@lg-tools/build/config/rollup.config.mjs'; export default [ esmConfig, umdConfig, - ...['./src/renderHookServer.tsx', './src/renderHookServerV17.tsx'].map( - input => ({ - ...umdConfig, - input, - }), - ), + ...[ + './src/ReactTestingLibrary/renderHookServer/renderHookServer18.tsx', + './src/ReactTestingLibrary/renderHookServer/renderHookServer17.tsx', + ].map(input => ({ + ...umdConfig, + input, + })), ]; diff --git a/packages/testing-lib/src/ReactTestingLibrary/act.ts b/packages/testing-lib/src/ReactTestingLibrary/act.ts new file mode 100644 index 0000000000..6c450e4f46 --- /dev/null +++ b/packages/testing-lib/src/ReactTestingLibrary/act.ts @@ -0,0 +1,21 @@ +import { isReact17 } from './utils/isReact17'; + +/** + * Type of `act` from `@testing-library/react` if it exists, + * otherwise defaults to compatible type. + */ +export type ActType = (cb: () => void | Promise) => void | Promise; + +/** + * Re-exports `act` from `"@testing-library/react"` in React18+ + * or from `"@testing-library/react-hooks"` in React17 environments + */ +export const act: ActType = (() => { + if (isReact17()) { + const RHTL = require('@testing-library/react-hooks'); + return RHTL.act; + } else { + const RTL = require('@testing-library/react'); + return RTL.act; + } +})(); diff --git a/packages/testing-lib/src/ReactTestingLibrary/index.ts b/packages/testing-lib/src/ReactTestingLibrary/index.ts new file mode 100644 index 0000000000..4f9acd6023 --- /dev/null +++ b/packages/testing-lib/src/ReactTestingLibrary/index.ts @@ -0,0 +1,11 @@ +export { act, type ActType } from './act'; +export { + renderHook, + type RenderHookOptions, + type RenderHookResult, +} from './renderHook'; +export { + renderHookServer, + type RenderHookServerOptions, + type RenderHookServerResult, +} from './renderHookServer'; diff --git a/packages/testing-lib/src/ReactTestingLibrary/renderHook.ts b/packages/testing-lib/src/ReactTestingLibrary/renderHook.ts new file mode 100644 index 0000000000..452bd1c42a --- /dev/null +++ b/packages/testing-lib/src/ReactTestingLibrary/renderHook.ts @@ -0,0 +1,50 @@ +import * as RTL from '@testing-library/react'; + +import { Exists } from './utils/types'; + +/** + * Returns the type of `RenderHookOptions` from `@testing-library/react` if it exists, + * otherwise defaults to a compatible type. + */ +export type RenderHookOptions = Exists< + typeof RTL, + 'RenderHookOptions', + RTL.RenderOptions & { + initialProps?: TProps; + } +>; + +/** + * Returns the type of `RenderHookResult` from `@testing-library/react` if it exists, + * otherwise defaults to a compatible type. + */ +export type RenderHookResult = Exists< + typeof RTL, + 'RenderHookResult', + { + current: TResult; + rerender: (props?: TProps) => void; + unmount: () => void; + result: { + all: Array; + current: TResult; + error: Error; + }; + } +>; + +/** + * Re-exports `renderHook` from `"@testing-library/react"` if it exists, + * or from `"@testing-library/react-hooks"` + * + * (used when running in a React 17 test environment) + */ +export const renderHook: ( + render: (initialProps: TProps) => TResult, + options?: RenderHookOptions, +) => RenderHookResult = + (RTL as any).renderHook ?? + (() => { + const RHTL = require('@testing-library/react-hooks'); + return RHTL.renderHook; + })(); diff --git a/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/index.ts b/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/index.ts new file mode 100644 index 0000000000..125572bc9c --- /dev/null +++ b/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/index.ts @@ -0,0 +1,22 @@ +import path from 'path'; + +import { isReact17 } from '../utils/isReact17'; + +import type { + RenderHookServerOptions, + RenderHookServerResult, +} from './renderHookServer.types'; + +export type { RenderHookServerOptions, RenderHookServerResult }; + +/** + * Correct `renderHookServer` method based on React version. + */ +export const renderHookServer: any>( + useHook: Hook, + options?: RenderHookServerOptions, +) => RenderHookServerResult = (() => { + const filename = isReact17() ? 'renderHookServer17' : 'renderHookServer18'; + const RHS = require(path.resolve(__dirname, filename)); + return RHS.renderHookServer; +})(); diff --git a/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer.types.ts b/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer.types.ts new file mode 100644 index 0000000000..f459842b12 --- /dev/null +++ b/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer.types.ts @@ -0,0 +1,10 @@ +import { ReactNode } from 'react'; + +export interface RenderHookServerOptions { + wrapper?: ({ children }: { children: ReactNode }) => JSX.Element; +} + +export interface RenderHookServerResult any> { + result: { current: ReturnType }; + hydrate: () => void; +} diff --git a/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer17.tsx b/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer17.tsx new file mode 100644 index 0000000000..6e916ea85e --- /dev/null +++ b/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer17.tsx @@ -0,0 +1,32 @@ +import { renderHook } from '@testing-library/react-hooks/server'; + +import type { + RenderHookServerOptions, + RenderHookServerResult, +} from './renderHookServer.types'; + +/** + * Allows you to mock the server side rendering of a hook in pre React 18 versions. + * For versions >=18, use `@testing-lib/renderHookServer`. + * + * e.g. + * ```typescript + * it('should return true when server-side rendered and false after hydration', () => { + * const { result, hydrate } = renderHookServer(useMyHook); + * expect(result.current).toBe(true); + * hydrate(); + * expect(result.current).toBe(false); + * }); + * ``` +} + */ +export function renderHookServer any>( + useHook: Hook, + { wrapper }: RenderHookServerOptions = {}, +): RenderHookServerResult { + // @ts-ignore Type 'undefined' is not assignable to type 'Window'. + jest.spyOn(global, 'window', 'get').mockImplementation(() => undefined); + const response = renderHook(useHook, { wrapper }); + jest.spyOn(global, 'window', 'get').mockRestore(); + return response; +} diff --git a/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer18.tsx b/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer18.tsx new file mode 100644 index 0000000000..a238d08a91 --- /dev/null +++ b/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer18.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +// @ts-ignore Cannot find module 'react-dom/client' or its corresponding type declarations +import { hydrateRoot } from 'react-dom/client'; +import { renderToString } from 'react-dom/server'; +import { act } from 'react-dom/test-utils'; + +import type { + RenderHookServerOptions, + RenderHookServerResult, +} from './renderHookServer.types'; + +/** + * Allows you to mock the server side rendering of a hook. + * + * @testing-library/react-hooks/server exposed a `renderHook` method + * that allowed for one to render hooks as if SSR, and control + * hydration. This is no longer supported in versions >=18. + * + * This code was extracted from @testing-library/react-hooks/server and + * updated to be compatible with React version >= 18 using `hydrateRoot`. + * + * More context found here: + * https://github.com/testing-library/react-testing-library/issues/1120 + * + * e.g. + * ```typescript + * it('should return true when server-side rendered and false after hydration', () => { + * const { result, hydrate } = renderHookServer(useMyHook); + * expect(result.current).toBe(true); + * hydrate(); + * expect(result.current).toBe(false); + * }); + * ``` +} + */ +export function renderHookServer18 any>( + useHook: Hook, + { wrapper: Wrapper }: RenderHookServerOptions = {}, +): RenderHookServerResult { + // Store hook return value + const results: Array> = []; + const result = { + get current() { + return results.slice(-1)[0]; + }, + }; + + // Test component to render hook in + const Component = ({ useHook }: { useHook: Hook }) => { + results.push(useHook()); + return null; + }; + + // Add wrapper if necessary + const component = Wrapper ? ( + + + + ) : ( + + ); + + // Running tests in an environment that simulates a browser (like Jest with jsdom), + // the window object will still be available even when server rendered. To ensure + // that window is not available during SSR we need to explicitly mock or remove the + // window object. + // @ts-ignore Type 'undefined' is not assignable to type 'Window'. + jest.spyOn(global, 'window', 'get').mockImplementation(() => undefined); + + // Render hook on server + const serverOutput = renderToString(component); + + // Restore window + jest.spyOn(global, 'window', 'get').mockRestore(); + + // Render hook on client + const hydrate = () => { + const root = document.createElement('div'); + root.innerHTML = serverOutput; + act(() => { + hydrateRoot(root, component); + }); + }; + + return { + result, + hydrate, + }; +} diff --git a/packages/testing-lib/src/ReactTestingLibrary/utils/getReactVersion.ts b/packages/testing-lib/src/ReactTestingLibrary/utils/getReactVersion.ts new file mode 100644 index 0000000000..bfcba305cc --- /dev/null +++ b/packages/testing-lib/src/ReactTestingLibrary/utils/getReactVersion.ts @@ -0,0 +1,5 @@ +import React from 'react'; + +export const getReactVersion = () => { + return parseInt(React.version.split('.')[0], 10); +}; diff --git a/packages/testing-lib/src/ReactTestingLibrary/utils/isReact17.ts b/packages/testing-lib/src/ReactTestingLibrary/utils/isReact17.ts new file mode 100644 index 0000000000..fca6655a09 --- /dev/null +++ b/packages/testing-lib/src/ReactTestingLibrary/utils/isReact17.ts @@ -0,0 +1,5 @@ +import { getReactVersion } from './getReactVersion'; + +export const isReact17 = () => { + return getReactVersion() === 17; +}; diff --git a/packages/testing-lib/src/ReactTestingLibrary/utils/types.ts b/packages/testing-lib/src/ReactTestingLibrary/utils/types.ts new file mode 100644 index 0000000000..5dce3990a7 --- /dev/null +++ b/packages/testing-lib/src/ReactTestingLibrary/utils/types.ts @@ -0,0 +1,11 @@ +/** + * Utility type that returns `X.Y` if it exists, otherwise defaults to fallback type `Z`, or `any` + * + * @internal + * Redeclared from /lib to avoid circular dependency issues + */ +export type Exists< + X, + Y extends keyof X | string, + Z = unknown, +> = Y extends keyof X ? X[Y] : Z; diff --git a/packages/testing-lib/src/index.ts b/packages/testing-lib/src/index.ts index 0ed6acc6eb..7071ffcd5e 100644 --- a/packages/testing-lib/src/index.ts +++ b/packages/testing-lib/src/index.ts @@ -3,10 +3,14 @@ import * as jest from './jest'; import * as JestDOM from './jest-dom'; export { act, + type ActType, renderHook, + type RenderHookOptions, type RenderHookResult, renderHookServer, -} from './RTLOverrides'; + type RenderHookServerOptions, + type RenderHookServerResult, +} from './ReactTestingLibrary'; export { useTraceUpdate } from './useTraceUpdate'; export { waitForState } from './waitForState'; export { waitForTransition } from './waitForTransition'; diff --git a/packages/testing-lib/src/waitForState.ts b/packages/testing-lib/src/waitForState.ts index b7f0b67c8c..e185c326b1 100644 --- a/packages/testing-lib/src/waitForState.ts +++ b/packages/testing-lib/src/waitForState.ts @@ -1,4 +1,4 @@ -import { act } from './RTLOverrides'; +import { act } from './ReactTestingLibrary'; /** * Wrapper around `act`. @@ -10,7 +10,7 @@ export const waitForState = async ( callback: () => T, ): Promise => { let val: T; - await act(() => { + await act(async () => { val = callback(); }); diff --git a/packages/testing-lib/src/waitForTransition/waitForTransition.ts b/packages/testing-lib/src/waitForTransition/waitForTransition.ts index fe765d2e09..a791d1aad2 100644 --- a/packages/testing-lib/src/waitForTransition/waitForTransition.ts +++ b/packages/testing-lib/src/waitForTransition/waitForTransition.ts @@ -1,6 +1,6 @@ import { fireEvent, waitFor } from '@testing-library/react'; -import { act } from '../RTLOverrides'; +import { act } from '../ReactTestingLibrary'; /** * Fires the `transitionEnd` event on the provided element, @@ -15,7 +15,7 @@ export async function waitForTransition( ) { if (element) { await waitFor(() => { - act(() => { + act(async () => { fireEvent.transitionEnd(element, options); }); }); From e8b8e7d97eca9a624fe7d5fecc379da582ab3f48 Mon Sep 17 00:00:00 2001 From: Adam Thompson Date: Wed, 10 Sep 2025 13:27:00 -0400 Subject: [PATCH 2/5] Update rtl-overrides.md --- .changeset/rtl-overrides.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.changeset/rtl-overrides.md b/.changeset/rtl-overrides.md index e2976c68ef..8b3e2ad3f6 100644 --- a/.changeset/rtl-overrides.md +++ b/.changeset/rtl-overrides.md @@ -2,5 +2,6 @@ '@leafygreen-ui/testing-lib': minor --- -Exports types `RenderHookOptions` & `RenderHookResult`. -Updates type signature of `renderHook` +- Exports types `RenderHookOptions` & `RenderHookResult`. +- Updates type signature of `renderHook` +- Updates internal structure of RTL override files \ No newline at end of file From f9795160131986819c90ed583f78a07e506043e3 Mon Sep 17 00:00:00 2001 From: Adam Thompson Date: Wed, 10 Sep 2025 13:54:52 -0400 Subject: [PATCH 3/5] fix git mv --- packages/hooks/src/hooks.spec.tsx | 2 +- packages/testing-lib/src/RTLOverrides.ts | 79 ---------------- .../renderHookServer/renderHookServer18.tsx | 17 ++-- packages/testing-lib/src/renderHookServer.tsx | 94 ------------------- .../testing-lib/src/renderHookServerV17.tsx | 32 ------- 5 files changed, 12 insertions(+), 212 deletions(-) delete mode 100644 packages/testing-lib/src/RTLOverrides.ts delete mode 100644 packages/testing-lib/src/renderHookServer.tsx delete mode 100644 packages/testing-lib/src/renderHookServerV17.tsx diff --git a/packages/hooks/src/hooks.spec.tsx b/packages/hooks/src/hooks.spec.tsx index 2df3bcc993..0cc5b1f44a 100644 --- a/packages/hooks/src/hooks.spec.tsx +++ b/packages/hooks/src/hooks.spec.tsx @@ -370,7 +370,7 @@ describe('packages/hooks', () => { }); }); - describe('useSsrCheck', () => { + describe.only('useSsrCheck', () => { test('should return true when server-side rendered and false after hydration', () => { const { result, hydrate } = renderHookServer(useSsrCheck); expect(result.current).toBe(true); diff --git a/packages/testing-lib/src/RTLOverrides.ts b/packages/testing-lib/src/RTLOverrides.ts deleted file mode 100644 index 53c23db0d5..0000000000 --- a/packages/testing-lib/src/RTLOverrides.ts +++ /dev/null @@ -1,79 +0,0 @@ -import * as React from 'react'; -import * as RTL from '@testing-library/react'; -import path from 'path'; - -import { - RenderHookServerOptions, - RenderHookServerResult, -} from './renderHookServer'; - -/** - * Utility type that returns `X.Y` if it exists, otherwise defaults to fallback type `Z`, or `any` - */ -export type Exists< - X, - Y extends keyof X | string, - Z = unknown, -> = Y extends keyof X ? X[Y] : Z; - -/** - * Re-exports `renderHook` from `"@testing-library/react"` if it exists, - * or from `"@testing-library/react-hooks"` - * - * (used when running in a React 17 test environment) - */ -export const renderHook: ( - render: (initialProps: TProps) => TResult, - options?: RenderHookOptions, -) => RenderHookResult = - (RTL as any).renderHook ?? - (() => { - const RHTL = require('@testing-library/react-hooks'); - return RHTL.renderHook; - })(); - -export type RenderHookOptions = Exists< - typeof RTL, - 'RenderHookOptions', - RTL.RenderOptions & { - initialProps?: TProps; - } ->; - -export type RenderHookResult = Exists< - typeof RTL, - 'RenderHookResult', - { - current: TResult; - rerender: (props?: TProps) => void; - unmount: () => void; - result: { - current: TResult; - }; - } ->; -/** - * Re-exports `act` from `"@testing-library/react"` if it exists, - * or from `"@testing-library/react-hooks"` - * - * (used when running in a React 17 test environment) - */ -export const act: Exists = - RTL.act ?? - (() => { - const RHTL = require('@testing-library/react-hooks'); - return RHTL.act; - })(); - -/** - * Correct `renderHookServer` method based on React version. - */ -export const renderHookServer: any>( - useHook: Hook, - options?: RenderHookServerOptions, -) => RenderHookServerResult = (() => { - const isReact18 = parseInt(React.version.split('.')[0], 10) >= 18; - const filename = isReact18 ? 'renderHookServer' : 'renderHookServerV17'; - const RHS = require(path.resolve(__dirname, filename)); - return RHS.renderHookServer; -})(); diff --git a/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer18.tsx b/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer18.tsx index a238d08a91..41a99bbebe 100644 --- a/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer18.tsx +++ b/packages/testing-lib/src/ReactTestingLibrary/renderHookServer/renderHookServer18.tsx @@ -1,13 +1,18 @@ +import type { ReactNode } from 'react'; import React from 'react'; -// @ts-ignore Cannot find module 'react-dom/client' or its corresponding type declarations +//@ts-ignore Cannot find module 'react-dom/client' or its corresponding type declarations import { hydrateRoot } from 'react-dom/client'; import { renderToString } from 'react-dom/server'; import { act } from 'react-dom/test-utils'; -import type { - RenderHookServerOptions, - RenderHookServerResult, -} from './renderHookServer.types'; +export interface RenderHookServerOptions { + wrapper?: ({ children }: { children: ReactNode }) => JSX.Element; +} + +export interface RenderHookServerResult any> { + result: { current: ReturnType }; + hydrate: () => void; +} /** * Allows you to mock the server side rendering of a hook. @@ -33,7 +38,7 @@ import type { * ``` } */ -export function renderHookServer18 any>( +export function renderHookServer any>( useHook: Hook, { wrapper: Wrapper }: RenderHookServerOptions = {}, ): RenderHookServerResult { diff --git a/packages/testing-lib/src/renderHookServer.tsx b/packages/testing-lib/src/renderHookServer.tsx deleted file mode 100644 index 41a99bbebe..0000000000 --- a/packages/testing-lib/src/renderHookServer.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import type { ReactNode } from 'react'; -import React from 'react'; -//@ts-ignore Cannot find module 'react-dom/client' or its corresponding type declarations -import { hydrateRoot } from 'react-dom/client'; -import { renderToString } from 'react-dom/server'; -import { act } from 'react-dom/test-utils'; - -export interface RenderHookServerOptions { - wrapper?: ({ children }: { children: ReactNode }) => JSX.Element; -} - -export interface RenderHookServerResult any> { - result: { current: ReturnType }; - hydrate: () => void; -} - -/** - * Allows you to mock the server side rendering of a hook. - * - * @testing-library/react-hooks/server exposed a `renderHook` method - * that allowed for one to render hooks as if SSR, and control - * hydration. This is no longer supported in versions >=18. - * - * This code was extracted from @testing-library/react-hooks/server and - * updated to be compatible with React version >= 18 using `hydrateRoot`. - * - * More context found here: - * https://github.com/testing-library/react-testing-library/issues/1120 - * - * e.g. - * ```typescript - * it('should return true when server-side rendered and false after hydration', () => { - * const { result, hydrate } = renderHookServer(useMyHook); - * expect(result.current).toBe(true); - * hydrate(); - * expect(result.current).toBe(false); - * }); - * ``` -} - */ -export function renderHookServer any>( - useHook: Hook, - { wrapper: Wrapper }: RenderHookServerOptions = {}, -): RenderHookServerResult { - // Store hook return value - const results: Array> = []; - const result = { - get current() { - return results.slice(-1)[0]; - }, - }; - - // Test component to render hook in - const Component = ({ useHook }: { useHook: Hook }) => { - results.push(useHook()); - return null; - }; - - // Add wrapper if necessary - const component = Wrapper ? ( - - - - ) : ( - - ); - - // Running tests in an environment that simulates a browser (like Jest with jsdom), - // the window object will still be available even when server rendered. To ensure - // that window is not available during SSR we need to explicitly mock or remove the - // window object. - // @ts-ignore Type 'undefined' is not assignable to type 'Window'. - jest.spyOn(global, 'window', 'get').mockImplementation(() => undefined); - - // Render hook on server - const serverOutput = renderToString(component); - - // Restore window - jest.spyOn(global, 'window', 'get').mockRestore(); - - // Render hook on client - const hydrate = () => { - const root = document.createElement('div'); - root.innerHTML = serverOutput; - act(() => { - hydrateRoot(root, component); - }); - }; - - return { - result, - hydrate, - }; -} diff --git a/packages/testing-lib/src/renderHookServerV17.tsx b/packages/testing-lib/src/renderHookServerV17.tsx deleted file mode 100644 index 937ba57c2f..0000000000 --- a/packages/testing-lib/src/renderHookServerV17.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { renderHook } from '@testing-library/react-hooks/server'; - -import { - RenderHookServerOptions, - RenderHookServerResult, -} from './renderHookServer'; - -/** - * Allows you to mock the server side rendering of a hook in pre React 18 versions. - * For versions >=18, use `@testing-lib/renderHookServer`. - * - * e.g. - * ```typescript - * it('should return true when server-side rendered and false after hydration', () => { - * const { result, hydrate } = renderHookServer(useMyHook); - * expect(result.current).toBe(true); - * hydrate(); - * expect(result.current).toBe(false); - * }); - * ``` -} - */ -export function renderHookServer any>( - useHook: Hook, - { wrapper }: RenderHookServerOptions = {}, -): RenderHookServerResult { - // @ts-ignore Type 'undefined' is not assignable to type 'Window'. - jest.spyOn(global, 'window', 'get').mockImplementation(() => undefined); - const response = renderHook(useHook, { wrapper }); - jest.spyOn(global, 'window', 'get').mockRestore(); - return response; -} From 1815335d5af69bdf9b120123bb553c3798483083 Mon Sep 17 00:00:00 2001 From: Adam Thompson Date: Wed, 10 Sep 2025 14:54:41 -0400 Subject: [PATCH 4/5] Update hooks.spec.tsx --- packages/hooks/src/hooks.spec.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/hooks/src/hooks.spec.tsx b/packages/hooks/src/hooks.spec.tsx index 0cc5b1f44a..2df3bcc993 100644 --- a/packages/hooks/src/hooks.spec.tsx +++ b/packages/hooks/src/hooks.spec.tsx @@ -370,7 +370,7 @@ describe('packages/hooks', () => { }); }); - describe.only('useSsrCheck', () => { + describe('useSsrCheck', () => { test('should return true when server-side rendered and false after hydration', () => { const { result, hydrate } = renderHookServer(useSsrCheck); expect(result.current).toBe(true); From fd0bd7319098c84627b0db839324077996669ec4 Mon Sep 17 00:00:00 2001 From: Adam Thompson Date: Wed, 10 Sep 2025 14:55:53 -0400 Subject: [PATCH 5/5] fix act --- packages/testing-lib/src/waitForState.ts | 2 +- packages/testing-lib/src/waitForTransition/waitForTransition.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/testing-lib/src/waitForState.ts b/packages/testing-lib/src/waitForState.ts index e185c326b1..a84ee151fc 100644 --- a/packages/testing-lib/src/waitForState.ts +++ b/packages/testing-lib/src/waitForState.ts @@ -10,7 +10,7 @@ export const waitForState = async ( callback: () => T, ): Promise => { let val: T; - await act(async () => { + await act(() => { val = callback(); }); diff --git a/packages/testing-lib/src/waitForTransition/waitForTransition.ts b/packages/testing-lib/src/waitForTransition/waitForTransition.ts index a791d1aad2..8a2f6f3369 100644 --- a/packages/testing-lib/src/waitForTransition/waitForTransition.ts +++ b/packages/testing-lib/src/waitForTransition/waitForTransition.ts @@ -15,7 +15,7 @@ export async function waitForTransition( ) { if (element) { await waitFor(() => { - act(async () => { + act(() => { fireEvent.transitionEnd(element, options); }); });