Deviseモデルのユーザーがいて、ロール:adminを持つユーザーのみが特定のURLの表示を許可されている場合、RSpec統合テストを作成して、そのURLのステータスが200を返すことを確認するにはどうすればよいですか?
def login(user)
post user_session_path, :email => user.email, :password => 'password'
end
これはこの質問への回答で疑似提案されました: リクエスト仕様でのスタブ認証 ですが、私はそれをdeviseで動作させることができません。 CanCanは、当然、正しい権限を持たないAbilityをチェックするときにnil Userを受け取ります。
統合仕様ではコントローラーにアクセスできないため、current_userをスタブできませんが、このようなことをしたいと思います。
describe "GET /users" do
it "should be able to get" do
clear_users_and_add_admin #does what it says...
login(admin)
get users_path
response.status.should be(200)
end
end
注!!!:質問が行われて以来、これはすべて変更されています。これを行う現在の最良の方法はここにあります: http://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara
@pschuegr自身の答えは私を一線を越えさせました。完全を期すために、これは私がリクエストスペックとコントローラースペックの両方を簡単にセットアップできるようにしたものです(FactoryGirlを使用してユーザーインスタンスを作成します)。
/spec/support/sign_in_support.rb内:
#module for helping controller specs
module ValidUserHelper
def signed_in_as_a_valid_user
@user ||= FactoryGirl.create :user
sign_in @user # method from devise:TestHelpers
end
end
# module for helping request specs
module ValidUserRequestHelper
# for use in request specs
def sign_in_as_a_valid_user
@user ||= FactoryGirl.create :user
post_via_redirect user_session_path, 'user[email]' => @user.email, 'user[password]' => @user.password
end
end
RSpec.configure do |config|
config.include ValidUserHelper, :type => :controller
config.include ValidUserRequestHelper, :type => :request
end
次に、要求仕様で:
describe "GET /things" do
it "test access to things, works with a signed in user" do
sign_in_as_a_valid_user
get things_path
response.status.should be(200)
end
end
describe "GET /things" do
it "test access to things, does not work without a signed in user" do
get things_path
response.status.should be(302) # redirect to sign in page
end
end
同様に、コントローラー仕様で 'signed_in_as_valid_user'を使用します(これは、Devise :: TestHelpers sign_inメソッドをFactoryGirlのユーザーでラップします)。
ああ、とても近い。これはトリックです-適切なパラメーターフォームとリダイレクトがありませんでした。
post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password
Warden :: Test :: Helpersを使用して、少し異なるアプローチを使用しました。
私のspec/support/macros.rbに追加しました:
module RequestMacros
include Warden::Test::Helpers
# for use in request specs
def sign_in_as_a_user
@user ||= FactoryGirl.create :confirmed_user
login_as @user
end
end
そして、それをspec_helper.rbのRSpecの設定に含めました:
RSpec.configure do |config|
config.include RequestMacros, :type => :request
end
そして、リクエスト仕様自体で:
describe "index" do
it "redirects to home page" do
sign_in_as_a_user
visit "/url"
page.should_not have_content 'content'
end
end
post_via_redirect user_session_path
メソッドとは対照的に、これは実際に機能し、たとえばbefore_filtersでcurrent_userを使用できます。
2017年半ばの時点で、Rspecにdeviseを統合する機会がもう1つあります。以下で説明するように定義されたヘルパーメソッドsign in
を使用して、スタブ認証を利用できます。
module ControllerHelpers
def sign_in(user = double('user'))
if user.nil?
allow(request.env['warden']).to receive(:authenticate!).and_throw(:warden, {:scope => :user})
allow(controller).to receive(:current_user).and_return(nil)
else
allow(request.env['warden']).to receive(:authenticate!).and_return(user)
allow(controller).to receive(:current_user).and_return(user)
end
end
end
また、新しく作成したファイルにspec_helper.rb
またはRails_helper.rb
参照を追加する必要があります。
require 'support/controller_helpers'
...
RSpec.configure do |config|
...
config.include Devise::TestHelpers, :type => :controller
config.include ControllerHelpers, :type => :controller
...
end
次に、メソッド内で、認証されたユーザーのコンテキストのメソッド本体sign_in
の先頭に配置するだけで、すべての準備が整います。最新の詳細はdevise docsにあります here
マクロ(/spec/support/controller_macros.rb)を作成して、次のように記述できます。
module ControllerMacros
def login_user
before(:each) do
@request.env["devise.mapping"] = :user
@user = Factory(:user)
sign_in @user
end
end
end
必要なCanCan属性を含めることもできます。次に、仕様で:
describe YourController do
login_user
it "should ..." do
end