getByRole、queryByRole、getAllByRole、queryAllByRole、findByRole、 findAllByRole
API
getByRole(
// If you're using `screen`, then skip the container argument:
container: HTMLElement,
role: string,
options?: {
hidden?: boolean = false,
name?: TextMatch,
description?: TextMatch,
selected?: boolean,
busy?: boolean,
checked?: boolean,
pressed?: boolean,
suggest?: boolean,
current?: boolean | string,
expanded?: boolean,
queryFallbacks?: boolean,
level?: number,
value?: {
min?: number,
max?: number,
now?: number,
text?: TextMatch,
}
}): HTMLElement
查询具有给定角色的元素(它还接受 TextMatch)。默认角色也会被考虑,例如,在不明确设置 role 属性时,其角色为 button。这里你可以看到一份包含 HTML 元素默认角色和期望角色的表格。
请注意,设置与隐式 ARIA 语义匹配的 role 和 / 或 aria-* 属性是不必要的,也是不建议的,因为这些属性已由浏览器设置,我们不得以与描述的语义相冲突的方式使用 role 和 aria-* 属性。例如,button 元素不能有 role 属性的 heading,因为 button 元素具有与 heading role 相冲突的默认特性。
角色的匹配是通过字符串相等性进行字面匹配的,并且不继承 ARIA 角色层次结构。因此,查询类似 checkbox 的超类角色将不会包括具有类似 switch 的子类角色的元素。
你可以通过可访问名称或描述来查询返回的元素。可访问名称对于简单情况来说,例如表单元素的标签,或者按钮的文本内容,或者aria-label属性的值,都是相等的。如果渲染的内容上存在多个具有相同角色的元素,那么它可用于查询特定元素。要了解更深入的指南,请查看TPGi的“可访问名称是什么?”。如果你只使用getByText('The name')查询单个元素,那么通常最好使用getByRole(expectedRole, { name: 'The name' })。可访问名称查询不能替代其他查询,如ByAlt或ByTitle。虽然可访问名称可能与这些属性相等,但它不能替代这些属性的功能。例如 <img aria-label="fancy image" src="fancy.jpg" />
,将通过 getByRole('img', { name: 'fancy image' }) 返回。但是,如果 fancy.jpg 无法加载,图像将不会显示其描述。是否要在测试中验证此功能由你决定。
Options
hidden
如果将 hidden 设置为 true,那么通常从可访问性树中排除的元素也将被纳入查询的考虑范围。默认行为遵循 https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion,但 role="none" 和 role="presentation" 无论如何都将被纳入查询的考虑范围。
例如:
<body>
<main aria-hidden="true">
<button>Open dialog</button>
</main>
<div role="dialog">
<button>Close dialog</button>
</div>
</body>
getByRole('button')
只会返回 “Close dialog” 按钮。如果你想对 “Open dialog” 按钮进行断言,你需要使用 getAllByRole('button', { hidden: true })
。
hidden 的默认值可以进行配置。
selected
您可以通过设置 selected: true 或 selected: false 来根据所选状态筛选返回的元素。
例如:
<body>
<div role="tablist">
<button role="tab" aria-selected="true">Native</button>
<button role="tab" aria-selected="false">React</button>
<button role="tab" aria-selected="false">Cypress</button>
</div>
</body>
你可以通过调用 getByRole('tab', { selected: true }) 来获取“Native”选项卡。要了解有关选定状态以及哪些元素可以具有此状态的更多信息,请参阅 ARIA aria-selected。
busy
通过设置 busy: true 或 busy: false,您可以根据其
繁忙状态对返回的元素进行过滤。
<body>
<section>
<div role="alert" aria-busy="false">Login failed</div>
<div role="alert" aria-busy="true">Error: Loading message...</div>
</section>
</body>
你可以通过调用 getByRole('alert', { busy: false }) 来获取“登录失败”的警告。要了解有关忙碌状态的更多信息,请参阅 ARIA aria-busy 和 MDN aria-busy 属性。
checked
你可以通过设置checked: true或checked: false,按它们的选中状态过滤返回的元素。
<body>
<section>
<button role="checkbox" aria-checked="true">Sugar</button>
<button role="checkbox" aria-checked="false">Gummy bears</button>
<button role="checkbox" aria-checked="false">Whipped cream</button>
</section>
</body>
你可以通过调用 getByRole('checkbox', { checked: true }) 来获取 "Sugar" 选项。要了解更多关于选中状态以及哪些元素可以具有这种状态,请参见 ARIA aria-checked。
注意:复选框具有“混合”状态,这种状态既不是选中状态也不是未选中状态(详情见此)。
current
您可以通过设置 current: boolean | string 来根据当前状态过滤返回的元素。请注意,没有 aria-current 属性将匹配 current: false,因为 false 是 aria-current 的默认值。
<body>
<nav>
<a href="current/page" aria-current="page">👍</a>
<a href="another/page">👎</a>
</nav>
</body>
您可以通过调用 getByRole('link', { current: 'page' }) 来获取“👍”链接,通过调用 getByRole('link', { current: false }) 来获取“👎”链接。要了解有关当前状态的更多信息,请参阅 ARIA aria-current。
pressed
按钮可以具有按下状态。您可以通过设置 pressed: true 或 pressed: false 来根据按钮的按下状态过滤返回的元素。
<body>
<section>
<button aria-pressed="true">👍</button>
<button aria-pressed="false">👎</button>
</section>
</body>
你可以通过调用 getByRole('button', { pressed: true }) 来获取“👍”按钮。要了解有关按下状态的更多信息,请参阅 ARIA aria-pressed。
suggest
您可以将此值设置为false来禁用对特定查询的建议功能。
expanded
你可以通过设置expanded: true或expanded: false,根据它们的展开状态过滤返回的元素。
<body>
<nav>
<ul>
<li>
<a aria-expanded="false" aria-haspopup="true" href="..."
>Expandable Menu Item</a
>
<ul>
<li><a href="#">Submenu Item 1</a></li>
<li><a href="#">Submenu Item 1</a></li>
</ul>
</li>
<li><a href="#">Regular Menu Item</a></li>
</ul>
</nav>
</body>
你可以通过调用 getByRole('link', { expanded: false }) 获取“可扩展菜单项”链接。要了解有关扩展状态和哪些元素可以具有此状态的更多信息,请参阅 ARIA aria-expanded。
<div role="dialog">...</div>
<script>
import {screen} from '@testing-library/dom'
const dialogContainer = screen.getByRole('dialog');
</script>
queryFallbacks
默认情况下,假定每个元素都支持第一个角色,因此只能查询第一个角色。如果您想根据元素的备用角色来查询该元素,可以使用 queryFallbacks: true。
例如,getByRole('switch') 总是会匹配 <div role="switch checkbox" />,因为 'switch' 是第一个 role,而 getByRole('checkbox') 则不会。然而,getByRole('checkbox', { queryFallbacks: true }) 会启用所有备选 role,因此也会匹配到相同的元素。
在一个给定的环境中,元素不具有多个角色。它只有一个。从左到右评估属性中的多个角色,直到环境找到它理解的第一个角色。当引入新角色并且您想同时支持这些角色以及不理解该角色的旧环境时,这一点很有用(尚未)。
level
可以使用任何标题级别的 getByRole('heading') 或者使用 level 选项的 getByRole('heading', { level: 2 }) 来查询带有标题角色的元素。
level
选项查询heading
由语义 HTML 标题元素<h1>-<h6>
匹配 aria-level
角色与 或 属性。
<body>
<section>
<h1>Heading Level One</h1>
<h2>First Heading Level Two</h2>
<h3>Heading Level Three</h3>
<div role="heading" aria-level="2">Second Heading Level Two</div>
</section>
</body>
您可以使用 getByRole('heading', { level: 3 })
来查询三级标题。
getByRole('heading', {level: 1})
// <h1>Heading Level One</h1>
getAllByRole('heading', {level: 2})
// [
// <h2>First Heading Level Two</h2>,
// <div role="heading" aria-level="2">Second Heading Level Two</div>
// ]
虽然可以在元素上显式设置 role="heading" 和 aria-level 属性,但强烈建议使用语义 HTML 标题 <h1>-<h6>。
value
一个范围小部件可以通过任何值 getByRole('spinbutton') 或使用 level 选项 getByRole('spinbutton', { value: { now: 5, min: 0, max: 10, text: 'medium' } }) 来查询特定的值。
请注意,您不必在值中指定所有属性。指定一个子集就足够了,例如 getByRole('spinbutton', { value: { now: 5, text: 'medium' } })。
<body>
<section>
<button
role="spinbutton"
aria-valuenow="5"
aria-valuemin="0"
aria-valuemax="10"
aria-valuetext="medium"
>
Volume
</button>
<button
role="spinbutton"
aria-valuenow="3"
aria-valuemin="0"
aria-valuemax="10"
aria-valuetext="medium"
>
Pitch
</button>
</section>
</body>
您可以使用以下查询来查询特定的 spinbutton(s):
getByRole('spinbutton', {value: {now: 5}})
// <button>Volume</button>
getAllByRole('spinbutton', {value: {min: 0}})
// [
// <button>Volume</button>,
// <button>Pitch</button>
// ]
值中的每个指定属性都必须匹配。例如,如果你查询{value: {min: 0, now: 3}},那么aria-valuemin必须等于0,并且aria-valuenow必须等于3。
值选项只适用于某些角色(请检查下面的MDN链接页面以获取适用的角色)。 如果用于任何其他角色,则会引发错误。
description
对于具有相同角色但没有可访问名称但具有描述性的元素,您可以根据它们的可访问描述筛选返回的元素。
<body>
<ul>
<li role="alertdialog" aria-describedby="notification-id-1">
<div><button>Close</button></div>
<div id="notification-id-1">You have unread emails</div>
</li>
<li role="alertdialog" aria-describedby="notification-id-2">
<div><button>Close</button></div>
<div id="notification-id-2">Your session is about to expire</div>
</li>
</ul>
</body>
可以像这样查询特定元素
getByRole('alertdialog', {description: 'Your session is about to expire'})
性能
getByRole是最受欢迎的查询方式,因为它最接近用户体验,然而,它执行的计算可能很昂贵(特别是当DOM树很大时)。
通过将选项hidden设置为true,可以改进getByRole的性能,从而避免昂贵的可见性检查。请注意,这样做的话,不可访问的元素将包含在结果中。
另一种选择可能是用更简单的getByLabelText和getByText查询来替代getByRole,虽然这些查询速度更快,但不太稳健。