ドロップダウンには複数の<option>
を選択できるパターンが存在する。これをテストする例は探しても中々出てこないため、記載する。
複数要素は<select>
にmultiple
属性を設定することで実現できる。
export default function StayExtensionMultipleSelectBox() { return ( // multipleを追加した <select multiple> <option value="none">宿泊なし</option> <option value="previous">前泊のみ</option> <option value="next">後泊のみ</option> <option value="both">前泊と後泊</option> </select> ); }
テストする場合、<option>
を複数選択する必要がある。実際はCtrlキーやCommandキーを押しながら複数の<option>
をクリックするが、Testing Libraryではこの操作を再現するのは難しい。そこで、公式のselectOptions
1を使ってテストを行う。selectOptions
の第二引数に配列で複数の<option>
のラベルまたはvalueを渡す。すると、選択要素を特定してくれる。
複数の値が選択状態であることを確かめる場合、toHaveValue
の引数を配列にし、選択している値を配列に全て含めれば良い。
実際のテストケースは次のようになる。
it("複数の選択肢を選択したときも対応するvalueが選択状態になる", async () => { // イベント検知のセットアップ const event = userEvent.setup(); const content = render(<StayExtensionMultipleSelectBox />); // 前泊と後泊を選択 await event.selectOptions(content.getByRole("listbox"), [ "前泊のみ", "後泊のみ", ]); // 前泊と後泊が選択されている expect(content.getByRole("listbox")).toHaveValue(["previous", "next"]); });
注意点として、<select>
要素の特定方法がmultiple
属性の有無で変わる点である。MDN2にも次のように解説されている。
combobox with no multiple attribute and no size attribute greater than 1, otherwise listbox
multiple属性がなく、かつsize
属性が1以下ならcombobox
を指定する。それ以外はlistbox
を指定する。size
は選択肢をいくつ表示するか?を指定する属性である。
multipleがない場合、デフォルトで0が指定される3。よって、大半の場合はcombobox
を使う。複数の選択肢を選択させる場合はlistbox
を使う。この点を見落とすと「<select>
が存在するのにクエリで見つけられない!」という事態にはまってしまう。
combobox
の場合は次のようにテストを記載する。
it("オプションラベルを選択すると対応するvalueが選択状態になる", async () => { // イベント検知のセットアップ const event = userEvent.setup(); const content = render(<StayExtensionSelectBox />); // オプションを全て取得 const options = content.getAllByRole("option"); // 前泊を選択 await event.selectOptions(content.getByRole("combobox"), [options[1]]); // 前泊が選択されている expect(content.getByRole("combobox")).toHaveValue("previous"); });