当组件使用 `useLoaderData`、`<Link>` 等时,需要在 React Router 应用的上下文中渲染它们。`createRoutesStub` 函数创建该上下文以隔离测试组件。
考虑一个依赖于 `useActionData` 的登录表单组件
import { useActionData } from "react-router";
export function LoginForm() {
const errors = useActionData();
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>
);
}
我们可以使用createRoutesStub
来测试这个组件。它接收一个对象数组,这些对象类似于包含加载器、操作和组件的路由模块。
import { createRoutesStub } from "react-router";
import * as Test from "@testing-library/react";
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 the app stub at "/login"
Test.render(<Stub initialEntries={["/login"]} />);
// simulate interactions
Test.user.click(screen.getByText("Login"));
await Test.waitFor(() => screen.findByText(USER_MESSAGE));
await Test.waitFor(() =>
screen.findByText(PASSWORD_MESSAGE)
);
});