LoginSignup
12
6

More than 5 years have passed since last update.

RSpecのfeatureテストでsessionを扱う方法

Last updated at Posted at 2019-07-08

環境

  • macOS 10.14.5
  • ruby 2.5.5
  • rails 5.2.3

はじめに

RailsチュートリアルのテストをRSpecで書いていた時にあることに気づきました。

featureテストではsessionが使えない!?

Railsチュートリアル8章のテストでis_logged_in?というユーザーがログイン中かどうかを論理値で返すテスト用ヘルパーを紹介していました。

test/test_helper.rb
# テストユーザーがログイン中の場合にtrueを返す
  def is_logged_in?
    !session[:user_id].nil?
  end

なので同様にspec/support/test_helper.rbに記述してfeatureテストでヘルパーを使用した。
(ヘルパーを定義する方法はこちらを見るとよいと思います
マクロ(ヘルパーメソッド)を定義してフィーチャースペックのユーザー切替えを楽に行う
)

spec/support/test_helper.rb
module TestHelper
  def is_logged_in?
    !session[:user_id].nil?
  end
end
spec/features/users_signup_spec.rb
require 'rails_helper'

RSpec.feature "UsersSignups", type: :feature do

  feature "valid signup information" do
    before do
      visit signup_path
      fill_in "Name", with: "Example User"
      fill_in "Email", with: "user@example.com"
      fill_in "Password", with: "password"
      fill_in "Confirmation", with: "password"
    end

    scenario "add users count" do
      expect {
        click_button "Create my account"
        expect(page).to have_current_path user_path(User.last)
      }.to change(User, :count).by(1)
    end

    scenario "show flash message" do
      click_button "Create my account"
      expect(page).to have_content "Welcome to the Sample App!"
      visit current_path
      expect(page).to_not have_content "Welcome to the Sample App!"
    end

    scenario "login created user" do
      click_button "Create my account"
      expect(is_logged_in?).to be_truthy  #### ここで使用 ####
    end
  end

  feature "invalid signup information" do
    before do
      visit signup_path
      fill_in "Name", with: ""
      fill_in "Email", with: "user@invalid"
      fill_in "Password", with: "foo"
      fill_in "Confirmation", with: "bar"
    end

    scenario "no difference users count" do
      expect {
        click_button "Create my account"
        expect(page).to have_current_path signup_path
      }.to_not change(User, :count)
    end

    scenario "is show error messages" do
      click_button "Create my account"
      expect(page).to have_content "Name can't be blank"
      expect(page).to have_content "Email is invalid"
      expect(page).to have_content "Password is too short"
      expect(page).to have_content "Password confirmation doesn't match Password"
    end
  end
end

するとこんなエラーが、、、

1) UsersSignups valid signup information login created user
     Failure/Error: !session[:user_id].nil?

     NameError:
       undefined local variable or method `session' for #<RSpec::ExampleGroups::UsersSignups::ValidSignupInformation:0x00007fe38a4a3e20>
     # ./spec/support/login_macros.rb:3:in `is_logged_in?'
     # ./spec/features/users_signup_spec.rb:30:in `block (3 levels) in <top (required)>'
     # -e:1:in `<main>'

解決策

どうやら調べてみるとfeatureテスト内ではsesssionが扱えないようで、コントローラーテスト内では使えるみたい。
でもどうにかfeatureテスト内でこのヘルパーを使えるようにする方法はないかと調べていたところある記事を見つけました。
Rails feature testing with logged in user (undefined method 'session')

'rack_session_access'というgemを使うとfeatureテスト内でもsessionを参照したり、変更したりできるみたいなのでgemのREADMEを参考にセットアップしました。

Gemfile
gem 'rack_session_access' # 追加
$ bundle install   # gemをインストール
config/environments/test.rb
Rails.application.configure do
  :
  :
  config.middleware.use RackSessionAccess::Middleware  # 追加
end
spec/spec_helper.rb
require "rack_session_access/capybara"   # 追加

このgemを使うとsessionに値を挿入することもできるらしいが今回は値が入っているかどうかを調べたいだけなので以下のメソッドを記述してRailsチュートリアルに習って論理値を反転。

spec/support/test_helper.rb
module TestHelper
  def is_logged_in?
    !page.get_rack_session_key('user_id').nil?   # 変更
  end
end

はじめはget_rack_session_key(:user_id)と修正したがダメだったのでREADEMEを見ると、文字列('user_id')を渡さなきゃいけないらしい

まとめ

'rack_session_access'gemを使うとfeatureスペックでもsessionを扱える!

しかし頻繁にsessionの操作をfeatureスペック内で行わないようなら、ログインしているかどうかをテストする方法は他にもいくらでもあるのでgemをわざわざ入れる必要はないかも。。

12
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
6