使用 React Router V6 测试 React 组件

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(),但这在组件之外不起作用。

如果有人对我如何使这项工作有任何想法。我将不胜感激。

Dre*_*ese 9

MemoryRouter仍然需要一个数组initialEntries

内存路由器

declare function MemoryRouter(
  props: MemoryRouterProps
): React.ReactElement;

interface MemoryRouterProps {
  basename?: string;
  children?: React.ReactNode;
  initialEntries?: InitialEntry[];
  initialIndex?: number;
}
Run Code Online (Sandbox Code Playgroud)

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)


San*_*tos 6

希望我能帮助别人。

这是我的场景:

  • 使用 useParams 接收参数的组件。
  • 测试库
  • 反应路由器 6
  • 打字稿

成分:

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)