🔔

Next.jsにnext/testmodeという概念が出現しMSW x Playwrightのテストがやりやすくなりそう

2023/08/15に公開1

2023年8月15日にリリースされた Next.js v13.4.16から
next/experimental/playwright
next/experimental/playwright/msw
が登場してテストがしやすくなりそう。というお話です!

前提条件

今回お話するのは、Next.js の開発サーバーに対してMSWによりAPI通信をモックしてPlaywrightで行うブラウザテストのことをお話します

これまでは?

Page RouterかつCSRに関して言えば、MSWでモックすることは可能でした。exampleとしてすでに公式が提供しているので、これをベースにセットアップすれば可能です

https://github.com/vercel/next.js/tree/canary/examples/with-msw

現状の課題

Page Router

CSRの場合はブラウザ上のservice worker経由でmswが実行されています。なのでmswのserver.useを使うにはそこそこ工夫が必要です。

有志が作成したリポジトリの実装を見ると色々頑張ってるのがわかります

https://github.com/valendres/playwright-msw/tree/main/packages/playwright-msw

自分はPlaywrightの手動クッキー追加機能を工夫してmswで読み取っていい感じにハンドリングさせるようにしています
https://playwright.dev/docs/api/class-browsercontext#browser-context-add-cookies

ただ単にjestでやってるような脳死でtestケースごとにserver.useを使うだけ、ということは難しいです

App Router

App Routerに関してはもっと根深い問題があります。詳しくは以下のMSWのIssueにありますが、超絶意訳すると、Next.jsの内部実装によってMSW側からじゃどうやってもモックできねぇ!!みたいなことを言っています。

https://github.com/mswjs/msw/issues/1644

何が起きたか

上記のissueを受けてv13.4.16から next.js側がmswを使っていい感じにモックしてくれる機能を提供するようになりました!!

next/experimental/testmode/playwright
および
next/experimental/testmode/playwright/msw
からimportし、利用可能です

個人的にここらへんのモックを今後どうしていこうかとうんうん悩んでいたのでこういった機能を提供してくれたのは非常に嬉しいです😭

実装されたPRは以下になります
https://github.com/vercel/next.js/pull/52520

まだExperimentalなのですが以下のような感じでmswを使ったモックサーバー経由でPlaywrightテストが実行可能です。以下は早速遊んでみたときのコードなのですが、確かにちゃんとモックされていました

https://github.com/u-yas/test-playwright/blob/main/tests/example-msw.spec.ts

※ただ、テストケースを回していると前のtestでオーバーライドしたresponseがリセットされていない?みたいな状態になったりしてて、ちょっと上手く動かせなかったです。単にコードがだめだったからなのかもしれないですが・・・まぁexperimentalですので長い目で見守りましょう!

これによってRSCでもtestケースごとにmsw.useを使ってresponseを変更し、エラーレスポンスの場合だったり、意図しないresponseだった場合のテストも行うことが可能になります!

※現在(2023年8月15日)のReact Testing LibraryではRSCでテストを行うことはできません(多分、react本家のreact-dom/test-utilsパッケージをいじくり回したらできそうだなとは思います)
つまり実質jestなどではRSCのコンポーネントをテストすることができず、コンポーネント実装を工夫する必要などがあります。

https://github.com/testing-library/react-testing-library/issues/1209

参考: RSCでのテストの考え方について良い解説がありました!
https://speakerdeck.com/uhyo/app-routershi-dai-nodetaqu-de-akitekutiya?slide=50

終わりに

個人的にPlaywrightのテストが大好きでこんな記事を書いちゃうくらいjest-domが嫌いなのですが、Next.jsがmswとplaywrightとの連携を考えてくれてて良かったなって思っています。Playwright大好き!!!ブラウザテスト最高!!!!

RSC時代のtest runnerについてのdiscussionがnext.jsリポジトリに上がっているので、ご意見がある人は是非コメントしてみてください
https://github.com/vercel/next.js/discussions/53409

Next.jsは今後testmodeという概念を出してテストutilな機能をたくさん出していくんですかね?まだまだ始まったばかりなので今後の動向に注目ですね!

では!

参考: next/experimental/testmode/playwrightのドキュメント
https://github.com/vercel/next.js/tree/canary/packages/next/src/experimental/testmode/playwright

Discussion

RenoaRenoa

ついにApp RouterでもMSWが使えるように…。

「ただ、テストケースを回していると前のtestでオーバーライドしたresponseがリセットされていない?みたいな状態になったり」
環境は違いますが、Next.js+Vitestの環境で、手動でMockした関数の戻値がリセットされない、という現象に私も出くわしたので、何か上手く動いてない部分があるかもしれませんね…。