Capybaraを使ったシステムテストで何かしらHTTPリクエストを送信したいときに色々ハマったのでメモしておきます📝
システムテストについてはこちら
リクエストを送る方法
以下を行うとシステムテスト内でリクエストを送信することができます。
current_driver
を:rack_test
に変更allow_forgery_protection
をfalse
に変更
上記を行うHelperみたいなのを用意してあげると便利そう(?)
module SendRequestHelper def send_request(method, path, params={}) use_rack_driver do disable_forgery_protection do page.driver.send(method, path, params) end end end private def use_rack_driver driver = Capybara.current_driver Capybara.current_driver = :rack_test yield Capybara.current_driver = driver end def disable_forgery_protection csrf_protection = ActionController::Base.allow_forgery_protection ActionController::Base.allow_forgery_protection = false yield ActionController::Base.allow_forgery_protection = csrf_protection end end # パラメータ付きで"/foo"にPOST send_request(:post, foo_path, { foo: 'foo'})
対応が必要な理由
current_driver
を:rack_test
に変更
デフォルトで利用されるCapybara::Selenium::Driver
だとpost
やget
といったリクエストを送信するようなメソッドが実装されていませんが、
しかしCapybara::RackTest::Driver
の場合はpost
やget
といったリクエストを送信するようなメソッドが実装されているので、current_driver
をリクエストを送信出来るCapybara::RackTest::Driver
に切り替えることで任意のタイミングでリクエストを送信出来るということですね。
※なお、認証状態といったものをRackTestとSelenium間で引き継ぐようなことは出来ないようです。(多分、Sessionが別になるため)
allow_forgery_protection
をfalse
に変更
直接リクエストを送る際にCSRFの保護が有効になっているとトークンがリクエストに含まれていない場合に、422 Unprocessable Entityが発生してしまいます。
そのためリクエスト送信時にはActionController::Base.allow_forgery_protection
をfalse
に変更しときます。
※Railsのテスト環境ではデフォルトで無効になっているのでやらなくても良いかも