RailsAPIモードを使っているときにrequest_specでログイン・ログアウトを実装

こんにちは!kossyです!



さて、今回はRailsAPIモードで認証機能周りのrequest_specでログイン・ログアウト状態を再現したい時の方法を
ブログに残してみたいと思います。




環境
Rails 5.1.6
Ruby 2.5.1
rspec 3.8.0
devise_token_auth 1.1.3




support直下にmoduleを定義したファイルを作成し、rails_helper.rbに読み込ませるだけ



supports直下にファイルを作成します。

spec/supports/authentication_helper.rb(名前は任意)

module AuthenticaitionHelper
  HTTP_HELPERS_TO_OVERRIDE = [:get, :post, :patch, :put, :delete]

  # ログイン状態にする
  def login(user)
    @user = user
    @auth_token = @user.create_new_auth_token # devise_token_authのメソッド 参考: https://www.rubydoc.info/gems/devise_token_auth/0.1.37/DeviseTokenAuth%2FConcerns%2FUser:create_new_auth_token
  end

  # ログアウトする
  def logout
    @user = nil
    @auth_token = nil
  end

  # 参考: https://gist.github.com/blaze182/3a59a6af8c6a7aaff7bf5f8078a5f2b6
  HTTP_HELPERS_TO_OVERRIDE.each do |helper| # 定数に対して繰り返し処理を実行
    define_method(helper) do |path, **args| # def get(path) のようなメソッドを動的に定義 
      add_auth_headers(args) # privateメソッドの呼び出し
      args == {} ? super(path) : super(path, **args) # argumentsが空ハッシュなら定義元のメソッドを実行、空でなければ定義元のメソッドをargumentsを引き連れて実行
    end
  end

  private
   # tokenをセットするprivateメソッド
    def add_auth_headers(args)
      return unless defined? @auth_token # @auth_tokenが定義されていなければ処理終了 https://www.xmisao.com/2014/03/30/checking-if-a-variable-is-defined.html
      args[:headers] ||= {} # args[:headers]がnilなら{}を代入
      args[:headers].merge!(@auth_token) # args[:headers]に@auth_tokenを代入
    end

end

作ったモジュールをrails_helper.rbで読み込む記述を追加します。

RSpec.configure do |config|

  省略

  Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } #support directoryをrequire
  config.include AuthenticationHelper, type: :request #type: :requestのときにRequestHelperをinclude
end


これで例えばFactoryBot等でuserを定義している場合、

user = FactoryBot.create :user
login user

等でログイン状態を再現できます。





参考にさせていただいた記事
type: :requestのテストでsign_in/sign_outする - Qiita