React Testing Library使用時、よくお世話になるuserEventですが、v14になって破壊的変更が入り、使用感が変わってました!
個人的には「いいな!」と思える変更でした🙆♀️
userEventってなに?
テスト上で、ユーザー操作によるシステム動作をシミュレートするライブラリです。
同様の機能を持つものにfireEventがありますが、userEventの方がより実際の動作を再現するようになってます(詳細)。
そのため、基本的にはfireEventよりuserEventを使用することが推奨されてます。
v14の変更内容
破壊的変更が入ったのですが、その中でも個人的に大きいなと思った内容を抜粋してます。
- APIが常にPromiseを返す
userEvent.click
、userEvent.hover
等からinit
パラメータを除外- その他:https://github.com/testing-library/user-event/releases/tag/v14.0.0
これらの変更が入ったことにより、使用方法にも変化があります。
v13, v14の使用方法の違い
v13までの使い方
test('click', () => {
render(<MyButton />)
userEvent.click(screen.getByRole('button'))
// ...
})
v14の使い方
test('click', async () => {
const user = userEvent.setup() // まずsetup
render(<MyButton />)
await user.click(screen.getByRole('button'))
// ...
})
けっこう変わってますよね、、!
個人的には、
- user.clickといった表現を可能にし、シミュレートさせるユーザー動作がイメージしやすい
- 全てのAPIがPromiseを返すようになり、シミュレート処理の完了後に以降の動作が実施される保証ができるのが嬉しい
と思いました。
setupするの面倒じゃないか・・・?と思ったら
公式にも書いてありますが、setupを共通関数化すると良いと思います。
userEventのsetupと、コンポーネントのrenderを行う関数を用意しておいて(↓)、
export function setup(jsx: JSX.Element) {
return {
user: userEvent.setup(),
...render(jsx),
}
}
各テストファイルではそれをインポートして使用する(↓)イメージです。
import React from 'react'
import {screen} from '@testing-library/react'
import {setup} from '../userEvent'
test('click', async () => {
const {user} = setup(<MyButton />)
await user.click(screen.getByRole('button'))
// ...
})
こうすると毎度setupする煩雑さも減るんじゃないでしょうか👀✨