在 react-testing-library 中按 id 查找元素

Posted

技术标签:

【中文标题】在 react-testing-library 中按 id 查找元素【英文标题】:Find element by id in react-testing-library 【发布时间】:2019-03-30 21:52:17 【问题描述】:

我正在使用react-testing-libarary 来测试我的 React 应用程序。出于某种原因,我需要能够通过id 而不是data-testid 找到元素。文档中没有办法实现这一点。

有没有办法做到这一点?

我的渲染输出为:

const dom = render(<App />);

我正在寻找符合以下条件的东西:

const input = dom.getElemenById('firstinput');
//or 
const input = dom.getById('firstinput');

【问题讨论】:

这对我有用:document.getElementById('firstinput') 【参考方案1】:

我觉得没有一个答案真正给出了完整的解决方案,所以这里是:

const result = render(<SomeComponent />);
const someElement = result.container.querySelector('#some-id');

【讨论】:

对我不起作用。但是当我登录 result.debug() 时,我可以清楚地看到具有该 ID 的元素。 :(【参考方案2】:

我找到了一种方法。

import App from './App';
import  render, queryByAttribute  from 'react-testing-library';

const getById = queryByAttribute.bind(null, 'id');

const dom = render(<App />);
const table = getById(dom.container, 'directory-table');

我希望这会有所帮助。

【讨论】:

为什么他们默认没有这个??我不敢相信。 简单地使用document.getElementById会容易得多。但是元素的 ID 是一个实现细节,我建议不要使用它。 @Victor 相信它。用户不会按 ID 填写元素,因此测试也不应该(至少根据 react-testing-library 的理念)。他们通过标签填写它们,因此您应该以与用户查找元素相同的方式在测试中找到您的元素:通过标签或占位符文本或其他方式。 @Imat - 恢复莫妮卡,好吧,我讨论了#id 解决方案可能是理想方案的一些场景。一切都取决于场景。一个简单的例子:当使用第三方库(如 Kendo)时,通过您提供的#id 构建元素,您可以创建依赖于 id 的测试来访问元素。使用#id 将保持与第三方库的新版本的兼容性,并且它也不会用 data-test-id 污染我们的代码。我在这里更深入地解释了这一点:github.com/testing-library/react-testing-library/issues/… 继续滚动直到@Liran H 回答。【参考方案3】:

看起来你的 DOM 节点本身是 container。因此,您应该可以使用它调用.querySelector('#firstinput')

【讨论】:

是的,这行得通,但这里唯一的问题是现在我无法在这个返回的节点上使用 react-testing-library 助手。 如果你不需要帮助器,不使用它们没有错 “我无法在这个返回的节点上使用 react-testing-library 助手。”这是不正确的。你说的是什么帮手?所有助手都处理常规的 DOM 节点,因此您如何找到它并没有什么不同。但无论哪种方式,通过 ID 查找元素都不包含在库中,因为这是一个实现细节。使用内置查询之一。 Liran H 的回答比较好。有些人可能不明白你的意思。举一个像他这样的完整例子更好。 这是实现这一目标的最快、最简单的方法。拥抱【参考方案4】:

您可以在配置中设置testIdAttribute

configure( testIdAttribute: 'id' )

https://testing-library.com/docs/dom-testing-library/api-configuration


设置有利有弊。这样做的好处是您可以设置一个 id 用于多种用途。 (测试 id、营销分析、标签管理器等)您不必同时添加 id 和 test-id。有利于代码的简洁。

但请注意,您可能会不小心在同一页面上的两个不同组件中设置了相同的 id。记得为列表项的组件 ID 添加索引或标识。

【讨论】:

testIdAttribute:getByTestId 和相关查询使用的属性。默认为data-testid 这是个坏主意,因为 id 对整个页面上的单个元素来说是唯一的,而测试 id 可以用于多个元素(例如列表项)。 是的,你可能是对的。但是,如果我们需要将 id 用于多种用途,则设置有一些好处。 (例如标签管理器)【参考方案5】:

有两种方法可以做到这一点

    只需使用container.getElementById('id')。最后,所有助手所做的都是在后台进行类似这样的查询 如果您想要自定义查询,您可以编写自定义渲染。查看文档以获取更多信息https://github.com/kentcdodds/react-testing-library#getbytestidtext-textmatch-htmlelement

最后一点,如果您可以避免通过 id 查找元素,那就更好了。

【讨论】:

我认为您无权访问容器上的 getElementById。 这是正确答案。 (我是测试库的作者)。 尝试登录container 我猜这不是你要找的 @kentcdodds 我的意思是,如果那样工作(从 1 开始)会很好,但我得到的只是TS2339: Property 'getElementById' does not exist on type 'HTMLElement'. getElementById 甚至没有出现在 RTL 文档中'-' 对我来说,正确的方法是使用这个工具:chrome.google.com/webstore/detail/testing-playground/… 我再也没有花时间添加/查找 ID。【参考方案6】:

我的建议:停止添加和搜索 id,这总是需要花费大量时间和精力,因为您必须添加 id(有时是 test-id),然后找出查询元素的最佳方法。但即使你真的需要一个 id,这个工具也会通过显示在你的屏幕上查询任何 DOM 元素的最佳方式为你节省大量时间:Testing Playground

【讨论】:

以上是关于在 react-testing-library 中按 id 查找元素的主要内容,如果未能解决你的问题,请参考以下文章

如何在 react-testing-library 中访问 prop 值

使用 react-testing-library 在 useEffect 中测试 api 调用

Codesandbox.io 中的 React-Testing-Library 问题

酶、ReactTestUtils 和 react-testing-library 之间的区别

如何在使用 react-testing-library 和 jest 完成的单元测试中启用 react-i18n 翻译文件?

如何为 react-testing-library 定义容器大小?