当钩子有一些导航逻辑时,我在用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 }
}

目前我想try 一下,当用户导航到不可扩展的路由时,它会发生变化.然而,在测试中,它似乎忽略了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更新位置呢?

推荐答案

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

我用过的renderHook不多,但我想您可以创建一个包装器来呈现一个HistoryRouter,该HistoryRouter传递一个定制的memoryHistory对象(e.g. a memory router),然后您可以使用该对象来实现导航操作.

示例:

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
  act(() => {
    history.push("/a-route");
  });

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

这一切都假设您使用的是react-router-dom@6.如果您使用的是较早的v5版本,那么导入低级别的Router,并确保您有history@4作为兼容性依赖项.

Javascript相关问答推荐

我的glb文件没有加载到我的three.js文件中

将json数组项转换为js中的扁平

屏幕右侧屏障上的产卵点""

如何避免页面第一次加载时由于CSS样式通过JavaScript更改而出现闪烁

JS:XML insertBefore插入元素

Eval vs函数()返回语义

WP Bootstrap NavWaker:下拉菜单一次打开所有下拉菜单

扩展类型的联合被解析为基类型

如何在FastAPI中为通过file:/URL加载的本地HTML文件启用CORS?

为什么云存储中的文件不能公开使用?

当标题被点击时,如何使内容出现在另一个div上?

如何使本地html页面在重新加载时保持当前可隐藏部分的打开状态?

如果NetSuite中为空,则限制筛选

AG-GRIDreact 显示布尔值而不是复选框

调用特定数组索引时,为什么类型脚本不判断未定义

在Puppeteer中使用promise进行日志(log)记录时出现TargetCloseError

为什么这个最小Angular 的Licial.dev设置不起作用?

当S点击按钮时,我如何才能改变它的样式?

验证Java脚本函数中的两个变量

如何使用Angular JS双击按钮