Files
zerobyte/app/test/test-utils.tsx
Nico 611640b32b fix: split display path and query base path (#714)
* fix: split display path and query base path

#709

* test(frontend): shared render utils

* fix(file-tree): add missing path segments

* chore: bump Bun version

* fix: select kind for synthetic folders
2026-03-29 12:30:35 +02:00

95 lines
2.6 KiB
TypeScript

import { MutationCache, QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
render as testingLibraryRender,
renderHook as testingLibraryRenderHook,
type RenderHookOptions,
type RenderOptions,
} from "@testing-library/react";
import testingLibraryUserEvent from "@testing-library/user-event";
import { Suspense, type ReactElement, type ReactNode } from "react";
import { logger } from "~/client/lib/logger";
type TestProviderOptions = {
queryClient?: QueryClient;
withSuspense?: boolean;
suspenseFallback?: ReactNode;
};
type TestRenderOptions = Omit<RenderOptions, "wrapper"> & TestProviderOptions;
type TestRenderHookOptions<Props> = Omit<RenderHookOptions<Props>, "wrapper"> & TestProviderOptions;
export const createTestQueryClient = () => {
let queryClient: QueryClient;
queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
gcTime: Infinity,
},
mutations: {
gcTime: Infinity,
},
},
mutationCache: new MutationCache({
onSuccess: () => {
void queryClient.invalidateQueries();
},
onError: (error) => {
logger.error("Mutation error:", error);
void queryClient.invalidateQueries();
},
}),
});
return queryClient;
};
const createWrapper = (options: TestProviderOptions = {}) => {
const { queryClient = createTestQueryClient(), withSuspense = false, suspenseFallback = null } = options;
const Wrapper = ({ children }: { children: ReactNode }) => {
return (
<QueryClientProvider client={queryClient}>
{withSuspense ? <Suspense fallback={suspenseFallback}>{children}</Suspense> : children}
</QueryClientProvider>
);
};
return { queryClient, Wrapper };
};
const customRender = (ui: ReactElement, options: TestRenderOptions = {}) => {
const { queryClient, withSuspense, suspenseFallback, ...renderOptions } = options;
const wrapper = createWrapper({ queryClient, withSuspense, suspenseFallback });
return {
queryClient: wrapper.queryClient,
...testingLibraryRender(ui, {
wrapper: wrapper.Wrapper,
...renderOptions,
}),
};
};
const customRenderHook = <Result, Props>(
callback: (initialProps: Props) => Result,
options: TestRenderHookOptions<Props> = {},
) => {
const { queryClient, withSuspense, suspenseFallback, ...renderOptions } = options;
const wrapper = createWrapper({ queryClient, withSuspense, suspenseFallback });
return {
queryClient: wrapper.queryClient,
...testingLibraryRenderHook(callback, {
wrapper: wrapper.Wrapper,
...renderOptions,
}),
};
};
export * from "@testing-library/react";
export const userEvent = testingLibraryUserEvent.setup();
export { customRender as render, customRenderHook as renderHook };