cxg*_*end 16 reactjs react-router react-router-dom react-testing-library
我知道 React 测试库有一个使用 React 路由器进行测试的示例,但我无法让它工作(我想是因为我使用的是 React 路由器 V6)。
基本上,我需要路由器测试,因为我有使用 useParams() 来获取部分 url 的详细信息组件。没有它我无法渲染组件。
这是我让它工作的尝试(是的,该页面也需要 apollo,尽管它并不真正需要 redux)。
const AllTheProviders = ({children, initialRoutes}) => {
return (
<ApolloProvider client={client}>
<Provider store={store}>
<MemoryRouter>
{children}
</MemoryRouter>
</Provider>
</ApolloProvider>
);
}
const customRender = (ui, options) => render(ui, {wrapper: AllTheProviders, ...options})
beforeEach(() => {
window.history.pushState({}, 'Test page',"/details/url-param-the-component-needs")
customRender(<App/>);
});
Run Code Online (Sandbox Code Playgroud)
毫不奇怪,但这不起作用。我假设 window.history.pushState() 不适用于 React Router V6。我尝试使用 useNavigate(),但这在组件之外不起作用。
如果有人对我如何使这项工作有任何想法。我将不胜感激。
MemoryRouter仍然需要一个数组initialEntries。
Run Code Online (Sandbox Code Playgroud)declare function MemoryRouter( props: MemoryRouterProps ): React.ReactElement; interface MemoryRouterProps { basename?: string; children?: React.ReactNode; initialEntries?: InitialEntry[]; initialIndex?: number; }
MemoryRouter我将从中删除customRender并仅在本地包装受测试的组件,并传入测试的特定初始路由条目。
const AllTheProviders = ({ children }) => {
return (
<ApolloProvider client={client}>
<Provider store={store}>
{children}
</Provider>
</ApolloProvider>
);
};
const customRender = (ui, options) =>
render(ui, { wrapper: AllTheProviders, ...options });
Run Code Online (Sandbox Code Playgroud)
...
const { ....queries.... } = customRender(
<MemoryRouter
initialEntries={["Test page", "/details/url-param-the-component-needs"]}
>
<ComponentUnderTest />
</MemoryRouter>
);
Run Code Online (Sandbox Code Playgroud)
另外一个想法,useParams钩子可能还需要一个Route带有path指定组件所需的匹配参数的 prop,因此您的测试可能如下所示:
const { ....queries.... } = customRender(
<MemoryRouter
initialEntries={["Test page", "/details/url-param-the-component-needs"]}
>
<Routes>
<Route path="/details/:theParam" element={<ComponentUnderTest />} />
</Routes>
</MemoryRouter>
);
Run Code Online (Sandbox Code Playgroud)
希望我能帮助别人。
这是我的场景:
成分:
type UrlParamsType = {
id: string;
};
const Code: FC = () => {
const navigate = useNavigate();
const { id } = useParams<keyof UrlParamsType>() as UrlParamsType;
return (<label> {id} </label>);};
Run Code Online (Sandbox Code Playgroud)
我用这个 id 做了几件事,所以我需要它可以用测试库进行测试。
import { createMemoryHistory } from 'history';
import { Router, Routes, Route } from 'react-router-dom';
it('should show something', () => {
const history = createMemoryHistory();
const route = '/something/sms/9393939393';
history.push(route);
render(
<Router location={history.location} navigator={history}>
<Routes>
<Route path="/something/sms/:id" element={<Code/>} />
</Routes>
</Router>
);
expect(screen.getByText(/9393/i));
});
Run Code Online (Sandbox Code Playgroud)
如果这对您不起作用,或者历史记录包不可用:
render(<MemoryRouter initialEntries={['/something/sms/9393939393']}>
<Routes>
<Route path="/something/sms/:id" element={<Code/>} />
</Routes>
</MemoryRouter>);
Run Code Online (Sandbox Code Playgroud)