React Testing Library の user-event の version 13 と version 14 の違い
はじめに
React Testing Library でコンポーネントのテストコードを書くときにユーザー操作に関するインタラクションテストを書く場合は@testing-library/user-event
を使用してテストコードを書くことが推奨されています。Why you should test with user-event(なぜあなたは user-event でテストを書くべきなのか?)で説明されているようにユーザーとのインタラクションに正しく反応しているかどうかをテストするためには、@testing-library/user-event
の方が優れているからです。そんなReactのテストで必須とも言える@testing-library/user-event
ですが、ver13系とver14系で大きくテストコードの書き方が異なるようになったのでこれからその違いに関して紹介します。
使用技術
- "react": "18.2.0",
- "react-dom": "18.2.0",
- “jest”: “^28.1.3"
- “@testing-library/react”: “^13.3.0",
- “@testing-library/user-event”: “^14.4.3",
※ @testing-library/react
の v13 で破壊的な変更が起きており、react の v17 との互換性がなくなっていることでエラーが出現するので注意してください。詳しくは react-testing-library v13 から React v17 のサポートされないことに起因するエラーについて の記事が参考になると思います。
user-event version13 までの書き方
userEvent の 各種関数の返り値
userEvent のEvent経由でアクセス可能な関数の返り値が void
を返していた
// user-event version13までの場合
userEvent.tab() : () => void
Space Keyboard 押下の判定
keyboard の引数に "{space}"
を指定していた
userEvent.keyboard("{space}");
pointer-events : none が付与されてるテストコードの書き方
第三引数に skipPointerEventsCheck: true
を指定していた
userEvent.click(screen.getByRole("button"), undefined, { skipPointerEventsCheck: true });
user-event version14 の書き方
userEvent の 各種関数の返り値
userEvent のEvent経由でアクセス可能な関数の返り値が Promise<void>
を返す様になった
// user-event version14 の場合
userEvent.tab() : () => Promise<void>
実際に user-event の公式ドキュメントのリファレンスコードを確認すると、テストコードのサンプルコードが async await を用いたコードに変化している
test('trigger some awesome feature when clicking the button', async () => {
const user = userEvent.setup()
render(<MyComponent />)
await user.click(screen.getByRole('button', {name: /click me!/i}))
// ...assertions...
})
上記サンプルコードを確認すると、userEvent.setup()
というのが追加されています。これは@testing-library/user-event
の v14 から setup API が追加されたからです。@testing-library/user-event
の v13 までのように userEvent.click()
のような使い方もできますが、 userEvent.setup()
を使うことが公式ドキュメントでは推奨されています。
Space Keyboard 押下の判定
keyboard の引数に " "
を指定する様になった
await user.keyboard(" ");
pointer-events : none が付与されてるテストコードの書き方
setup の第一引数に { pointerEventsCheck: 0 }
を指定する
const user = userEvent.setup({ pointerEventsCheck: 0 });
await user.click(screen.getByRole("button"));
まとめ
ですので@testing-library/user-event
のversion13仕様で書かれていたコードは以下の具体例の様にテストコードを修正する必要があります。
test("Tabキーでフォーカスできないこと", () => {
render(<Disabled />);
userEvent.tab();
expect(screen.getByRole("textbox")).not.toHaveFocus();
});
↓
test("Tabキーでフォーカスできないこと", async () => {
render(<Disabled />);
await userEvent.tab();
expect(screen.getByRole("textbox")).not.toHaveFocus();
});
さいごに
上記変更内容を踏まえると、現在のプロジェクトで@testing-library/user-event
のversion13を使用しており、@testing-library/user-event
のversionを14系にバージョンアップしようと考え、安易にバージョンアップしてしまうとテストコードが多く書かれているプロジェクトの場合は、変更しないといけない箇所は非常に多くなると予想できます。変更内容が分かってしまえば修正自体はそんなに難しくないですが、自分は最初「なんでテストが落ちているのか?」が分からずに修正に少し時間を食ったので、同じような状況の人を救えたら嬉しいです。
Discussion