テスト環境でcsrf_token(csrf_meta_tags)が出力されない問題への対処法(RSpec)
【結論】
・RailsにはCSRF保護の仕組みがデフォルトで備わっている
・しかし、CSRF保護はテスト環境ではオフになっており、csrf_tokenがHTMLに埋め込まれない為、それが原因でテストが通らない場合がある
・その場合は、CSRF保護をテスト環境でも有効にするか、該当箇所のコードをエラーハンドリングする必要がある
【目次】
【本題】
RailsのCSRF保護
前回の記事で詳しく書きましたが、RailsにはCSRF保護の仕組みがデフォルトで備わっています。
CSRF保護が有効になっていると、以下の様にheadタグにcsrf_tokenが記述されます。
フォーム送信時に、このセキュリティタグも一緒に送信し、ページの正当性を判断しています。
テスト環境ではcsrf_token(csrf_meta_tags)が出力されない
しかし、このcsrf_tokenですが、テスト環境では出力されません。
その理由はconfig/environments/test.rb
の以下の記述にあります。
# Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false
この記述により、CSRF保護はテスト環境ではオフになっています。
これにより、HTMLにcsrf_tokenが埋め込まれなくなります。
その為、もしAjax通信の為にcsrf_tokenをJavaScirptで取得している場合、そのコードがエラーになってしまいます。
対策
対策としては、先ほどのコードをコメントアウトして、CSRF保護をオンにする方法があります。
しかし、テスト全体への影響範囲が大きい為、正常にテストが動作しなくなる懸念があります。
もし、JavaScirptのコードだけがエラーになっているのであれば、その部分をエラーハンドリング して防ぐ方法もあります。
JavaScriptでよく使用されるのはtry~catch文
です。
try{ var csrf_token = document.getElementsByName( 'csrf-token' ).item(0).content; } catch(e){ // error handling }
これで、JavaScirptでエラーは発生せず、正常にテストを実行することが出来ます。
参考情報
Rails4.2でcsrf_tokenが表示されない環境があって調べた - mokokko desu
ruby on rails - phantomjs 2.0.0以降にするとpoltergeistでstatus_codeが304になることがある - スタック・オーバーフロー