webentwicklung-frage-antwort-db.com.de

Wie kann ich Integrationstests mit RSpec und Devise/CanCan durchführen?

Wenn ich einen Devise-Modellbenutzer habe, von dem nur die Benutzer mit der Rolle: admin eine bestimmte URL anzeigen dürfen, wie kann ich einen RSpec-Integrationstest schreiben, um zu überprüfen, ob der Status 200 für diese URL zurückgibt?

def login(user)
  post user_session_path, :email => user.email, :password => 'password'
end

Dies wurde in der Antwort auf diese Frage pseudo vorgeschlagen: Stubbing Authentifizierung in Anforderungsspezifikation , aber ich kann es nicht für mein ganzes Leben bekommen, damit es mit devise zusammenarbeitet. CanCan erhält bei der Überprüfung von Ability einen nil-Benutzer, der natürlich nicht über die richtigen Berechtigungen verfügt.

In den Integrationsspezifikationen gibt es keinen Zugriff auf den Controller. Daher kann ich current_user nicht stubben, aber ich möchte so etwas tun.

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

HINWEIS!!!: Das hat sich seit der Frage geändert. Der derzeit beste Weg, dies zu tun, ist hier: http://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara

36
pschuegr

@ pschuegr's eigene Antwort hat mich über die Linie gebracht. Der Vollständigkeit halber ist es das, was ich getan habe, was es mir leicht macht, sowohl für Anforderungsspezifikationen als auch für Controllerspezifikationen (unter Verwendung von FactoryGirl zum Erstellen der Benutzerinstanz) einzurichten:

in /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

Dann in der Anforderungsspezifikation:

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

und verwenden Sie in den Controller-Spezifikationen ebenfalls 'signed_in_as_valid_user' (wodurch die sign_in-Methode von Devise :: TestHelpers mit einem Benutzer von FactoryGirl umschlossen wird).

47
Matt Connolly

Ah, so nah. Das macht den Trick - mir fehlte die richtige Parameterform und die Umleitung. 

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

Ich habe einen etwas anderen Ansatz verwendet, die Warden :: Test :: Helpers.

In meiner spec/support/macros.rb habe ich hinzugefügt:

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

Und dann das in die RSpec-Konfiguration in spec_helper.rb aufgenommen:

RSpec.configure do |config|
  config.include RequestMacros, :type => :request
end

Und dann in der Anfrage spezifiziert:

describe "index" do
  it "redirects to home page" do
    sign_in_as_a_user 
    visit "/url"
    page.should_not have_content 'content'
  end
end

Im Gegensatz zur post_via_redirect user_session_path-Methode funktioniert dies tatsächlich und ermöglicht es mir beispielsweise, current_user in before_filters zu verwenden.

20
Jure Triglav
0
Shimaa Marzouk

Ab Mitte 2017 haben wir eine weitere, meiner Meinung nach bessere Möglichkeit, in unsere Rspecs zu integrieren. Wir können die Stub-Authentifizierung mit der Helper-Methode sign in verwenden, die wie folgt definiert ist:

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

Sie sollten auch in spec_helper.rb oder Rails_helper.rb an eine neu erstellte Datei anhängen:

require 'support/controller_helpers'
  ...
  RSpec.configure do |config|
    ...
    config.include Devise::TestHelpers, :type => :controller
    config.include ControllerHelpers, :type => :controller
    ...
  end

Platzieren Sie dann in method am Anfang des Methodenhauptteils sign_in für Kontext für den authentifizierten Benutzer, und Sie sind alle festgelegt. Aktuelle Informationen finden Sie in devise docs hier

0
w1t3k

Sie können ein Makro erstellen (/spec/support/controller_macros.rb) und Folgendes schreiben:

module ControllerMacros
  def login_user
    before(:each) do
      @request.env["devise.mapping"] = :user
      @user = Factory(:user)
      sign_in @user
    end
  end
end

Sie können auch beliebige CanCan-Attribute hinzufügen. Dann in Ihrer Spezifikation:

describe YourController do
    login_user

    it "should ..." do

    end
0
Spyros