役割によるクエリ (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 /> は `role` 属性を明示的に設定しなくても `button` の役割を持ちます。 デフォルトおよび推奨される役割を持つHTML要素の表はこちらをご覧ください。
暗黙的なARIAセマンティクスと一致する `role` 属性や `aria-*` 属性を設定することは不要であり、**推奨されません**。これらのプロパティはブラウザによって既に設定されているため、記述されているセマンティクスと矛盾する形で `role` 属性や `aria-*` 属性を使用しないでください。たとえば、`button` 要素は `heading` の `role` 属性を持つことができません。`button` 要素には `heading` の役割と矛盾するデフォルトの特性があるためです。
役割は、ARIA役割階層を継承することなく、文字列の完全一致によって照合されます。そのため、`checkbox` のようなスーパークラスの役割をクエリしても、`switch` のようなサブクラスの役割を持つ要素は含まれません。
返された要素は、アクセシブルな名前または説明によってクエリできます。アクセシブルな名前は、単純なケースでは、フォーム要素のラベル、ボタンのテキストコンテンツ、`aria-label` 属性の値などに等しくなります。レンダリングされたコンテンツに同じ役割を持つ複数の要素が存在する場合、特定の要素をクエリするために使用できます。詳細なガイドについては、TPGiの"アクセシブルな名前とは?"をご覧ください。 `getByText('名前')` で単一の要素のみをクエリする場合は、多くの場合 `getByRole(期待される役割, { name: '名前' })` を使用することをお勧めします。アクセシブルな名前のクエリは、`*ByAlt` や `*ByTitle` などの他のクエリを置き換えるものではありません。アクセシブルな名前はこれらの属性と等しくなる場合がありますが、これらの属性の機能を置き換えるものではありません。たとえば、`<img aria-label="派手な画像" src="fancy.jpg" />` は `getByRole('img', { name: '派手な画像' })` で返されます。ただし、`fancy.jpg` が読み込めない場合、画像は説明を表示しません。この機能をテストでアサートするかどうかは、ユーザー次第です。
残念ながら、仕様では `<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` を設定することで、返される要素を現在の状態によってフィルタリングできます。 `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` に設定することで、特定のクエリに対して候補を提示する機能を無効にできます。
この値を `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` 
`heading` 役割を持つ要素は、任意の見出しレベル `getByRole('heading')` または `level` オプションを使用して特定の見出しレベル `getByRole('heading', { level: 2 })` でクエリできます。
level オプションは、セマンティックHTMLの見出し要素 <h1>-<h6> で決定される、または aria-level 属性と一致する、指定されたレベルに一致する heading ロールの要素をクエリします。
以下の例では、
<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>
以下のクエリを使用して、特定のスピンボタンをクエリできます。
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
同じロールを持つ要素が複数あり、アクセシブルな名前はないが説明がある場合、アクセシブルな説明 で返される要素をフィルタリングできます。
これは、aria-describedby 属性を使用して要素の内容を記述する、alertdialog ロールの要素の場合です。
たとえば、
<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 ツリーでは)コストがかかる可能性があります。
テストのパフォーマンスが懸念される場合は、この信頼性の一部をパフォーマンスの向上と引き換えることが望ましい場合があります。
getByRole のパフォーマンスは、オプション hidden を true に設定することで向上させることができ、それによってコストのかかる可視性チェックを回避できます。ただし、そうすることで、アクセスできない要素が結果に含まれるようになることに注意してください。
別のオプションは、getByRole を、より単純で大幅に高速ですが、堅牢性が低い代替手段である getByLabelText および getByText クエリに置き換えることです。