2011-03-08 4 views
8

J'essaie d'écrire des tests d'intégration avec rspec, factory_girl & capybara. J'ai aussi du concombre installé, mais je ne l'utilise pas (à ma connaissance).Test des sessions dans Rails 3 avec Rspec & Capybara

Je veux fondamentalement préremplir la base de données avec mon utilisateur, puis aller à ma page d'accueil et essayer de se connecter. Il devrait rediriger vers user_path (@user). Cependant, les sessions ne semblent pas être persistantes dans mes tests/rspec/requests/integration.

Mes spécifications: /rspec/requests/users_spec.rb

require 'spec_helper' 

describe "User flow" do 

    before(:each) do 
    @user = Factory(:user) 
    end 

    it "should login user" do 

    visit("/index") 

    fill_in :email, :with => @user.email 
    fill_in :password, :with => @user.password 
    click_button "Login" 
    assert current_path == user_path(@user) 
    end 
end 

Retours:

Failures: 

    1) User flow should login user 
    Failure/Error: assert current_path == user_path(@user) 
    <false> is not true. 
    # (eval):2:in `send' 
    # (eval):2:in `assert' 
    # ./spec/requests/users_spec.rb:16 

, il réoriente lieu à mon please_login_path - ce qui devrait se produire si la connexion échoue pour une raison quelconque (ou si la session [: id_utilisateur] n'est pas définie).

Si j'essaie de mettre session.inspect, il échoue en tant qu'objet nil.

Si j'essaie de le faire dans les tests de contrôleur (/rspec/controllers/sessions_spec.rb), je peux accéder à la session sans problème, et je peux appeler session [: user_id]

+1

Je ne sais pas si cela est lié, mais vous ne devriez pas pouvoir obtenir le mot de passe d'un utilisateur en tapant @ user.password. Ceci est une faille de sécurité dans votre application. Conservez-vous les mots de passe en utilisant du texte brut? –

+5

Ce n'est pas lié, et ce n'est probablement pas une faille de sécurité. L'appel à #password renvoie uniquement un mot de passe car il est défini dans la variable d'instance par Factory. Il est probable qu'il utilise Devise ou quelque chose de similaire qui ne conserve pas l'attribut password de la base de données en texte clair, et donc il ne serait pas disponible si cette variable d'instance disparaissait. –

Répondre

6

Si vous êtes En utilisant Devise, vous devez inclure Warden :: Test :: Helpers (juste après que require de spec_helper est un bon endroit) comme indiqué in the warden wiki.

L'appel à la session renvoie un résultat nul car capybara ne lui fournit pas d'accès lors de l'exécution d'un test d'intégration.

1

Vous avez probablement changé de sujet, mais je me débattais avec la même question. Il s'avère que c'était une question de syntaxe. J'utilisais des symboles pour :email et :password et j'aurais dû utiliser des chaînes à la place ("email" et "password").

En d'autres termes, essayez de changer ceci:

fill_in :email, :with => @user.email 
fill_in :password, :with => @user.password 

à ceci:

fill_in "email", :with => @user.email 
fill_in "password", :with => @user.password 
3

j'ai les mêmes problèmes et, bien que remplissant un formulaire pourrait être une option pour certains, je devais rouler ma propre authentification ruby ​​parce que j'utilisais un système d'authentification tiers (Janrain pour être exact) .... dans mes tests j'ai fini par utiliser quelque chose comme ceci:

Voici ce que j'ai dans ma spéc/support /test_helpers_and_stuff.rb

module AuthTestHelper 

    class SessionBackdoorController < ::ApplicationController 
    def create 
     sign_in User.find(params[:user_id]) 
     head :ok 
    end 
    end 

    begin 
    _routes = Rails.application.routes 
    _routes.disable_clear_and_finalize = true 
    _routes.clear! 
    Rails.application.routes_reloader.paths.each{ |path| load(path) } 
    _routes.draw do 
     # here you can add any route you want 
     match "/test_login_backdoor", to: "session_backdoor#create" 
    end 
    ActiveSupport.on_load(:action_controller) { _routes.finalize! } 
    ensure 
    _routes.disable_clear_and_finalize = false 
    end 

    def request_signin_as(user) 
    visit "/test_login_backdoor?user_id=#{user.id}" 
    end 

    def signin_as(user) 
    session[:session_user] = user.id 
    end 

end 

ensuite dans ma spec demande, avec capybara et le sélénium, je ne les éléments suivants:

describe "Giveaway Promotion" do 
    context "Story: A fan participates in a giveaway", js: :selenium do 
    context "as a signed in user" do 

     before :each do 
     @user = Factory(:user) 
     request_signin_as @user 
     end 

     it "should be able to participate as an already signed in user" do 
     visit giveaway_path 
     .... 
     end 
    end 
    end 
end 

BTW, je suis venu avec des solutions après avoir essayé les solutions proposées à this post et this post et aucun d'eux n'a travaillé pour moi. (mais ils ont certainement inspiré ma solution)

Bonne chance!

Questions connexes