更新 2
我已经使用了很多次,创建了一个助手。下面是使用此帮助程序的示例测试。
测试助手:
// withMarkup.ts
import { MatcherFunction } from '@testing-library/react'
type Query = (f: MatcherFunction) => HTMLElement
const withMarkup = (query: Query) => (text: string): HTMLElement =>
query((content: string, node: HTMLElement) => {
const hasText = (node: HTMLElement) => node.textContent === text
const childrenDontHaveText = Array.from(node.children).every(
child => !hasText(child as HTMLElement)
)
return hasText(node) && childrenDontHaveText
})
export default withMarkup
测试:
// app.test.tsx
import { render } from '@testing-library/react'
import App from './App'
import withMarkup from '../test/helpers/withMarkup'
it('tests foo and bar', () => {
const { getByText } = render(<App />)
const getByTextWithMarkup = withMarkup(getByText)
getByTextWithMarkup('Name: Bob (special guest)')
})
更新 1
这是一个创建新匹配器getByTextWithMarkup 的示例。请注意,此函数在测试中扩展 getByText,因此必须在此处定义。 (当然可以更新函数以接受getByText 作为参数。)
import { render } from "@testing-library/react";
import "jest-dom/extend-expect";
test("pass functions to matchers", () => {
const Hello = () => (
<div>
Hello <span>world</span>
</div>
);
const { getByText } = render(<Hello />);
const getByTextWithMarkup = (text: string) => {
getByText((content, node) => {
const hasText = (node: HTMLElement) => node.textContent === text
const childrenDontHaveText = Array.from(node.children).every(
child => !hasText(child as HTMLElement)
)
return hasText(node) && childrenDontHaveText
})
}
getByTextWithMarkup('Hello world')
这是来自Five Things You (Probably) Didn't Know About Testing Library 的第 4 个来自Giorgio Polvara's Blog 的可靠答案:
查询也接受函数
你可能见过这样的错误:
找不到带有以下文字的元素:Hello world。
这可能是因为文本被多个元素分解。
在这种情况下,您可以为您的文本提供一个功能
matcher 让你的 matcher 更加灵活。
通常,这是因为您的 HTML 如下所示:
<div>Hello <span>world</span></div>
解决方案包含在错误消息中:“[...] you can provide a function for your text matcher [...]”。
那是怎么回事?事实证明,匹配器接受字符串、正则表达式或函数。
函数会为您渲染的每个节点调用。它接收两个参数:节点的内容和节点本身。您所要做的就是根据节点是否是您想要的节点返回 true 或 false。
举个例子就明白了:
import { render } from "@testing-library/react";
import "jest-dom/extend-expect";
test("pass functions to matchers", () => {
const Hello = () => (
<div>
Hello <span>world</span>
</div>
);
const { getByText } = render(<Hello />);
// These won't match
// getByText("Hello world");
// getByText(/Hello world/);
getByText((content, node) => {
const hasText = node => node.textContent === "Hello world";
const nodeHasText = hasText(node);
const childrenDontHaveText = Array.from(node.children).every(
child => !hasText(child)
);
return nodeHasText && childrenDontHaveText;
});
});
我们忽略了content 参数,因为在这种情况下,它将是“Hello”、“world”或空字符串。
我们检查的是当前节点是否拥有正确的textContent。 hasText 是一个小助手功能。我宣布它是为了保持清洁。
这还不是全部。我们的div 不是我们要查找的文本的唯一节点。例如,body 在这种情况下具有相同的文本。为了避免返回比需要更多的节点,我们确保没有一个子节点与其父节点具有相同的文本。通过这种方式,我们确保我们返回的节点是最小的——换句话说,那个节点靠近我们的 DOM 树的底部。
阅读Five Things You (Probably) Didn't Know About Testing Library的其余部分