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(render): Don't reject wrapper types based on statics #973

Merged
merged 3 commits into from Oct 3, 2021
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
2 changes: 1 addition & 1 deletion types/index.d.ts
Expand Up @@ -70,7 +70,7 @@ export interface RenderOptions<
*
* @see https://testing-library.com/docs/react-testing-library/api/#wrapper
*/
wrapper?: React.ComponentType<{children: React.ReactElement}>
wrapper?: React.JSXElementConstructor<{children: React.ReactElement}>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering whether we should define children as React.ReactNode which seems to be the "official" type for children props. https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L829

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrapper never receives anything other than ReactElement. If we would widen children to ReactNode, the implementation of wrapper would have to account for types that it never actually receives.

This is problematic if you want to apply methods to children in the implementation of wrapper that require a single ReactElement such as React.cloneElement.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes perfect sense - ReactNode is indeed very wide. Thanks for the explanation.

}

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
Expand Down
21 changes: 20 additions & 1 deletion types/test.tsx
Expand Up @@ -115,13 +115,32 @@ export function wrappedRenderB(
ui: React.ReactElement,
options?: pure.RenderOptions,
) {
const Wrapper: React.FunctionComponent = ({children}) => {
const Wrapper: React.FunctionComponent<{children?: React.ReactNode}> = ({
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While FunctionComponent adds implicit children, its propTypes do not so we didn't catch that issue. Here we make sure all statics assume the same props. Also makes sure this doesn't break once we get rid of implicit children in React.FunctionComponent.

children,
}) => {
return <div>{children}</div>
}

return pure.render(ui, {wrapper: Wrapper, ...options})
}

export function wrappedRenderC(
ui: React.ReactElement,
options?: pure.RenderOptions,
) {
interface AppWrapperProps {
userProviderProps?: {user: string}
}
const AppWrapperProps: React.FunctionComponent<AppWrapperProps> = ({
children,
userProviderProps = {user: 'TypeScript'},
}) => {
return <div data-testid={userProviderProps.user}>{children}</div>
}

return pure.render(ui, {wrapper: AppWrapperProps, ...options})
}

/*
eslint
testing-library/prefer-explicit-assert: "off",
Expand Down