はじめに
無限スクロールをreact-intersection-observerで実装して、モックを実装するときに詰まったので投稿します。
問題
vitestでコンポーネントテストを書いている中でタイトルのエラーが表示されました。
どうやら、jsdomではIntersectionObserverを直接扱えないようです。
そこでIntersectionObserverのモックを作成したり、無限スクロールのカスタムフックのモックを作成したのですが、交差後のテストがなかなか通りませんでした。
解決方法
react-intersection-observerのドキュメントを見ると、react-intersection-observer/test-utilsというテストツールがあるようです。
さらに、
If you're running Vitest with globals, then it'll automatically mock the IntersectionObserver, just like running with Jest. Otherwise, you'll need to manually setup/reset the mocking in either the individual tests, or a setup file.
と記述されており、importするだけで自動でモックしてくれるようです。
// IntersectionObserverをモック化
import { mockIsIntersecting } from 'react-intersection-observer/test-utils';
it('最下部までスクロールすると投稿が追加で表示されること', async () => {
const postNum = POSTS_PER_PAGE + 1;
renderTopPage(postNum);
const bottomBoundary = screen.getByTestId('bottom-boundary');
// 最下部の要素を「画面内に入った」状態にする。
mockIsIntersecting(bottomBoundary, true);
expect(await screen.findByRole('heading'
, { level: 3, name: `テスト投稿${postNum}` })).toBeVisible();
});
おわりに
そもそも、jsdomではなく、vitestのブラウザモードを利用するべきかもしれません。
[!TIP] Consider using Vitest Browser Mode instead of jsdom or happy-dom. This option allows you to utilize the real browser implementation and triggers correctly when scrolling or adding elements to the viewport. You can skip the react-intersection-observer/test-utils, or use it as needed.
参考