React Testing Library で Material UI の TextField を取得する方法
はじめに
@testing-library/react
で Material UI の TextField
を取得する際、 label
が設定されていても getByRole
や getByLabelText
で取得したときに label
が正しく取得できません。
調べると inputProps
を使って data-test-id
を使う方法も出てきますが、テストのために data-test-id
を指定するのは極力避けたく、他の方法を調査していました。
結論
-
label
を設定する - 一見不要でも
id
を設定する -
getByRole
またはgetByLabelText
で取得する- 一般的には
getByRole
が推奨されていますがtype="password
の場合は使えません
- 一般的には
解説
Material UI の TextField
コンポーネントを以下のように配置した場合
<TextField id="email" name="email" label="メールアドレス" />
実際には以下の DOM として展開されます。
<div class="MuiFormControl-root MuiTextField-root">
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated"
data-shrink="false"
for="email"
id="email-label"
>
メールアドレス
</label>
<div class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-formControl MuiInput-formControl">
<input
aria-invalid="false"
class="MuiInputBase-input MuiInput-input"
id="email"
name="email"
type="text"
value=""
/>
</div>
</div>
id="email"
を消すと以下のようになります。
<div class="MuiFormControl-root MuiTextField-root">
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated"
data-shrink="false"
>
メールアドレス
</label>
<div class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-formControl MuiInput-formControl">
<input
aria-invalid="false"
class="MuiInputBase-input MuiInput-input"
name="email"
type="text"
value=""
/>
</div>
</div>
ここで注目したいのは <label>
の for="email"
という箇所です。
<label>
タグには for
に <input>
の id
を指定してあげるとその <input>
に関連づけられるという仕様があります。
Material UI の TextField
の場合、 id
を設定すると for
を指定してくれるようです。
よく見たらドキュメントの隅のほうに書いてありました。
If you are using the TextField component, you just have to provide a unique id.
TextField
を使う場合、一見不要でも id
をつけるのは癖にしたほうがよさそうです。
余談
@testing-library/react
は最初はとっつきづらくて enzyme
使いたい〜〜となってしまいますが、慣れてくるとブラウザ上で操作するように直感的にテストが書けるなと感じてきました。
以下の記事にベストプラクティスが沢山まとめられているので、 @testing-library/react
を使用している方は一読してみるとよさそうです。
Discussion