84 lines
2.6 KiB
TypeScript
84 lines
2.6 KiB
TypeScript
|
|
/**
|
||
|
|
* Shared test utilities — wraps components in the providers they need.
|
||
|
|
*
|
||
|
|
* Usage:
|
||
|
|
* import { renderWithProviders } from '../test-utils'
|
||
|
|
* renderWithProviders(<LoginPage />, { initialPath: '/login' })
|
||
|
|
*/
|
||
|
|
|
||
|
|
import type { ReactNode } from 'react'
|
||
|
|
import { render } from '@testing-library/react'
|
||
|
|
import { MantineProvider } from '@mantine/core'
|
||
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||
|
|
import { MemoryRouter, Routes, Route } from 'react-router-dom'
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// Provider wrapper
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
interface RenderOptions {
|
||
|
|
/** Initial URL path (default: '/'). */
|
||
|
|
initialPath?: string
|
||
|
|
/**
|
||
|
|
* Extra routes to register alongside the component under test.
|
||
|
|
* Useful for asserting navigation (e.g. render a /home sentinel and check
|
||
|
|
* that the component navigates there after login).
|
||
|
|
*/
|
||
|
|
routes?: Array<{ path: string; element: ReactNode }>
|
||
|
|
/**
|
||
|
|
* React-router initial entries (overrides initialPath when provided).
|
||
|
|
* Use when you need to seed location.state (e.g. from-path for redirect-after-login).
|
||
|
|
*/
|
||
|
|
initialEntries?: Array<string | { pathname: string; state?: unknown }>
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Render `ui` inside MantineProvider + a fresh QueryClientProvider + MemoryRouter.
|
||
|
|
* SessionProvider is NOT included — tests that need session state should mock
|
||
|
|
* `GET /api/session` via vi.fn() on the apiClient or use MSW.
|
||
|
|
*/
|
||
|
|
export function renderWithProviders(ui: ReactNode, options: RenderOptions = {}) {
|
||
|
|
const { initialPath = '/', routes = [], initialEntries } = options
|
||
|
|
|
||
|
|
const queryClient = new QueryClient({
|
||
|
|
defaultOptions: {
|
||
|
|
queries: { retry: false },
|
||
|
|
mutations: { retry: false },
|
||
|
|
},
|
||
|
|
})
|
||
|
|
|
||
|
|
const entries = initialEntries ?? [initialPath]
|
||
|
|
|
||
|
|
function Wrapper() {
|
||
|
|
return (
|
||
|
|
<MantineProvider>
|
||
|
|
<QueryClientProvider client={queryClient}>
|
||
|
|
<MemoryRouter initialEntries={entries}>
|
||
|
|
<Routes>
|
||
|
|
<Route path={initialPath} element={ui} />
|
||
|
|
{routes.map(({ path, element }) => (
|
||
|
|
<Route key={path} path={path} element={element} />
|
||
|
|
))}
|
||
|
|
</Routes>
|
||
|
|
</MemoryRouter>
|
||
|
|
</QueryClientProvider>
|
||
|
|
</MantineProvider>
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
return render(<Wrapper />)
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Create a minimal SessionProvider-less wrapper that just supplies the
|
||
|
|
* query and router context. Returns the queryClient so tests can prime it.
|
||
|
|
*/
|
||
|
|
export function createTestQueryClient() {
|
||
|
|
return new QueryClient({
|
||
|
|
defaultOptions: {
|
||
|
|
queries: { retry: false },
|
||
|
|
mutations: { retry: false },
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}
|