Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Ensure renderHook options extend options for render #1308

Merged
merged 1 commit into from Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
63 changes: 56 additions & 7 deletions types/index.d.ts
Expand Up @@ -179,19 +179,58 @@ export interface RenderHookResult<Result, Props> {
unmount: () => void
}

export interface RenderHookOptions<
export interface BaseRenderHookOptions<
Props,
Q extends Queries = typeof queries,
Container extends Element | DocumentFragment = HTMLElement,
BaseElement extends Element | DocumentFragment = Container,
> extends RenderOptions<Q, Container, BaseElement> {
Q extends Queries,
Container extends RendererableContainer | HydrateableContainer,
BaseElement extends Element | DocumentFragment,
> extends BaseRenderOptions<Q, Container, BaseElement> {
/**
* The argument passed to the renderHook callback. Can be useful if you plan
* to use the rerender utility to change the values passed to your hook.
*/
initialProps?: Props
}

export interface ClientRenderHookOptions<
Props,
Q extends Queries,
Container extends Element | DocumentFragment,
BaseElement extends Element | DocumentFragment = Container,
> extends BaseRenderHookOptions<Props, Q, Container, BaseElement> {
/**
* If `hydrate` is set to `true`, then it will render with `ReactDOM.hydrate`. This may be useful if you are using server-side
* rendering and use ReactDOM.hydrate to mount your components.
*
* @see https://testing-library.com/docs/react-testing-library/api/#hydrate)
*/
hydrate?: false | undefined
}

export interface HydrateHookOptions<
Props,
Q extends Queries,
Container extends Element | DocumentFragment,
BaseElement extends Element | DocumentFragment = Container,
> extends BaseRenderHookOptions<Props, Q, Container, BaseElement> {
/**
* If `hydrate` is set to `true`, then it will render with `ReactDOM.hydrate`. This may be useful if you are using server-side
* rendering and use ReactDOM.hydrate to mount your components.
*
* @see https://testing-library.com/docs/react-testing-library/api/#hydrate)
*/
hydrate: true
}

export type RenderHookOptions<
Props,
Q extends Queries = typeof queries,
Container extends Element | DocumentFragment = HTMLElement,
BaseElement extends Element | DocumentFragment = Container,
> =
| ClientRenderHookOptions<Props, Q, Container, BaseElement>
| HydrateHookOptions<Props, Q, Container, BaseElement>

/**
* Allows you to render a hook within a test React component without having to
* create that component yourself.
Expand All @@ -200,11 +239,21 @@ export function renderHook<
Result,
Props,
Q extends Queries = typeof queries,
Container extends Element | DocumentFragment = HTMLElement,
Container extends RendererableContainer = HTMLElement,
BaseElement extends Element | DocumentFragment = Container,
>(
render: (initialProps: Props) => Result,
options?: ClientRenderHookOptions<Props, Q, Container, BaseElement>,
): RenderHookResult<Result, Props>
export function renderHook<
Result,
Props,
Q extends Queries = typeof queries,
Container extends HydrateableContainer = HTMLElement,
BaseElement extends Element | DocumentFragment = Container,
>(
render: (initialProps: Props) => Result,
options?: RenderHookOptions<Props, Q, Container, BaseElement>,
options?: HydrateHookOptions<Props, Q, Container, BaseElement>,
): RenderHookResult<Result, Props>

/**
Expand Down
19 changes: 19 additions & 0 deletions types/test.tsx
Expand Up @@ -45,6 +45,8 @@ export function testRenderOptions() {
const options = {container}
const {container: returnedContainer} = render(<button />, options)
expectType<HTMLDivElement, typeof returnedContainer>(returnedContainer)

render(<div />, {wrapper: () => null})
}

export function testSVGRenderOptions() {
Expand Down Expand Up @@ -191,6 +193,8 @@ export function testRenderHook() {
rerender()

unmount()

renderHook(() => null, {wrapper: () => null})
}

export function testRenderHookProps() {
Expand All @@ -215,6 +219,21 @@ export function testContainer() {
// @ts-expect-error Only allowed for createRoot
render('a', {container: document.createDocumentFragment(), hydrate: true})
render('a', {container: document, hydrate: true})

renderHook(() => null, {container: document.createElement('div')})
renderHook(() => null, {container: document.createDocumentFragment()})
// @ts-expect-error Only allowed in React 19
renderHook(() => null, {container: document})
renderHook(() => null, {
container: document.createElement('div'),
hydrate: true,
})
// @ts-expect-error Only allowed for createRoot
renderHook(() => null, {
container: document.createDocumentFragment(),
hydrate: true,
})
renderHook(() => null, {container: document, hydrate: true})
}

/*
Expand Down