我有这个 React 组件,它依赖于 props 和要渲染的查询参数:
const Module = ({ color = 'green' }) => {
const location = useLocation()
let name = 'Pear'
const matchedStr = location.search.match(/name=[a-zA-Z]+/)
if (matchedStr){
name = matchedStr.split('=')[1]
}
return <div id="Module">{`${name} is ${color}`}</div>
}
我正在尝试编写一个测试来检查组件是否对 prop 更改和查询参数更改做出反应。
/* react-testing-libray setup */
test('Module responses to both prop change and query param change', () => {
const screen = render(
<MemoryRouter initialEntries={["/?name=Banana"]}>
<Module color="yellow" />
</MemoryRouter>
)
expect(screen.getByText('Banana is yellow')).toBeInTheDocument() // this passes
screen.rerender(
<MemoryRouter initialEntries={["/?name=Apple"]}>
<Module color="red" />
</MemoryRouter>
)
expect(screen.getByText('Apple is red')).toBeInTheDocument() // this fails
})
我不知道如何让组件从 React-Router 钩子中观察位置变化。文本总是显示为“香蕉是红的”
部分套餐信息:
我尝试过以下方法,但都不起作用:
Routes
和 Route
组件来渲染模块。useSearhParams
挂钩代替 useLocation
initialEntries
的MemoryRouter
亲搞混。只要我重新渲染当前屏幕,查询参数名称似乎就会及时冻结为“Banana”。如果我渲染一个新屏幕就好了。
测试应实现从初始
"/?name=Banana"
URL 路径/searchParams 到下一个 "/?name=Apple"
URL 路径/searchParams 的导航更改。
使用
HistoryRouter
和自定义 history
对象,以便您可以在测试中实现导航操作。
示例:
模块.test.jsx
import { render, act } from "@testing-library/react";
import "@testing-library/jest-dom";
import { unstable_HistoryRouter as Router } from "react-router-dom";
import { createMemoryHistory } from "history"; // <-- history@5
import Module from "./Module";
const history = createMemoryHistory({
initialEntries: ["/?name=Banana"]
});
test("Module responses to both prop change and query param change", () => {
const screen = render(
<Router history={history}>
<Module color="yellow" />
</Router>
);
expect(screen.getByText("Banana is yellow")).toBeInTheDocument(); // this passes
// Navigate to new path with new search params
act(() => {
history.push("/?name=Apple");
});
screen.rerender(
<Router history={history}>
<Module color="red" />
</Router>
);
expect(screen.getByText("Apple is red")).toBeInTheDocument(); // this fails
});
FWIW,您的
Module
组件以及从 URL searchParams 读取 name
值也需要改进。使用 useSearchParams
钩子来读取它们,而不是尝试对 location.search
字符串进行字符串/REGEX 处理。
示例:
import { useSearchParams } from "react-router-dom";
const Module = ({ color = "green" }) => {
const [searchParams] = useSearchParams();
const name = searchParams.get("name");
return <div id="Module">{`${name} is ${color}`}</div>;
};
export default Module;