更新2
我已经多次使用过这个工具,所以我创建了一个辅助程序。下面是使用这个辅助程序的一个示例测试。
测试辅助程序:
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
测试:
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')
})
这是来自
Giorgio Polvara's Blog的
Five Things You (Probably) Didn't Know About Testing Library第四个问题的确切答案。
查询也接受函数
你可能会看到这样的错误:
无法找到文本为“Hello world”的元素。
这可能是因为文本被多个元素分隔开。
在这种情况下,你可以为你的文本匹配器提供一个函数,
以使你的匹配器更加灵活。
通常,这是因为你的 HTML 看起来像这样:
<div>Hello <span>world</span></div>
解决方案包含在错误信息中:“[...]您可以为文本匹配器提供一个函数[...]”。
这是什么意思?原来,匹配器接受字符串、正则表达式或函数。
该函数会为您渲染的每个节点调用。它接收两个参数:节点的内容和节点本身。您只需根据节点是否符合您的要求返回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 />);
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树底部最接近的节点。
阅读
关于Testing Library你(可能)不知道的五件事的其余部分。