new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

React Router · Getting started · all subjects

testing

7 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

createRoutesStub purpose and function

The createRoutesStub function creates React Router context to test components in isolation. Components using features like useLoaderData, Link, useActionData, or other hooks require this context. createRoutesStub takes an array of objects that resemble route modules with loaders, actions, and components.

createRoutesStub is for unit testing reusable components

createRoutesStub is designed for unit testing of reusable components that rely on contextual router information such as loaderData, actionData, and matches. These components typically obtain information via hooks (useLoaderData, useActionData, useMatches) or props passed from ancestor route components. Usage should be limited to testing these types of reusable components.

createRoutesStub is not suitable for testing Route components with Framework Mode types

createRoutesStub is not designed for direct testing of Route components using the Route.* types available in Framework Mode. The Route.* types are derived from the actual application's loader/action functions and route tree structure, which defines the matches type. When using createRoutesStub with stubbed values, the types won't align with Route.* types, causing type incompatibility errors. Route level components should be tested via integration or E2E tests instead.

createRoutesStub usage example with LoginForm

This example shows testing a LoginForm component with createRoutesStub. The LoginForm uses useActionData to display error messages. The stub is created with a route at '/login' that returns actionData with error objects. The test renders the stub with initialEntries set to '/login', simulates a click on the Login button, and waits for error messages to appear. ```tsx import { createRoutesStub } from "react-router"; import { render, screen, waitFor, } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { LoginForm } from "./LoginForm"; test("LoginForm renders error messages", async () => { const USER_MESSAGE = "Username is required"; const PASSWORD_MESSAGE = "Password is required"; const Stub = createRoutesStub([ { path: "/login", Component: LoginForm, action() { return { errors: { username: USER_MESSAGE, password: PASSWORD_MESSAGE, }, }; }, }, ]); render(<Stub initialEntries={["/login"]} />); userEvent.click(screen.getByText("Login")); await waitFor(() => screen.findByText(USER_MESSAGE)); await waitFor(() => screen.findByText(PASSWORD_MESSAGE)); }); ```

LoginForm component using useActionData

This example shows a LoginForm component that imports useActionData from react-router. It accesses actionData and extracts errors, rendering error messages in labels if they exist. The component submits via a Form with method="post". ```tsx import { useActionData } from "react-router"; export function LoginForm() { const actionData = useActionData(); const errors = actionData?.errors; return ( <Form method="post"> <label> <input type="text" name="username" /> {errors?.username && <div>{errors.username}</div>} </label> <label> <input type="password" name="password" /> {errors?.password && <div>{errors.password}</div>} </label> <button type="submit">Login</button> </Form> ); } ```

matches type alignment issue in createRoutesStub

When testing Route components with createRoutesStub, the matches type won't align between test code and app code. In a test, matches will only contain the test route with no root route or ancestor routes, while at runtime the matches will include the root route and other ancestors. There is no automatic way to align the typegen types with the runtime types in tests.

Use @ts-expect-error for Route component tests with createRoutesStub

If you must write a unit test for a Route component using createRoutesStub, you can add a @ts-expect-error comment to silence TypeScript errors caused by matches type misalignment between test and runtime code.

Give your agent this brain