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
@ 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).
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
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.
Ich fand diesen Link sehr hilfreich https://github.com/plataformatec/devise/wiki/How-To:-Testcontroller-mit-Rails-3-und-4- (und-RSpec) }
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
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