前提
Webアプリ開発をしています。
フロントエンドは TypeScript / React で書いています。
TDD 開発をしていて、Testing Library を使っています。
事の発端
フロントエンドでとあるテストを実行したとき・・・
Warning: An update to DefectCollectionPage 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
いつの間にか見慣れた警告。
言われた通りに act()
で囲っても警告は出たままだし・・・
未だに対応方法を理解していないのでお勉強タイムです!!
この警告なぁに?
警告の内容としては、テストが React コンポーネントの状態変更を正しく処理していないことを教えてくれているみたい。
act()
で囲うといいよって書いてあって、親切に Web ページも提供してくれてる。
ページを開くと、更新が終了している React の公式ドキュメントに遷移した。
親切に教えてくれた、更新が終了している React の公式ドキュメントを開き、
とりあえず act() の部分だけ読んでみる。
なんとなくの理解だけど、非同期処理もちゃんと終わらせた状態を作りたいよねって感じかな。
そしてこんな一文も。
You can use a library like React Testing Library to reduce the boilerplate code.
(React Testing Libraryのようなライブラリを使えば、定型的なコードを減らすことができる。)
あぁ・・・。その手があったか!!!
非同期処理を待機する
Testing Library で非同期処理を待機してくれそうなやつ。
公式ドキュメントに書いてあった・・・
findBy
は、要素が表示されることを期待しているけど、DOMへの変更がすぐには起こらないかもしれない場合に動作してくれる。
そして、findBy
は、getByクエリ
と waitFor
を組み合わせたものとのことです。
waitFor
は、findBy
ではカバーできない非同期操作の完了を待機できる。
タイムアウトするまで何度もコールバックを実行することができるらしい。
デフォルトのコールバックの間隔は 50ms。
デフォルトのタイムアウトは 1000ms。
結論
act() で囲ってねって言われたら、findBy
か waitFor
を使うことを検討します。
今回やりたかったテストでは DOM 要素を取得するものだったので、findBy
で解決します!
おまけ
waitForElementToBeRemoved
ってのもあるらしい。
DOMから要素が削除されるのを待つことができるんだって。