ByRole
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
)的元素。預設角色會被納入考量,例如 <button />
具有 button
角色,而無需明確設定 role
屬性。您可以在此處查看 具有其預設和所需角色的 HTML 元素表格。
請注意,設定與隱含 ARIA 語意相符的 role
和/或 aria-*
屬性是不必要的,而且不建議這麼做,因為這些屬性已經由瀏覽器設定,而且我們不得以與描述的語意衝突的方式使用 role
和 aria-*
屬性。例如,button
元素不能具有 heading
的 role
屬性,因為 button
元素具有與 heading
角色衝突的預設特性。
角色會以字串相等的方式逐字比對,而不會從 ARIA 角色階層繼承。因此,查詢像
checkbox
這樣的超類別角色不會包含像switch
這樣的子類別角色的元素。
您可以透過它們的可存取名稱或描述來查詢返回的元素。可存取名稱在簡單的情況下等於表單元素的標籤,或按鈕的文字內容,或 aria-label
屬性的值。如果呈現的內容上存在多個具有相同角色的元素,則可以使用它來查詢特定元素。如需深入的指南,請查看 TPGi 的「什麼是可存取名稱?」。如果您只使用 getByText('The name')
查詢單個元素,通常最好使用 getByRole(expectedRole, { name: 'The name' })
。可存取名稱查詢不會取代其他查詢,例如 *ByAlt
或 *ByTitle
。雖然可存取名稱可能等於這些屬性,但它不會取代這些屬性的功能。例如,如果 fancy.jpg
無法載入,則 <img aria-label="fancy image" src="fancy.jpg" />
將會針對 getByRole('img', { name: 'fancy image' })
返回。您是否要在測試中斷言此功能取決於您。
遺憾的是,規格定義 <input type="password" />
沒有隱含角色。這表示為了查詢此類型的元素,我們必須退而求其次使用較弱的查詢,例如 ByLabelText
。
選項
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')
只會返回「關閉對話方塊」按鈕。若要對「開啟對話方塊」按鈕進行斷言,您需要使用 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 })
來取得「原生」索引標籤。若要進一步了解選取狀態以及哪些元素可以具有此狀態,請參閱 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 })
來取得「糖」選項。若要進一步了解勾選狀態以及哪些元素可以具有此狀態,請參閱 ARIA aria-checked
。
注意
核取方塊具有「混合」狀態,既不視為已勾選也不視為未勾選(詳細資訊請參閱 此處)。
current
您可以透過設定 current: boolean | string
來依其目前狀態篩選返回的元素。請注意,由於 false
是 aria-current
的預設值,因此沒有 aria-current
屬性會符合 current: false
。
例如,在
<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
,來停用 針對特定查詢擲回建議 的能力。
將此值設定為 true
將會針對特定查詢擲回建議。
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>
- 原生
- React
- Angular
- Cypress
import {screen} from '@testing-library/dom'
const dialogContainer = screen.getByRole('dialog')
import {render, screen} from '@testing-library/react'
render(<MyComponent />)
const dialogContainer = screen.getByRole('dialog')
import {render, screen} from '@testing-library/angular'
await render(MyComponent)
const dialogContainer = screen.getByRole('dialog')
cy.findByRole('dialog').should('exist')
queryFallbacks
根據預設,假設每個元素的第一個角色都受支援,因此只能查詢第一個角色。如果您需要改為依任何其回退角色查詢元素,您可以使用 queryFallbacks: true
。
例如,getByRole('switch')
會永遠比對 <div role="switch checkbox" />
,因為它是第一個角色,而 getByRole('checkbox')
則不會。但是,getByRole('checkbox', { queryFallbacks: true })
會啟用所有回退角色,因此會比對相同的元素。
元素在給定環境中沒有多個角色。它只有一個。屬性中的多個角色會從左到右評估,直到環境找到它理解的第一個角色。當引入新角色時,並且您想要開始支援這些角色以及不理解該角色(尚未)的舊環境時,這非常有用。
level
可以使用任何標題層級 getByRole('heading')
或使用 level
選項 getByRole('heading', { level: 2 })
來查詢具有 heading
角色的元素。
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 })
來查詢 Heading Level Three
標題。
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>
。
若要深入了解 aria-level
屬性,請參閱 ARIA aria-level
。
level
選項僅適用於heading
角色。若用於其他任何角色,則會拋出錯誤。
value
範圍小工具可以使用任何值 getByRole('spinbutton')
查詢,也可以使用 level
選項指定特定值,例如 getByRole('spinbutton', { value: { now: 5, min: 0, max: 10, text: 'medium' } })
。
請注意,您不必指定 value
中的所有屬性。指定子集就足夠了,例如 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),
getByRole('spinbutton', {value: {now: 5}})
// <button>Volume</button>
getAllByRole('spinbutton', {value: {min: 0}})
// [
// <button>Volume</button>,
// <button>Pitch</button>
// ]
value
中每個指定的屬性都必須符合。例如,如果您查詢{value: {min: 0, now: 3}}
,則aria-valuemin
必須等於 0 且aria-valuenow
必須等於 3。
value
選項僅適用於某些角色(請查看下方連結的 MDN 頁面以了解適用角色)。若用於其他任何角色,則會拋出錯誤。
若要深入了解 aria-value*
屬性,請參閱 MDN aria-valuemin
、MDN aria-valuemax
、MDN aria-valuenow
、MDN aria-valuetext
。
description
您可以根據元素的無障礙描述來篩選返回的元素。這種情況適用於當您有多個具有相同角色且沒有無障礙名稱但有描述的元素時。
例如,具有 alertdialog 角色的元素就是這種情況,其中 aria-describedby
屬性用於描述元素的內容。
例如,在
<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
的效能,從而避免耗費資源的可見性檢查。請注意,這樣做會將無法訪問的元素包含在結果中。
另一種選擇可能是將 getByRole
替換為更簡單的 getByLabelText
和 getByText
查詢,這些查詢速度明顯更快,但健壯性較低。