Si j'ai un utilisateur modèle Devise dont seuls les utilisateurs dotés du rôle: admin sont autorisés à afficher une certaine URL, comment puis-je écrire un test d'intégration RSpec pour vérifier que le statut renvoie 200 pour cette URL?
def login(user)
post user_session_path, :email => user.email, :password => 'password'
end
Cela a été pseudo-suggéré dans la réponse à cette question: Stubbing authentification dans request spec , mais je ne peux pas pour la vie de le faire fonctionner avec un système. CanCan reçoit naturellement un utilisateur nul lors de la vérification de Ability, qui ne dispose pas des autorisations appropriées.
Il n'y a pas d'accès au contrôleur dans les spécifications d'intégration, donc je ne peux pas stub current_user, mais j'aimerais faire quelque chose comme ça.
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
REMARQUE!!!: tout cela a changé depuis que la question a été posée. La meilleure façon de procéder est la suivante: http://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara
La propre réponse de @ pschuegr m'a amené à traverser la ligne. Par souci d'exhaustivité, voici ce que j'ai fait pour configurer facilement les spécifications de demande et les spécifications de contrôleur (en utilisant FactoryGirl pour créer l'instance d'utilisateur):
dans /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
Puis dans la demande spec:
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
de même, utilisez 'signed_in_as_valid_user' dans les spécifications du contrôleur (qui englobe la méthode sign_in Devise :: TestHelpers avec un utilisateur de FactoryGirl)
Ah, si proche. Cela fait le tour - il me manquait la forme de paramètre appropriée et la redirection.
post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password
J'ai utilisé une approche légèrement différente, en utilisant Warden :: Test :: Helpers.
Dans ma spéc/support/macros.rb, j'ai ajouté:
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
Et ensuite inclus cela dans la configuration de RSpec dans spec_helper.rb:
RSpec.configure do |config|
config.include RequestMacros, :type => :request
end
Et puis dans les spécifications de la demande elles-mêmes:
describe "index" do
it "redirects to home page" do
sign_in_as_a_user
visit "/url"
page.should_not have_content 'content'
end
end
Contrairement à la méthode post_via_redirect user_session_path
, cela fonctionne réellement et me permet d'utiliser current_user dans before_filters, par exemple.
J'ai trouvé ce lien très utile https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-(and-RSpec)
À la mi-2017, nous en avons une de plus, à mon avis, une meilleure opportunité d’intégrer le système dans nos Rspecs. Nous sommes en mesure d'utiliser l'authentification de stub avec la méthode d'assistance sign in
définie comme décrit ci-dessous:
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
Vous devez également ajouter dans la référence spec_helper.rb
ou Rails_helper.rb
au fichier nouvellement créé:
require 'support/controller_helpers'
...
RSpec.configure do |config|
...
config.include Devise::TestHelpers, :type => :controller
config.include ControllerHelpers, :type => :controller
...
end
Ensuite, dans la méthode, placez simplement au début de la méthode le corps sign_in
pour le contexte de l'utilisateur authentifié et vous êtes tous définis. Les détails les plus récents sont disponibles dans les documents docs ici
Vous pouvez créer une macro (/spec/support/controller_macros.rb) et écrire quelque chose comme:
module ControllerMacros
def login_user
before(:each) do
@request.env["devise.mapping"] = :user
@user = Factory(:user)
sign_in @user
end
end
end
Vous pouvez également inclure tous les attributs CanCan de votre choix. Ensuite, dans vos spécifications:
describe YourController do
login_user
it "should ..." do
end