React Hook Form と Testing-Library を使ったときの act ワーニングを解決する
に公開背景
React Hook Form を使ったコンポーネントをレンダリングしてある要素にチェックが入っているか確認するだけのテストで、テスト自体は通過するものの以下のようなワーニングが表示されていた
Warning: An update to ThreadForm inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
at ThreadForm (/Users/oz0012/ghq/github.com/opz-dev/sns/src/app/(main)/forum/[threadCategory]/_components/thread-form.tsx:39:23)
解決法
コンポーネントの要素がレンダリングされるのをまつ。
test(‘デフォルトでチェックが入っている’, ()=>{
render(<App />)
// コンポーネントのなんらかの要素がレンダリングされるのを待つ
expect(await screen.findByText("SUBMIT")).toBeInTheDocument()
// 実際に行いたいテスト
expect(screen.getByRole(“checkbox”, {name: “consent"})).toBeChecked()
})
補足
今回の Warning は react-hook-form がレンダリング時に初回のバリデーションを非同期で行うため、コンポーネントの状態が更新されることで表示される。
act でラップことでも Warning 自体は消すことができるが react-hook-form 以外による意図しない非同期処理があったとしてもメッセージを抑制してしまうため、非推奨。
これに限らず基本的に act でラップしていたら危険信号なので注意。