zzz / frontend /test-utils.tsx
ar08's picture
Upload 1040 files
246d201 verified
// See https://redux.js.org/usage/writing-tests#setting-up-a-reusable-test-render-function for more information
import React, { PropsWithChildren } from "react";
import { Provider } from "react-redux";
import { configureStore } from "@reduxjs/toolkit";
import { RenderOptions, render } from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { I18nextProvider, initReactI18next } from "react-i18next";
import i18n from "i18next";
import { vi } from "vitest";
import { AppStore, RootState, rootReducer } from "./src/store";
import { AuthProvider } from "#/context/auth-context";
import { ConversationProvider } from "#/context/conversation-context";
import { SettingsProvider } from "#/context/settings-context";
// Mock useParams before importing components
vi.mock("react-router", async () => {
const actual =
await vi.importActual<typeof import("react-router")>("react-router");
return {
...actual,
useParams: () => ({ conversationId: "test-conversation-id" }),
};
});
// Initialize i18n for tests
i18n.use(initReactI18next).init({
lng: "en",
fallbackLng: "en",
ns: ["translation"],
defaultNS: "translation",
resources: {
en: {
translation: {},
},
},
interpolation: {
escapeValue: false,
},
});
const setupStore = (preloadedState?: Partial<RootState>): AppStore =>
configureStore({
reducer: rootReducer,
preloadedState,
});
// This type interface extends the default options for render from RTL, as well
// as allows the user to specify other things such as initialState, store.
interface ExtendedRenderOptions extends Omit<RenderOptions, "queries"> {
preloadedState?: Partial<RootState>;
store?: AppStore;
}
// Export our own customized renderWithProviders function that creates a new Redux store and renders a <Provider>
// Note that this creates a separate Redux store instance for every test, rather than reusing the same store instance and resetting its state
export function renderWithProviders(
ui: React.ReactElement,
{
preloadedState = {},
// Automatically create a store instance if no store was passed in
store = setupStore(preloadedState),
...renderOptions
}: ExtendedRenderOptions = {},
) {
function Wrapper({ children }: PropsWithChildren) {
return (
<Provider store={store}>
<AuthProvider>
<QueryClientProvider
client={
new QueryClient({
defaultOptions: { queries: { retry: false } },
})
}
>
<SettingsProvider>
<ConversationProvider>
<I18nextProvider i18n={i18n}>{children}</I18nextProvider>
</ConversationProvider>
</SettingsProvider>
</QueryClientProvider>
</AuthProvider>
</Provider>
);
}
return { store, ...render(ui, { wrapper: Wrapper, ...renderOptions }) };
}