🗂

React Testing Library の user-event の version 13 と version 14 の違い

2023/01/11に公開約3,400字

はじめに

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

ログインするとコメントできます