import React from "react";
import { PropsWithChildren, StrictMode } from "react";
import { render, renderHook, RenderHookOptions } from "@testing-library/react";
const DefaultWrapper = ({ children }: PropsWithChildren) => <>{children}>;
/**
* Composes two React wrapper components.
* OuterWrapper wraps InnerWrapper which wraps children.
*/
function composeWrappers(
OuterWrapper: React.ComponentType<{ children: React.ReactNode }>,
InnerWrapper?: React.ComponentType<{ children: React.ReactNode }>
): React.ComponentType<{ children: React.ReactNode }> {
if (!InnerWrapper) {
return OuterWrapper;
}
return function ComposedWrapper({ children }: { children: React.ReactNode }) {
return (
{children}
);
};
}
const StrictModeWrapper = ({ children }: PropsWithChildren) => (
{children}
);
export const wrappers: {
mode: "normal" | "strict";
Wrapper: React.FC<{ children: React.ReactNode }>;
render: (ui: React.ReactElement) => ReturnType;
renderHook: (
render: (props: TProps) => TResult,
options?: RenderHookOptions
) => ReturnType>;
}[] = [
{
mode: "normal" as const,
Wrapper: DefaultWrapper,
render: (ui: React.ReactElement) => {
return render(ui, { wrapper: DefaultWrapper });
},
renderHook: (
callback: (props: TProps) => TResult,
options?: RenderHookOptions
) => {
return renderHook(callback, options);
},
},
{
mode: "strict" as const,
Wrapper: StrictModeWrapper,
render: (ui: React.ReactElement) => {
return render(ui, { wrapper: StrictModeWrapper });
},
renderHook: (
callback: (props: TProps) => TResult,
options?: RenderHookOptions
) => {
const composedWrapper = composeWrappers(
StrictModeWrapper,
options?.wrapper
);
return renderHook(callback, { ...options, wrapper: composedWrapper });
},
},
];