使用 React 测试库在 React 中模拟浏览器事件
为何模拟
在对 React 组件进行单元测试时,能够模拟浏览器事件通常很有用。这使我们能够断言事件处理程序已被调用并断言正确的参数。我们模拟浏览器事件是因为我们通常不想在测试环境中(尤其是在单元测试中)要求真实的浏览器。
模拟浏览器事件的方法有很多种。在这里,我们将介绍一个可靠的第三方库,它为我们提供了出色的 API 和测试浏览器事件的方法,即React Testing Library。
使用@testing-library/react fireEvent
React Testing Library 的fireEvent模块中提供了一些实用程序,用于模拟浏览器事件,例如click和change 。此模块包含许多不同的受支持事件。我们将尝试两种常见的事件:
- fireEvent.click
- fireEvent.change
要使用该库,首先安装它:
npm install @testing-library/react --save-dev
一个简单的组件
为了进行测试,让我们设置一个简单的组件:
import React from "react";
export default function Button(props) {
return <button {...props} />;
}
这里没什么事情发生。我们正在创建最简单的自定义组件,并将 props 传播到按钮元素上。
模拟点击事件
让我们在这个自定义按钮组件上测试一个onClick prop 。我们将使用create-react-app中的标准jest API :
import {
cleanup,
fireEvent,
render
} from "@testing-library/react";
import Button from "./Button.js";
it("captures clicks", done => {
function handleClick() {
done();
}
const { getByText } = render(
<Button onClick={handleClick}>Click Me</Button>
);
const node = getByText("Click Me");
fireEvent.click(node);
});
afterEach(cleanup);
首先,我们从@testing-library/react导入所需的函数。
在我们的测试中,我们从该库调用render ,传入按钮组件的使用。React Testing Library 负责设置测试的 DOM,然后渲染到该 DOM 中。为了确保 DOM 在测试之间得到清理,以便每个测试都可以独立运行,我们调用afterEach(cleanup)。
render函数调用返回许多内容。在此示例中,我们正在解构 React Testing Library 的getBy函数之一,特别是getByText 。此函数将在此特定测试的渲染 DOM 中搜索具有匹配 innerText 的元素。在示例中,我们寻找“Click Me” 。
一旦我们有了这个节点,我们就能够使用fireEvent.click在其上发送点击事件。
<Button />的onClick属性是handleClick事件处理函数的值。该函数调用done() ,它是it函数的回调。
请注意,传递此回调会使测试异步,这意味着在调用回调之前测试不会完成。如果从未调用过,测试将超时并失败。相反,如果调用了回调,则表明在按钮上模拟了点击并调用了处理程序。使用上面的代码,确实如此!
模拟变化事件
让我们尝试另一种浏览器事件模拟。这次,我们将模拟一个更改事件。这种事件对于文本输入字段之类的东西很有用,我们想知道输入值何时发生变化以及当前值实际上是多少。
我们将创建一个TextInput.js组件:
import React from "react";
export default function TextInput(props) {
return <input {...props} />;
}
请注意,这再次非常简单,只是将所有{...props}传递到输入元素的前面。
这次测试与上次非常相似:
it("captures changes", done => {
function handleChange(evt) {
expect(evt.target.value).toEqual("whamo");
done();
}
const { getByPlaceholderText } = render(
<TextInput onChange={handleChange} placeholder="Change Me" />
);
const node = getByPlaceholderText("Change Me");
fireEvent.change(node, { target: { value: "whamo" } });
});
这次,为了找到触发事件的节点,我们使用了不同的查询函数getByPlaceholderText。并且,我们调用fireEvent.change函数,传递一个新的第二个参数。我们作为参数传递的这个对象代表Event对象。例如,它包括target属性,通常表示从哪个元素分派了 Event。在这里,我们只是存根一个值。
然后,在我们的handleChange处理程序中,我们可以断言事件目标的值作为“whamo”(始终是一个很大的输入值)。
众多方法之一
现在我们已经模拟了两种不同的浏览器事件。我们应该能够以类似的方式处理我们可能需要的任何其他事件。
这是一个可靠的社区库,它为我们提供了一些用于事件模拟和其他方面的出色 API。我们使用的查询方法还帮助我们不深入组件实现,而是将其视为黑盒,检查 DOM 本身(组件的普通客户端可以看到的内容)。
还有许多其他库和方法可以模拟浏览器事件。最基本的、不需要任何额外测试库的方法之一是使用官方的react-dom/test-utils。要探索这种方法,请参阅相关指南使用 ReactTestUtils 在 React 中模拟浏览器事件。
试验并尝试几种方法,然后选择一种适合您的口味和项目的方法。
要在您自己的机器上运行上述示例中的测试,请查看此demo-react-simulate-test项目。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~