web-dev-qa-db-ja.com

RSpecおよびDevise / CanCanとの統合テストを行う方法は?

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

36
pschuegr

@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のユーザーでラップします)。

47
Matt Connolly

ああ、とても近い。これはトリックです-適切なパラメーターフォームとリダイレクトがありませんでした。

post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password
28
pschuegr

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を使用できます。

20
Jure Triglav
0
Shimaa Marzouk

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

0
w1t3k

マクロ(/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
0
Spyros