如何使用React路由器导航测试hooks?

问题描述 投票:0回答:1

当挂钩具有一些导航逻辑时,我在使用

renderHook
实用程序测试挂钩时遇到一些问题。我无法在测试中模拟导航。

例如,让我们以这个示例钩子为例

export const useNavBar = () => {
   const location = useLocation();

   const isExpandable = useMemo(() => {
         const aPath = matchPath({path: "/a-rute"}, location.pathName);
         const anotherPath = matchPath({path: "/another-rute"}, location.pathName);

         return !aPath && !anotherPath
   },[location.pathname]);

   return {isExpandable}
}

目前我想尝试当用户导航到不可扩展的路线时,它会发生变化。然而,它似乎在测试中忽略了

window.history.pushState

it("changes expandable accessing an invalid route", () => {
   const {result} = renderHook(useNavBar, {wrapper: BrowserRouter});    
   expect(result.current.isExpandable).toBeTruthy();
 
   window.history.pushState({}, '', '/a-route');

   expect(result.current.isExpandable).toBeFalsy();
}

调用

window.history.pushState
不会触发重新渲染,因此不会更新值。同样手动调用
rerender
也没有效果,因为
useLocation
没有注意到这些变化。

那么,如何使用

renderHook
更新位置?

reactjs react-hooks react-router react-testing-library
1个回答
0
投票

问题在于

BrowserRouter
不知道任何
window.history.pushState
,并且可能无论如何都无法在 Node.js 环境中工作。在单元测试中,我们通常使用
MemoryRouter

我没有太多使用

renderHook
,但我怀疑你可以创建一个包装器来呈现一个
HistoryRouter
,并传递一个自定义的
memoryHistory
对象(例如内存路由器),然后你可以使用它来实现效果导航动作。

示例:

import { renderHook, act } from "@testing-library/react";
import { unstable_HistoryRouter as Router } from "react-router-dom"; // <-- v6
import { createMemoryHistory } from "history"; // <-- history@5

const history = createMemoryHistory(); // defaults to `"/"`

const RouterWrapper = ({ children }) => (
  <Router history={history}>
    {children}
  </Router>
);

it("changes expandable accessing an invalid route", () => {
  const { result } = renderHook(useNavBar, { wrapper: RouterWrapper });    
  expect(result.current.isExpandable).toBeTruthy();
 
  // Navigate to new path with new search params
  act(() => {
    history.push("/a-route");
  });

  expect(result.current.isExpandable).toBeFalsy();
}

这一切都假设您正在使用

react-router-dom@6
。如果您使用的是较旧的 v5 版本,请导入低级
Router
并确保您将
history@4
作为兼容性依赖项。

© www.soinside.com 2019 - 2024. All rights reserved.