使用 React Router V6 测试 React 组件

Testing React Component with React Router V6

我知道 React Testing Library 有一个使用 React router 进行测试的示例,但我无法让它工作(我想是因为我使用的是 React router 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/>);
});

不足为奇,但这没有用。我假设 window.history.pushState() 不适用于 React 路由器 V6。我尝试使用 useNavigate(),但这在组件之外不起作用。

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

MemoryRouter 仍然采用 initialEntries 的数组。

MemoryRouter

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

interface MemoryRouterProps {
  basename?: string;
  children?: React.ReactNode;
  initialEntries?: InitialEntry[];
  initialIndex?: number;
}

我会从 customRender 中删除 MemoryRouter 并只在本地包装被测组件并传入特定的初始路由条目以进行测试。

const AllTheProviders = ({ children }) => {
  return (
    <ApolloProvider client={client}>
      <Provider store={store}>
        {children}
      </Provider>
    </ApolloProvider>
  );
};
const customRender = (ui, options) => 
  render(ui, { wrapper: AllTheProviders, ...options });

...

const { ....queries.... } = customRender(
  <MemoryRouter
    initialEntries={["Test page", "/details/url-param-the-component-needs"]}
  >
    <ComponentUnderTest />
  </MemoryRouter>
);

一个额外的想法,useParams 钩子可能还需要一个 Route 和一个 path 属性来指定组件需要的匹配参数,所以你的测试可能看起来像下面这样:

const { ....queries.... } = customRender(
  <MemoryRouter
    initialEntries={["Test page", "/details/url-param-the-component-needs"]}
  >
    <Routes>
      <Route path="/details/:theParam" element={<ComponentUnderTest />} />
    </Routes>
  </MemoryRouter>
);

希望能帮到别人。

这是我的场景:

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

组件:

type UrlParamsType = {
  id: string;
};
const Code: FC = () => {
  const navigate = useNavigate();
  const { id } = useParams<keyof UrlParamsType>() as UrlParamsType;
return (<label> {id} </label>);};

我用那个 id 做了很多事情,所以我需要它可以用 testing-library 进行测试。

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));
  });