Comprehensive reference for every public export of the TanStack Router/Start Testing Library, organized by package.
Framework-agnostic primitives that the @tanstack-router-testing/react-* packages build on. No React, Solid, or Vue code -- only utilities any framework adapter can compose.
type TestEnv = 'server' | 'client';The environments an isomorphic function can run under.
'server'-- server-only code paths (direct DB access, filesystem, etc.).'client'-- client-only code paths (fetch()to an API route, etc.).
interface CreateTestHistoryOptions {
readonly initialEntries?: readonly string[];
readonly initialIndex?: number;
}Options for createTestHistory. Forwards to @tanstack/history's createMemoryHistory with test-friendly defaults.
| Property | Type | Default | Description |
|---|---|---|---|
initialEntries |
readonly string[] |
['/'] |
Initial history entries. The last entry is active unless initialIndex is set. |
initialIndex |
number |
initialEntries.length - 1 |
Index into initialEntries to start at. Note: upstream uses a truthiness check, so passing 0 falls back to the last entry. Use a single-element array instead. |
type AnyFn = (...args: readonly unknown[]) => unknown;Loose function shape used as the key/handler type in the server-fn and middleware registries. Concrete typing lives in @tanstack-router-testing/react-start-testing.
interface ServerFnEntry {
readonly original: AnyFn;
mock: AnyFn | undefined;
}Registry entry for a single server function.
| Property | Type | Description |
|---|---|---|
original |
AnyFn |
The original handler registered via createServerFn().handler(original). Never mutated after registration. |
mock |
AnyFn | undefined |
When set, in-process dispatch calls this instead of original. |
interface MiddlewareEntry {
readonly originalClient: AnyFn | undefined;
readonly originalServer: AnyFn | undefined;
mockClient: AnyFn | undefined;
mockServer: AnyFn | undefined;
}Registry entry for a single middleware object.
| Property | Type | Description |
|---|---|---|
originalClient |
AnyFn | undefined |
Original .client() implementation. undefined means the middleware has no client phase. |
originalServer |
AnyFn | undefined |
Original .server() implementation. |
mockClient |
AnyFn | undefined |
Replaces the client phase during in-process dispatch. |
mockServer |
AnyFn | undefined |
Replaces the server phase during in-process dispatch. |
interface MiddlewareMockOptions {
readonly client?: AnyFn;
readonly server?: AnyFn;
}Options for setMiddlewareMock. Provide client, server, or both. Omitted keys leave the corresponding phase unchanged.
interface CallMiddlewareOptions {
readonly phase: 'server' | 'client';
readonly context?: unknown;
readonly request?: Request;
}Options for callMiddleware.
| Property | Type | Default | Description |
|---|---|---|---|
phase |
'server' | 'client' |
-- | Which middleware phase to invoke. |
context |
unknown |
{} |
Initial context passed to the middleware. |
request |
Request |
Synthetic test request | Request object available inside the middleware. |
interface CallMiddlewareResult {
readonly context: unknown;
}Result of calling a middleware in isolation. Contains the context after the middleware (and its next() call) has run.
function createTestHistory(options?: CreateTestHistoryOptions): RouterHistory;Build a RouterHistory backed by an in-memory stack, suitable for createRouter({ history }) in tests.
Thin wrapper around createMemoryHistory -- its only job is to provide a default initialEntries of ['/'] so tests that don't care about the starting path can omit it entirely.
Parameters:
| Parameter | Type | Description |
|---|---|---|
options |
CreateTestHistoryOptions |
Memory-history options. Optional. |
Returns: RouterHistory -- accepted directly by @tanstack/react-router's createRouter.
Example:
import { createRouter } from '@tanstack/react-router';
import { createTestHistory } from '@tanstack-router-testing/router-testing-core';
import { routeTree } from './routeTree.gen';
const router = createRouter({
routeTree,
history: createTestHistory({ initialEntries: ['/orders/42'] }),
});function getEnv(): TestEnv | undefined;Read the currently-simulated environment.
Returns: The current TestEnv, or undefined if none is set.
Example:
import { getEnv, runInEnv } from '@tanstack-router-testing/router-testing-core';
await runInEnv('server', () => {
expect(getEnv()).toBe('server');
});
expect(getEnv()).toBeUndefined();function setEnv(env: TestEnv | undefined): void;Imperatively set the current environment. Prefer runInEnv over this -- it guarantees restoration after the scope ends, even when the callback throws. Direct calls to setEnv are intended for test-lifecycle hooks (beforeEach/afterEach) where the caller manages restoration explicitly.
Parameters:
| Parameter | Type | Description |
|---|---|---|
env |
TestEnv | undefined |
The environment to simulate, or undefined to clear. |
function runInEnv<T>(env: TestEnv, fn: () => T | Promise<T>): Promise<T>;Run fn under a fixed environment, then restore the previous value. Restoration happens whether fn resolves, rejects, or throws synchronously. Nested calls work: each call saves and restores the exact prior value.
Parameters:
| Parameter | Type | Description |
|---|---|---|
env |
TestEnv |
The environment to simulate for the duration of fn. |
fn |
() => T | Promise<T> |
The callback to execute. May return a value or a Promise. |
Returns: Promise<T> -- resolves to the value returned by fn.
Example:
const data = await runInEnv('server', async () => {
return db.users.findMany();
});function registerServerFn(fn: AnyFn, original: AnyFn): ServerFnEntry;Register a server function so tests can find, mock, or invoke its original handler. Idempotent: registering the same fn twice returns the existing entry.
Parameters:
| Parameter | Type | Description |
|---|---|---|
fn |
AnyFn |
The server-fn callable (value returned by createServerFn().handler(original)). |
original |
AnyFn |
The original handler passed to .handler(). |
Returns: ServerFnEntry -- the registry entry for fn.
Example:
const listOrders = createServerFn({ method: 'GET' }).handler(listOrdersImpl);
registerServerFn(listOrders, listOrdersImpl);function getServerFnEntry(fn: AnyFn): ServerFnEntry | undefined;Fetch a server-fn's registry entry.
Parameters:
| Parameter | Type | Description |
|---|---|---|
fn |
AnyFn |
The server-fn callable. |
Returns: The entry, or undefined if fn was never registered.
function setServerFnMock(fn: AnyFn, mock: AnyFn | undefined): () => void;Install a mock handler for a server function. Returns a disposer that restores the prior mock (or clears it) when called.
Parameters:
| Parameter | Type | Description |
|---|---|---|
fn |
AnyFn |
The server-fn callable to mock. |
mock |
AnyFn | undefined |
The replacement handler. Pass undefined to clear the mock. |
Returns: () => void -- a no-arg function that restores the prior state.
Throws: If fn has not been registered. Mocking an unregistered fn would silently no-op.
Example:
const restore = setServerFnMock(listOrders, async () => [{ id: 1 }]);
// ... test body ...
restore();function clearAllServerFnMocks(): void;Clear every registered mock. Typically called from a Vitest afterEach hook to prevent test bleed. Does not unregister the fns themselves -- originals are preserved.
function registerMiddleware(
mw: object,
phases: {
readonly client?: AnyFn | undefined;
readonly server?: AnyFn | undefined;
},
): MiddlewareEntry;Register a middleware object so tests can mock its phase implementations. Idempotent.
Parameters:
| Parameter | Type | Description |
|---|---|---|
mw |
object |
The middleware object (value returned by createMiddleware). |
phases |
{ client?: AnyFn; server?: AnyFn } |
Original .client() and .server() implementations, or undefined for phases the middleware doesn't provide. |
Returns: MiddlewareEntry -- the registry entry for mw.
function getMiddlewareEntry(mw: object): MiddlewareEntry | undefined;Fetch a middleware's registry entry.
Parameters:
| Parameter | Type | Description |
|---|---|---|
mw |
object |
The middleware object. |
Returns: The entry, or undefined if mw was never registered.
function setMiddlewareMock(mw: object, options: MiddlewareMockOptions): () => void;Override one or both phases of a middleware. Returns a disposer that restores the prior phase values.
Parameters:
| Parameter | Type | Description |
|---|---|---|
mw |
object |
The middleware object to mock. |
options |
MiddlewareMockOptions |
Phase replacements. Provided keys are swapped; omitted keys are left untouched. |
Returns: () => void -- a no-arg function that restores the prior state.
Throws: If mw has not been registered.
Example:
const restore = setMiddlewareMock(authMw, {
server: async ({ next, context }) => next({ context: { ...context, user: { id: 'u1' } } }),
});
// ... test body ...
restore();function clearAllMiddlewareMocks(): void;Clear every registered middleware mock (both client and server phases). Originals are preserved.
function callMiddleware(mw: object, options: CallMiddlewareOptions): Promise<CallMiddlewareResult>;Call a registered middleware in isolation, without a full router. Invokes the specified phase (server or client) with a fake next() that captures context. Mocks installed via setMiddlewareMock take precedence over originals.
Parameters:
| Parameter | Type | Description |
|---|---|---|
mw |
object |
The middleware object returned by createMiddleware. Must be registered first. |
options |
CallMiddlewareOptions |
Phase, initial context, and optional request. |
Returns: Promise<CallMiddlewareResult> -- the resolved context after middleware execution.
Throws: If mw has not been registered, or if the specified phase has no implementation.
Example:
registerMiddleware(authMw, { server: authServerImpl });
const result = await callMiddleware(authMw, {
phase: 'server',
context: { user: null },
});
expect(result.context).toEqual({ user: null, checked: true });Test helpers for @tanstack/react-router. The public surface is intentionally small: createTestRouter and createRouterHarness, plus SSR support via the ./ssr subpath.
interface CreateTestRouterMemoryOptions {
readonly initialEntries?: readonly string[];
readonly initialIndex?: number;
}Memory history options used when a test does not supply its own history.
type CreateTestRouterOptions<
TRouteTree extends AnyRoute,
TTrailingSlash extends TrailingSlashOption = 'never',
TDefaultStructural extends boolean = false,
TDehydrated extends Record<string, unknown> = Record<string, unknown>,
> =
| (Omit<RouterConstructorOptions<...>, 'history'> & CreateTestRouterMemoryOptions & { readonly history?: never })
| (RouterConstructorOptions<...> & { readonly initialEntries?: never; readonly initialIndex?: never });A discriminated union: pass either a history object (production-shaped) or initialEntries/initialIndex (test convenience), but not both.
interface FileRouteHarnessOptions<TRoute extends AnyRoute = AnyRoute> {
readonly route: TRoute;
readonly params?: TRoute['types']['allParams'];
readonly search?: TRoute['types']['fullSearchSchema'];
readonly loaderData?: TRoute['types']['loaderData'];
readonly context?: Record<string, unknown>;
readonly queryClient?: object;
}Options for createRouterHarness when testing a single file-based route. All type parameters are inferred from the route, giving full autocomplete on params, search, and loaderData.
| Property | Type | Description |
|---|---|---|
route |
TRoute |
The file-based route to test. The harness walks to the root automatically. |
params |
TRoute['types']['allParams'] |
Path params, fully typed from the route's path definition. |
search |
TRoute['types']['fullSearchSchema'] |
Search params, fully typed from the route's validateSearch. |
loaderData |
TRoute['types']['loaderData'] |
Override loader data instead of running the real loader. |
context |
Record<string, unknown> |
Router context passed to beforeLoad and loader functions. |
queryClient |
object |
Optional QueryClient for @tanstack/react-query integration. |
type RouteMatchTarget = string | AnyRoute | { readonly id?: string; readonly routeId?: string; readonly fullPath?: string };Identifies a route match inside the current router state. Pass a plain string to match against any of id, routeId, or fullPath. Pass a route object to match by its id. Pass an object to match a specific field.
When an object is given, fields are checked in precedence order: id > routeId > fullPath. A bare string is compared against all three, returning the first match. A route object uses its internal id.
interface RouterHarness<TRouter extends AnyRouter> {
readonly router: TRouter;
readonly TestRouterProvider: ComponentType<{ children?: ReactNode }>;
readonly load: () => Promise<void>;
readonly navigate: (options: Parameters<TRouter['navigate']>[0]) => Promise<void>;
readonly preload: (options: Parameters<TRouter['preloadRoute']>[0]) => Promise<readonly AnyRouteMatch[] | undefined>;
readonly match: (href: string) => readonly AnyRouteMatch[];
readonly getMatch: (target: RouteMatchTarget) => AnyRouteMatch | undefined;
readonly getLoaderData: (target: RouteMatchTarget) => unknown;
readonly getRouteContext: (target: RouteMatchTarget) => unknown;
readonly getSearch: (target: RouteMatchTarget) => unknown;
readonly getParams: (target: RouteMatchTarget) => unknown;
readonly getError: (target: RouteMatchTarget) => unknown;
readonly getRedirect: (
options: Parameters<TRouter['navigate']>[0],
) => Promise<{ readonly pathname: string; readonly search: string; readonly hash: string } | undefined>;
readonly cleanup: () => void;
}Facade returned by createRouterHarness for testing routes, loaders, guards, redirects, and component rendering against a real TanStack Router instance. Full route-tree type inference is preserved through TRouter.
Members:
| Member | Type | Description |
|---|---|---|
router |
TRouter |
The underlying router instance. Useful for low-level assertions on router.state. |
TestRouterProvider |
ComponentType<{ children?: ReactNode }> |
A React component wrapping RouterProvider (and optionally QueryClientProvider). Pass to render(). When using the route option, pass children to test independent components that call route hooks like Route.useLoaderData(). |
load() |
() => Promise<void> |
Load the router, resolving all matched route loaders and beforeLoad guards. Must be called before state accessors. |
navigate(options) |
(...) => Promise<void> |
Navigate and wait for the transition to settle. Navigation errors reject the returned promise. |
preload(options) |
(...) => Promise<AnyRouteMatch[] | undefined> |
Preload a route's chunks and loaders without navigating. |
match(href) |
(href: string) => AnyRouteMatch[] |
Match a URL against the route tree without mutating router state. Does not trigger loaders or guards. |
getMatch(target) |
(...) => AnyRouteMatch | undefined |
Find a single route match in router.state.matches. |
getLoaderData(target) |
(...) => unknown |
Retrieve loader data for a matched route. |
getRouteContext(target) |
(...) => unknown |
Retrieve the route context (populated by beforeLoad and parent routes). |
getSearch(target) |
(...) => unknown |
Retrieve validated search params. |
getParams(target) |
(...) => unknown |
Retrieve parsed route params. |
getError(target) |
(...) => unknown |
Retrieve the error thrown during loading. |
getRedirect(options) |
(...) => Promise<{pathname, search, hash} | undefined> |
Navigate and detect whether a redirect occurred. Returns undefined if the router landed at the intended destination. |
cleanup() |
() => void |
Tear down the router, cancelling pending matches and destroying the history instance. Call in afterEach. |
interface RouteOverride {
readonly loader?: (...args: never[]) => unknown;
readonly beforeLoad?: (...args: never[]) => unknown;
readonly context?: (...args: never[]) => unknown;
readonly validateSearch?: (input: Record<string, unknown>) => unknown;
readonly loaderDeps?: (opts: { readonly search: Record<string, unknown> }) => unknown;
}A per-route option override applied by cloneRouteTree. Each field replaces the corresponding option on the cloned route; fields left out keep the route's real behavior, so real loaders and guards still run everywhere except the routes you name.
The override functions are intentionally loosely typed: an override rarely needs the real per-route context type, and matching it would require threading the route's generics through the override map. Write loader: async () => data or annotate the context parameter yourself when you need it.
| Property | Type | Description |
|---|---|---|
loader |
(...args: never[]) => unknown |
Replace the route's loader, skipping the real one. |
beforeLoad |
(...args: never[]) => unknown |
Replace the route's beforeLoad guard (e.g. to inject auth context). |
context |
(...args: never[]) => unknown |
Replace the route's context option (a function — return an object for a static bag: context: () => ({ ... })). |
validateSearch |
(input: Record<string, unknown>) => unknown |
Replace the route's validateSearch. |
loaderDeps |
(opts: { search: Record<string, unknown> }) => unknown |
Replace the route's loaderDeps. |
type RouteOverrides = Readonly<Record<string, RouteOverride>>;Per-route overrides keyed by route id. Ids match the router's own ids -- '__root__' for the root, and the file-route id for everything else (e.g. '/_authed', '/posts/$postId').
interface ClonedRouteTree {
readonly root: AnyRoute;
readonly byId: ReadonlyMap<string, AnyRoute>;
}A structurally-cloned route tree. Returned by cloneRouteTree.
| Property | Type | Description |
|---|---|---|
root |
AnyRoute |
The cloned root route, ready to hand to createRouter/createTestRouter. |
byId |
ReadonlyMap<string, AnyRoute> |
Cloned routes indexed by their original route id. |
Import from @tanstack-router-testing/react-router-testing/ssr.
type RouterSsrMode = 'string' | 'stream';interface CreateRouterSsrHarnessOptions<TRouter extends AnyRouter> {
readonly createRouter: () => TRouter;
readonly request?: Request | string | URL;
readonly mode?: RouterSsrMode;
readonly getRouterManifest?: () => Manifest | Promise<Manifest>;
}| Property | Type | Default | Description |
|---|---|---|---|
createRouter |
() => TRouter |
-- | Factory that creates the router instance for each SSR pass. |
request |
Request | string | URL |
'http://tanstack-router-testing.test/' |
The incoming request to render. |
mode |
RouterSsrMode |
'string' |
Render mode: 'string' for renderToString, 'stream' for renderToStream. |
getRouterManifest |
() => Manifest | Promise<Manifest> |
-- | Optional manifest provider for code-split route loading. |
interface HydrateRouterSsrOptions<TRouter extends AnyRouter> {
readonly createRouter?: () => TRouter;
readonly container?: Document | Element;
}Options for RouterSsrHarness.hydrate().
| Property | Type | Description |
|---|---|---|
createRouter |
() => TRouter |
Override the router factory for hydration. Defaults to the one passed to createRouterSsrHarness. |
container |
Document | Element |
DOM target for hydration. Defaults to document. |
interface RouterSsrHarness<TRouter extends AnyRouter> {
readonly request: Request;
readonly router: TRouter;
readonly response: Response;
readonly responseHeaders: Headers;
readonly html: string;
readonly mode: RouterSsrMode;
readonly hydrate: (options?: HydrateRouterSsrOptions<TRouter>) => Promise<{
readonly router: TRouter;
readonly errors: readonly unknown[];
readonly unmount: () => void;
}>;
}Returned by createRouterSsrHarness. Provides the SSR-rendered HTML and a hydrate() method to test client-side hydration.
| Member | Type | Description |
|---|---|---|
request |
Request |
The request used for SSR. |
router |
TRouter |
The server-side router instance. |
response |
Response |
The full HTTP response from the request handler. |
responseHeaders |
Headers |
Response headers set during SSR. |
html |
string |
The rendered HTML string. |
mode |
RouterSsrMode |
The render mode used. |
hydrate(options?) |
(...) => Promise<{router, errors, unmount}> |
Hydrate the SSR output into a DOM container. Returns the client router, any console errors captured during hydration, and an unmount() function. |
function createTestRouter<
TRouteTree extends AnyRoute,
TTrailingSlash extends TrailingSlashOption = 'never',
TDefaultStructural extends boolean = false,
TDehydrated extends Record<string, unknown> = Record<string, unknown>,
>(
options: CreateTestRouterOptions<TRouteTree, TTrailingSlash, TDefaultStructural, TDehydrated>,
): Router<TRouteTree, TTrailingSlash, TDefaultStructural, RouterHistory, TDehydrated>;Build a Router configured for in-memory, in-test use. Thin wrapper around createRouter -- defaults to memory history and defaultPendingMinMs: 0, then forwards every other router option verbatim.
The return type is fully generic: router.navigate({ to }), router.state, and every hook are constrained by routeTree in the same way they would be in production.
Parameters:
| Parameter | Type | Description |
|---|---|---|
options |
CreateTestRouterOptions<...> |
Router options. Pass either history or initialEntries/initialIndex, not both. |
Returns: Router<TRouteTree, TTrailingSlash, TDefaultStructural, RouterHistory, TDehydrated>
Throws: If both history and initialEntries/initialIndex are provided.
Example:
import { createTestRouter } from '@tanstack-router-testing/react-router-testing';
import { routeTree } from './routeTree.gen';
const router = createTestRouter({
routeTree,
initialEntries: ['/orders/42'],
context: { auth: stubAuth },
});Two overloads: one for testing a single file-based route, one for a full route tree.
Overload 1: File route (preferred for file-based routing)
function createRouterHarness<TRoute extends AnyRoute>(options: FileRouteHarnessOptions<TRoute>): RouterHarness<AnyRouter>;Overload 2: Full route tree
function createRouterHarness<
TRouteTree extends AnyRoute,
TTrailingSlash extends TrailingSlashOption = 'never',
TDefaultStructural extends boolean = false,
TDehydrated extends Record<string, unknown> = Record<string, unknown>,
>(
options: CreateTestRouterOptions<TRouteTree, TTrailingSlash, TDefaultStructural, TDehydrated> & {
readonly queryClient?: object;
readonly overrides?: RouteOverrides;
},
): RouterHarness<Router<TRouteTree, TTrailingSlash, TDefaultStructural, RouterHistory, TDehydrated>>;Create a RouterHarness containing a fully wired test router and a React provider component. Combines createTestRouter with a RouterProvider wrapper (and an optional QueryClientProvider), giving tests a single entry point for rendering, navigating, and asserting against route state.
When route is provided, the harness automatically walks to the root, neuters ancestor loaders for isolation (preserving beforeLoad for context cascading), and computes the initial URL from params/search.
When overrides is provided (route tree overload only), the route tree is structurally cloned via cloneRouteTree and the named routes' loader/beforeLoad/context/validateSearch/loaderDeps are replaced on the clone -- real loaders and guards still run for every other route. The source tree is never mutated, so it is safe even when several harnesses share one tree concurrently. See RouteOverrides.
Parameters (file route overload):
| Parameter | Type | Description |
|---|---|---|
route |
AnyRoute |
The file-based route to test. |
params |
Typed from route | Path params. Fully typed from the route's path definition. |
search |
Typed from route | Search params. Fully typed from validateSearch. |
loaderData |
Typed from route | Override loader data. Skips the real loader. |
context |
Record<string, unknown> |
Router context for beforeLoad/loader. |
queryClient |
object |
Optional QueryClient instance. |
Parameters (route tree overload):
All options from CreateTestRouterOptions plus:
| Parameter | Type | Description |
|---|---|---|
queryClient |
object |
Optional QueryClient instance. When provided, wraps RouterProvider with QueryClientProvider from @tanstack/react-query. |
overrides |
RouteOverrides |
Per-route option overrides keyed by route id. The tree is structurally cloned via cloneRouteTree before mounting. Optional. |
Returns: RouterHarness<...>
Example (file route):
import { createRouterHarness } from '@tanstack-router-testing/react-router-testing';
import { render } from '@testing-library/react';
import { Route } from './routes/posts.$postId';
const harness = createRouterHarness({
route: Route,
params: { postId: '7' }, // fully typed
});
await harness.load();
expect(harness.getLoaderData(Route)).toBeDefined();
const { getByText } = render(<harness.TestRouterProvider />);
expect(getByText('Post #7')).toBeDefined();
harness.cleanup();Example (full route tree):
import { createRouterHarness } from '@tanstack-router-testing/react-router-testing';
import { routeTree } from './routeTree.gen';
const harness = createRouterHarness({
routeTree,
initialEntries: ['/posts/7'],
context: { auth: stubAuth },
});
await harness.load();
expect(harness.getLoaderData('/posts/$postId')).toEqual({ id: 7 });
harness.cleanup();function cloneRouteTree(rootRoute: AnyRoute, overrides?: RouteOverrides): ClonedRouteTree;Deep-clone a TanStack Router tree, applying per-route option overrides keyed by route id. The source tree is never mutated -- every node is rebuilt via createRootRouteWithContext/createRoute, so the clone can be mounted in an isolated test router without leaking state back to the imported tree.
Cloning is leak-proof by construction: unlike mutate-and-restore isolation, it is safe even when several routers share the same source tree at once (e.g. test.concurrent).
Parameters:
| Parameter | Type | Description |
|---|---|---|
rootRoute |
AnyRoute |
Any route in the target tree, or its root. The enclosing root is located by walking getParentRoute; pass the root directly when you already have it. |
overrides |
RouteOverrides |
Optional per-route overrides keyed by route id (see RouteOverrides). Real loaders/guards run for every route you omit. |
Returns: ClonedRouteTree -- the cloned tree: a fresh root plus a map from the original route ids to their cloned counterparts.
Example:
const { root } = cloneRouteTree(routeTree, {
'/_authed': { beforeLoad: () => ({ user: stubUser }) },
'/posts/$postId': { loader: async () => ({ id: 7, title: 'Mock' }) },
});
const router = createTestRouter({ routeTree: root, initialEntries: ['/posts/7'] });function walkToRoot(route: AnyRoute): AnyRoute;Walk from a route to its root ancestor via getParentRoute. Used internally by createRouterHarness when the route option is provided.
Parameters:
| Parameter | Type | Description |
|---|---|---|
route |
AnyRoute |
Any route in the tree (leaf or intermediate). |
Returns: AnyRoute -- the root route at the top of the parent chain.
function computeFullPath(route: AnyRoute): string;Compute the full URL path for a route by walking up the parent chain.
Parameters:
| Parameter | Type | Description |
|---|---|---|
route |
AnyRoute |
The route whose full path to compute. |
Returns: string -- e.g. '/posts/$postId'.
function neuterAncestorLoaders(targetRoute: AnyRoute): () => void;Replace all ancestor loaders with undefined for test isolation. Ancestor beforeLoad functions are preserved so context cascading (auth, permissions, etc.) continues to work.
Parameters:
| Parameter | Type | Description |
|---|---|---|
targetRoute |
AnyRoute |
The route under test. Its own loader is kept intact. |
Returns: () => void -- a cleanup function that restores original loaders.
function createRouterSsrHarness<TRouter extends AnyRouter>(options: CreateRouterSsrHarnessOptions<TRouter>): Promise<RouterSsrHarness<TRouter>>;Create a RouterSsrHarness for testing server-side rendering of a TanStack Router application. Executes the request handler, captures the rendered HTML, and provides a hydrate() method for testing client-side hydration.
Parameters:
| Parameter | Type | Description |
|---|---|---|
options |
CreateRouterSsrHarnessOptions<TRouter> |
SSR harness configuration. |
Returns: Promise<RouterSsrHarness<TRouter>> -- async because the request handler runs during creation.
Example:
import { createRouterSsrHarness } from '@tanstack-router-testing/react-router-testing/ssr';
const harness = await createRouterSsrHarness({
createRouter: () => createTestRouter({ routeTree }),
request: 'http://localhost:3000/posts/7',
mode: 'string',
});
expect(harness.html).toContain('Post #7');
expect(harness.response.status).toBe(200);
// Test hydration
const { router, errors, unmount } = await harness.hydrate();
expect(errors).toHaveLength(0);
unmount();Test helpers for @tanstack/react-start. Server functions are called directly in tests, exactly as production code calls them. This package exposes mock controls, environment simulation, and test runtimes.
type AnyServerFn = (...args: never[]) => unknown;Catch-all type representing any TanStack Start server function. Used as a generic constraint in mockServerFn and ServerFnMock.
type ServerFnMock<TFn extends AnyServerFn> = (...args: Parameters<TFn>) => ReturnType<TFn>;The mock implementation signature for a server function of type TFn. Full generic inference is preserved so autocomplete works identically to the real call.
type ServerFnMockPair<TFn extends AnyServerFn = AnyServerFn> = readonly [TFn, ServerFnMock<TFn>];A [serverFn, mockImplementation] pair installed before the route renders. Used by renderRoute's serverFnMocks option.
interface RenderRouteOptions {
readonly routeTree: AnyRoute;
readonly initialEntries?: readonly string[];
readonly initialIndex?: number;
readonly context?: Record<string, unknown>;
readonly overrides?: RouteOverrides;
readonly serverFnMocks?: readonly ServerFnMockPair[];
readonly queryClient?: object;
}Options for renderRoute.
| Property | Type | Default | Description |
|---|---|---|---|
routeTree |
AnyRoute |
-- | The route tree to mount. |
initialEntries |
readonly string[] |
['/'] |
Initial navigation entries; the last one is active. |
initialIndex |
number |
-- | Index into initialEntries to start at. |
context |
Record<string, unknown> |
-- | Router context passed to beforeLoad/loader. |
overrides |
RouteOverrides |
-- | Per-route option overrides keyed by route id. The tree is structurally cloned, so the source tree is never mutated. See RouteOverrides (from @tanstack-router-testing/react-router-testing). |
serverFnMocks |
readonly ServerFnMockPair[] |
-- | [serverFn, mock] pairs installed via mockServerFn before render and disposed on unmount. |
queryClient |
object |
-- | Optional QueryClient for @tanstack/react-query integration. |
interface RenderRouteResult extends RenderResult {
readonly harness: RouterHarness<AnyRouter>;
}Result of renderRoute: the full React Testing Library RenderResult plus the underlying RouterHarness (from @tanstack-router-testing/react-router-testing).
| Property | Type | Description |
|---|---|---|
harness |
RouterHarness<AnyRouter> |
The router harness backing the render, for state assertions and navigation. |
All members from RTL's RenderResult are also available.
interface MockMiddlewareOptions {
readonly client?: AnyFn;
readonly server?: AnyFn;
}Phase override options for mockMiddleware. Provide client, server, or both. Omitted keys leave the corresponding phase untouched.
interface StartTestRuntimeOptions {
readonly startInstance?: {
readonly getOptions: () => AnyStartInstanceOptions | Promise<AnyStartInstanceOptions>;
};
readonly startOptions?: AnyStartInstanceOptions;
readonly request?: Request | string | URL;
readonly router?: AnyRouter;
readonly context?: unknown;
readonly env?: TestEnv;
readonly handlerType?: StartHandlerType;
}Configuration for createStartTestRuntime.
| Property | Type | Default | Description |
|---|---|---|---|
startInstance |
{ getOptions: () => ... } |
-- | A Start instance whose getOptions() is called once during creation. Ignored when startOptions is also provided. |
startOptions |
AnyStartInstanceOptions |
{} |
Explicit Start options. Takes precedence over startInstance. |
request |
Request | string | URL |
'http://tanstack-router-testing.test/' |
Incoming request available to server functions via getRequest(). |
router |
AnyRouter |
-- | Router instance available via getRouter() inside server functions. |
context |
unknown |
{} |
Initial middleware context merged into each call's context. |
env |
TestEnv |
'server' |
Default simulated environment. |
handlerType |
StartHandlerType |
'serverFn' |
Default handler type passed to the storage context. |
interface StartTestRunOptions {
readonly request?: Request | string | URL;
readonly context?: unknown;
readonly env?: TestEnv;
readonly handlerType?: StartHandlerType;
}Per-invocation overrides for StartTestRuntime.run and StartTestRuntime.call. Every property mirrors a field from StartTestRuntimeOptions and takes precedence for that single invocation only.
interface StartTestRuntime {
readonly request: Request;
readonly startOptions: AnyStartInstanceOptions;
readonly run: <T>(fn: () => T | Promise<T>, options?: StartTestRunOptions) => Promise<T>;
readonly call: <TArgs extends readonly unknown[], TReturn>(
fn: (...args: TArgs) => TReturn | Promise<TReturn>,
args: TArgs,
options?: StartTestRunOptions,
) => Promise<Awaited<TReturn>>;
readonly cleanup: () => void;
}A test runtime that simulates the TanStack Start server environment.
| Member | Type | Description |
|---|---|---|
request |
Request |
The Request object available to server functions. |
startOptions |
AnyStartInstanceOptions |
The resolved Start options used by the runtime. |
run(fn, options?) |
<T>(...) => Promise<T> |
Run an arbitrary function inside the Start storage context with optional per-invocation overrides. |
call(fn, args, options?) |
<TArgs, TReturn>(...) => Promise<Awaited<TReturn>> |
Invoke a function with explicit arguments inside the Start storage context. |
cleanup() |
() => void |
Remove all server-function and middleware mocks. Equivalent to clearStartMocks(). |
interface RscTestRuntimeOptions extends StartTestRuntimeOptions {
readonly streaming?: boolean;
}Configuration for createRscTestRuntime. Extends StartTestRuntimeOptions.
| Property | Type | Default | Description |
|---|---|---|---|
streaming |
boolean |
false |
When true, renders via renderToReadableStream and collects chunks. When false, uses renderToString. |
interface RscRenderResult {
readonly html: string;
readonly stream: ReadableStream<Uint8Array> | null;
readonly chunks: readonly string[];
}The result of rendering a React Server Component.
| Property | Type | Description |
|---|---|---|
html |
string |
The complete HTML string produced by the render. |
stream |
ReadableStream<Uint8Array> | null |
Cloned readable stream. Only present when streaming: true; otherwise null. |
chunks |
readonly string[] |
Decoded text chunks collected from the stream. Empty when streaming is false. |
interface RscTestRuntime extends StartTestRuntime {
readonly renderServerComponent: <TProps extends Record<string, unknown>>(component: ComponentType<TProps>, props: TProps) => Promise<RscRenderResult>;
}Extended test runtime that adds React Server Component rendering on top of StartTestRuntime.
| Member | Type | Description |
|---|---|---|
renderServerComponent(component, props) |
<TProps>(...) => Promise<RscRenderResult> |
Render a React component to HTML using react-dom/server. |
All members from StartTestRuntime are also available.
function mockServerFn<TFn extends AnyServerFn>(fn: TFn, impl: ServerFnMock<TFn>): () => void;Install a mock implementation for a TanStack Start server function. The mock is authored against the public callable shape, so a server function normally called as listOrders({ data }) is mocked with that same signature. Internal context fields are normalized automatically.
Parameters:
| Parameter | Type | Description |
|---|---|---|
fn |
TFn |
The server function created by createServerFn().handler(...). |
impl |
ServerFnMock<TFn> |
Replacement handler. Receives the same callable-shape arguments as the original. |
Returns: () => void -- a disposer that restores the original implementation.
Example:
import { createServerFn } from '@tanstack/react-start';
import { mockServerFn } from '@tanstack-router-testing/react-start-testing';
const listOrders = createServerFn()
.validator((input: { userId: string }) => input)
.handler(async ({ data }) => db.orders.findMany(data.userId));
const dispose = mockServerFn(listOrders, async ({ data }) => [{ id: '1', userId: data.userId, total: 42 }]);
// ... run your test ...
dispose();function mockMiddleware(mw: object, options: MockMiddlewareOptions): () => void;Override one or both phases of a registered middleware.
Parameters:
| Parameter | Type | Description |
|---|---|---|
mw |
object |
The middleware object returned by createMiddleware().server(...).client(...). |
options |
MockMiddlewareOptions |
Which phases to replace. |
Returns: () => void -- a disposer that restores the original handlers.
Throws: If mw is not registered.
Example:
import { createMiddleware } from '@tanstack/react-start';
import { mockMiddleware } from '@tanstack-router-testing/react-start-testing';
const authMiddleware = createMiddleware()
.server(async ({ next }) => next({ context: { user: await getUser() } }))
.client(async ({ next }) => next());
const dispose = mockMiddleware(authMiddleware, {
server: async ({ next }) => next({ context: { user: { id: 'test-user' } } }),
});
// ... run your test ...
dispose();function renderRoute(options: RenderRouteOptions): Promise<RenderRouteResult>;Mount a route tree at a location with server-function mocks and per-route overrides -- the router, mocks, render, and load happen in one call. Wires createRouterHarness (with overrides), installs each serverFnMocks pair via mockServerFn, loads the router, and renders it through React Testing Library. It is the declarative counterpart to hand-composing createTestRouter + mockServerFn + render.
The returned unmount disposes the installed mocks and tears down the harness in addition to unmounting the DOM; it is idempotent, so it composes safely with the standard clearStartMocks / cleanupAllHarnesses teardown.
Parameters:
| Parameter | Type | Description |
|---|---|---|
options |
RenderRouteOptions |
Describes the tree, location, context, overrides, and server-function mocks. |
Returns: Promise<RenderRouteResult> -- RTL queries plus the harness. Requires @testing-library/react to be installed.
Example:
import { routeTree } from './routeTree.gen';
import { listOrders } from './server/orders';
const screen = await renderRoute({
routeTree,
initialEntries: ['/orders/42'],
context: { auth: stubAuth },
overrides: { '/_authed': { beforeLoad: () => ({ user: stubUser }) } },
serverFnMocks: [[listOrders, async () => [{ id: 1, total: 42 }]]],
});
await screen.findByText('Order 42');
expect(screen.harness.getLoaderData('/orders/$id')).toBeDefined();function clearStartMocks(): void;Clear every server-function and middleware mock installed by mockServerFn or mockMiddleware. This is the same function wired to StartTestRuntime.cleanup, so you only need to call it explicitly when installing mocks outside of a runtime.
Example:
import { afterEach } from 'vitest';
import { clearStartMocks } from '@tanstack-router-testing/react-start-testing';
afterEach(() => {
clearStartMocks();
});function runInStartEnv<T>(env: TestEnv, fn: () => T | Promise<T>): Promise<T>;Execute fn with the simulated TanStack Start environment forced to env, then restore the prior value. Delegates to runInEnv from router-testing-core.
Parameters:
| Parameter | Type | Description |
|---|---|---|
env |
TestEnv |
'server' or 'client'. |
fn |
() => T | Promise<T> |
Synchronous or asynchronous function to run. |
Returns: Promise<T>
Example:
import { runInStartEnv } from '@tanstack-router-testing/react-start-testing';
const result = await runInStartEnv('server', () => {
return fetchDataOnServer();
});Re-exported from @tanstack-router-testing/router-testing-core. See callMiddleware above.
function createStartTestRuntime(options?: StartTestRuntimeOptions): Promise<StartTestRuntime>;Create a StartTestRuntime for executing server functions in a simulated TanStack Start environment. Resolves Start options from either startOptions or startInstance.getOptions(), sets up the Start storage context, and executes global request middlewares before each invocation.
Parameters:
| Parameter | Type | Description |
|---|---|---|
options |
StartTestRuntimeOptions |
Runtime configuration. Optional; defaults to an empty options object. |
Returns: Promise<StartTestRuntime> -- async because Start options may need to be resolved.
Example:
import { createServerFn } from '@tanstack/react-start';
import { createStartTestRuntime, mockServerFn } from '@tanstack-router-testing/react-start-testing';
const runtime = await createStartTestRuntime({
request: 'http://localhost:3000/api/orders',
env: 'server',
});
const listOrders = createServerFn()
.validator((input: { userId: string }) => input)
.handler(async ({ data }) => [{ id: '1', userId: data.userId }]);
mockServerFn(listOrders, async ({ data }) => [{ id: 'mock-1', userId: data.userId }]);
const orders = await runtime.call(listOrders, [{ data: { userId: 'u1' } }]);
// orders === [{ id: 'mock-1', userId: 'u1' }]
runtime.cleanup();function createRscTestRuntime(options?: RscTestRuntimeOptions): Promise<RscTestRuntime>;Create an RscTestRuntime for rendering React Server Components in a simulated TanStack Start environment. Delegates to createStartTestRuntime for the base runtime, then adds renderServerComponent which uses react-dom/server.
Parameters:
| Parameter | Type | Description |
|---|---|---|
options |
RscTestRuntimeOptions |
Runtime configuration including the optional streaming flag. |
Returns: Promise<RscTestRuntime>
Example:
import { createRscTestRuntime } from '@tanstack-router-testing/react-start-testing';
const runtime = await createRscTestRuntime({ streaming: true });
function Greeting({ name }: { name: string }) {
return <h1>Hello, {name}!</h1>;
}
const { html, chunks } = await runtime.renderServerComponent(Greeting, {
name: 'TanStack',
});
// html === '<h1>Hello, TanStack!</h1>'
runtime.cleanup();Import from @tanstack-router-testing/react-start-testing/vite.
interface TanstackStartTestingOptions {
readonly routesDirectory?: string;
readonly generatedRouteTree?: string;
readonly aliasReactStart?: boolean;
readonly rsc?: boolean;
}| Property | Type | Default | Description |
|---|---|---|---|
routesDirectory |
string |
'src/routes' |
Directory holding file-based routes, relative to the Vite root. |
generatedRouteTree |
string |
'src/routeTree.gen.ts' |
Output path for the generated route tree. |
aliasReactStart |
boolean |
true |
Whether to alias @tanstack/react-start to the test runtime shim. |
rsc |
boolean |
false |
Install a small test runtime module for TanStack Start RSC imports that need virtual:tanstack-rsc-runtime under Vitest. |
function tanstackStartTesting(options?: TanstackStartTestingOptions): readonly Plugin[];Vite/Vitest plugins for TanStack Start tests. Keeps route-tree generation on the real TanStack Router plugin path while swapping the Start runtime to the in-process testing shim. Also injects generatedRouteTree as a Vitest setupFiles entry so all file-based routes have their parent/path/id wired up before any test runs.
Parameters:
| Parameter | Type | Description |
|---|---|---|
options |
TanstackStartTestingOptions |
Plugin configuration. Optional. |
Returns: readonly Plugin[] -- an array of Vite plugins.
Example:
// vitest.config.ts
import { defineConfig } from 'vitest/config';
import { tanstackStartTesting } from '@tanstack-router-testing/react-start-testing/vite';
export default defineConfig({
plugins: [
tanstackStartTesting({
routesDirectory: 'src/routes',
generatedRouteTree: 'src/routeTree.gen.ts',
}),
],
test: {
environment: 'jsdom',
},
});