如何在react-testing-library中获取带有“name”属性的元素

30

我正在使用React测试库和Jest测试我的React应用。

我想知道如何在react-testing-library中使用'name'属性获取元素。

例如,在下面的页面中,是否可以通过"userName"获取此元素?

<input type="text" name="userName" />

我应该将data-testId设置到元素中并使用getByTestId方法吗?

return (
  <div>
    <input type="text" name="userName" />
  </div>
)
3个回答

38
你可以使用返回的 containercontainer 是一个 DOM 节点,并支持 querySelector 方法,该方法接受一个 CSS 选择器来查找元素。与这个更详细的答案的方法相同。
例如:
const { container } = render(<MyComponent />);
const inputEl = container.querySelector(`input[name="userName"]`);

24

在DOM中查找元素的一般推荐方式是采用类似应用程序使用方式的方法。

在这个例子中,如@ggorlen所指出的那样,name属性将不会被识别。

对于文本输入的回退,您可以依靠getByLabelText(假设您已经添加了一个带有htmlFor的标签),或者您可以向文本输入添加aria-label

<input type="text" aria-label="userName" />

然后使用:

screen.getByRole("textbox", {name: /userName/i});

data-testid的问题在于你必须专门为测试添加它,而不能依赖更自然的findByRolefindByPlaceholderTextfindByLabelText

getByTestId 应该是你的最后选择。

作为后续建议,我推荐使用Testing Playground浏览器扩展程序,它可以为元素生成RTL查询,类似于在浏览器devTools中查找元素。

另外,当搜索名称(或其他属性)时遇到问题时,请尝试调查给定元素/组件的可访问性特性,以准确确定如何搜索它。


1
这里可能会有一些关于 name 的混淆。它是 ARIA 可访问名称,而不是 name="userName" 属性。请参阅 What is the name option in react-testing-library? - ggorlen
添加了一个答案,并提供了一个示例,证明这种方法{name: /userName/i}是无效的。 - ggorlen
感谢您的反馈,我更新了我的答案,以便未来的读者不会看到错误的代码片段。我还标记了您,以便您得到认可。 - jckmlczk

5

在某些情况下,您可以通过角色(或者不太理想的测试 ID)选择元素,然后断言所需属性是否存在,而不是依赖于本地 DOM,以代替全能的getBy调用:

expect(screen.getByRole("textbox")).toHaveAttribute("name", "userName");

很遗憾,

screen.getByRole("textbox", {name: "userName"});

代码似乎并没有按照预期工作。请参考React测试库中的名称选项是什么?进行解释。

证明:

import React from "react"; // 17.0.2
import {render, screen} from "@testing-library/react"; // 12.1.2
import "@testing-library/jest-dom/extend-expect"; // ^5.16.1

describe("getByRole experiments", () => {
  beforeEach(() => render(<input type="text" name="userName" />));

  it("should work with a plain getByRole", () => {
    expect(screen.getByRole("textbox"))
      .toHaveAttribute("name", "userName"); // OK
  });

  it("will fail specifying {name: /userName/i}", () => {
    screen.getByRole("textbox", {name: /userName/i}); // Fails
  });

  it('will also fail specifying {name: "userName"}', () => {
    screen.getByRole("textbox", {name: "userName"}); // Fails
  });
});

部分输出(name: "userName" 断言失败基本相同):

TestingLibraryElementError: Unable to find an accessible element with the role "textbox" and name `/userName/i`

Here are the accessible roles:

  textbox:

  Name "":
  <input
    name="userName"
  />

  --------------------------------------------------

Ignored nodes: comments, <script />, <style />
<body>
  <div>
    <input
      name="userName"
    />
  </div>
</body>

另请参阅{{link1:React测试库:如何在自定义角色上使用getByRole}}。


密码字段可以使用吗? - undefined
请参考dom-testing-library问题#567来选择密码字段。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接