我正在使用React Testing Library中的getByTestId
函数:
const button = wrapper.getByTestId("button");
expect(heading.textContent).toBe("something");
是否有可能/建议搜索HTML元素?就像这样:
const button = wrapper.getByHTML("button");
const heading = wrapper.getByHTML("h1");
我正在使用React Testing Library中的getByTestId
函数:
const button = wrapper.getByTestId("button");
expect(heading.textContent).toBe("something");
是否有可能/建议搜索HTML元素?就像这样:
const button = wrapper.getByHTML("button");
const heading = wrapper.getByHTML("h1");
我不确定在这种情况下wrapper
是什么。但是为了回答你的两个问题:是的,可以通过HTML元素实现,但并不推荐。
以下是如何实现:
// Possible but not advisable
const { container } = render(<MyComponent />)
// `container` is just a DOM node
const button = container.querySelector('button')
由于您得到的是DOM节点,因此可以使用所有常规的DOM API,例如querySelector
。
那么,为什么这不可取呢? react-testing-library的一个重要卖点是您像用户一样测试组件。这意味着不依赖于实现细节。例如,您无法直接访问组件状态。
以这种方式编写测试有点困难,但允许您编写更健壮的测试。
在您的情况下,我会认为底层HTML是一项实现细节。如果您更改HTML结构,使h1
成为h2
或div
,测试将会失败。相反,如果通过文本查看这些元素,则标记变得无关紧要。
在某些情况下,普通查询助手可能不足够。对于这些事件,您可以使用data-testid
并使用getByTestId
。
根据您要查询的元素类型,您可能还会发现byRole
API很有用:
https://testing-library.com/docs/queries/byrole/
例如,level
对我来说特别有用,可用于测试默认的<h1>
元素是否正确地被覆盖:
it('correctly renders override header level', () => {
const { getByRole } = render(<Heading overrideHeadingLevel="h6" />)
expect(getByRole('heading', { level: 6 })).toBeInTheDocument()
})
*ByRole
查询是更符合惯用法的解决方案。 - juliomalvesgetByRole('button')
将匹配<button>
和<a role="button">
,上面例子将匹配<h6>
和<a role="heading" aria-level="6">
——这很好,因为关心这些角色的工具(如果构建得正确…)将把它们视为相同。 - user56reinstatemonica8另一个可能的解决方案是
考虑渲染您的组件。
render(<ReactComponent />);
const button = screen.getByText((content, element) => element.tagName.toLowerCase() === 'button');
如果您有多个按钮,请使用getAllByText
并引用您需要选择的目标元素。
getByRole('paragraph')
不起作用)。container.querySelector
。虽然对于大多数情况来说这样做没问题,但自定义查询将允许更多地控制当找不到、找到过多等情况时该怎么做,还可以自定义错误消息。
文档仅提供了基于属性的自定义查询示例,因此我们可以这样做:import { queryHelpers } from '@testing-library/dom';
import { queries as libraryQueries } from '@testing-library/react';
function getAllByTagName(
container: HTMLElement,
tagName: keyof JSX.IntrinsicElements,
) {
return Array.from(container.querySelectorAll<HTMLElement>(tagName));
}
function getByTagName(
container: HTMLElement,
tagName: keyof JSX.IntrinsicElements,
) {
const result = getAllByTagName(container, tagName);
if (result.length > 1) {
throw queryHelpers.getElementError(
`Found multiple elements with the tag ${tagName}`,
container,
);
}
return result[0] || null;
}
export const queries = {
...libraryQueries,
getAllByTagName,
getByTagName,
};
import { queries } from '../helpers/queries'
// it('...')
const { getAllByTagName } = render(<MyComponent />, { queries } )
const paragraphs = getAllByTagName('p')
import { render } from '@testing-library/react';
import { queries } from '../helpers/queries'
function renderWithProviders(node: JSX.Element) {
return render(
<SomeProvider>{node}</SomeProvider>, { queries }
)
}
h2
,但通常这是例外而不是规则。 - Gio PolvaragetByDataAttribute("data-custom-value")
方法。这些并不是实现细节,它们可以存在于任何元素上,并且可以更改而不会破坏测试。为什么要将事情限制在特定于测试的数据属性上呢? - Jeremy