web-dev-qa-db-fra.com

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

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

36
pschuegr

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)

47
Matt Connolly

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
28
pschuegr

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.

20
Jure Triglav
0
Shimaa Marzouk

À 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

0
w1t3k

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
0
Spyros