36 votes

Comment faire des tests d'intégration avec RSpec et Devise/CanCan ?

Si j'ai un modèle Devise User, dont seuls les utilisateurs ayant le rôle :admin sont autorisés à consulter 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 : Suppression de l'authentification dans les spécifications de la demande mais je n'arrive pas à le faire fonctionner avec devise. CanCan reçoit un nil User lors de la vérification de Ability, qui n'a pas les bonnes permissions, naturellement.

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

NOTE ! !! : tout cela a changé depuis que la question a été posée. La meilleure façon actuelle de le faire est ici : http://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara

47voto

Matt Connolly Points 4851

La réponse de @pschuegr m'a fait franchir la ligne. Pour être complet, voici ce que j'ai fait et qui me permet d'être facilement configuré pour les spécifications des requêtes et les spécifications des contrôleurs (en utilisant FactoryGirl pour créer l'instance 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

Ensuite, dans la requête 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

et de la même manière, utilisez 'signed_in_as_valid_user' dans les spécifications du contrôleur (qui englobe la méthode de signature de Devise::TestHelpers avec un utilisateur de FactoryGirl).

28voto

pschuegr Points 828

Ah, si proche. Cela fait l'affaire - il me manquait le bon formulaire de paramètre, et la redirection.

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

20voto

Jure Triglav Points 784

J'ai utilisé une approche légèrement différente, en utilisant les Warden::Test::Helpers.

Dans mon spec/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 l'inclure 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 elle-même :

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 post_via_redirect user_session_path cela fonctionne réellement et me permet d'utiliser current_user dans before_filters, par exemple.

0voto

Spyros Points 13741

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 que vous souhaitez. Ensuite, dans votre spécification :

describe YourController do
    login_user

    it "should ..." do

    end

0voto

Shimaa Marzouk Points 345

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X