フューチャー技術ブログ

Playwrightでなぜかボタンにヒットしない

getByRole()でボタンがヒットしないです、という相談を受けて調べた内容のメモです。次のようなHTMLになっていました。

<label for="my-button">ラベル</label>
<button id="my-button">
ボタンキャプション
</button>

ボタンに対して、ラベルがついていない場合は、<button>タグの中のキャプション(ここでは「ボタンキャプション」という文字列)を指定して、getByRole('button', {name: 'ボタンキャプション'})でヒットするのですが、上記のようなラベルがついていると、そちらのキャプションにはヒットしなくなって、ラベルの方にのみヒットするようになります。

test('has title', async ({ page }) => {
await page.goto('http://localhost:5173/');
// ヒットする
await page.getByRole('button', {name: 'ボタンキャプション'}).click();
// ヒットしない
await page.getByRole('button', {name: 'ラベル'}).click();
await expect(page.getByRole("status")).toHaveText('1')
});

W3Cのアクセシビリティの実践的ガイドのボタンのページを見ると次のように書かれています。

The button has an accessible label. By default, the accessible name is computed from any text content inside the button element. However, it can also be provided with aria-labelledby or aria-label.

訳: ボタンはアクセス可能なラベルを持っています。デフォルトではボタン要素の中のテキストコンテンツから算出されます。しかし、aria-labelledbyやaria-labelでも提供できます。

ということで、ボタンキャプションはラベルがない場合にのみ有効なデフォルト値ということで、こちらはバグなどではなく、アクセシビリティのガイドラインに従った動きをしているということがわかります。