2010-09-22 3 views
58

Voici mon authentification HTTP de base dans le fichier du contrôleur d'application (application_controller.rb)Rails/Rspec Faire les tests passent avec l'authentification HTTP de base

before_filter :authenticate 

protected 

def authenticate 
    authenticate_or_request_with_http_basic do |username, password| 
    username == "username" && password == "password" 
    end 
end 

et le test par défaut pour l'action index de mon contrôleur de la maison (spec/controllers/home_controller_spec.rb)

require 'spec_helper' 

describe HomeController do 

describe "GET 'index'" do 
    it "should be successful" do 
    get 'index' 
    response.should be_success 
    end 
end 

Le test ne s'exécute pas en raison de la méthode d'authentification. Je pourrais commenter "before_filter: authenticate" pour les exécuter mais j'aimerais savoir s'il y a moyen de les faire fonctionner avec la méthode.

Merci!

Répondre

121

Mise à jour: Matt Connolly a fourni une GIST qui fonctionne également pour les spécifications de demande et contrôleur: http://gist.github.com/4158961


Une autre façon de procéder si vous avez plusieurs tests à exécuter et que vous ne souhaitez pas l'inclure à chaque fois (code DRYer):

Créer un fichier /spec/support/auth_helper.rb:

module AuthHelper 
    def http_login 
    user = 'username' 
    pw = 'password' 
    request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user,pw) 
    end 
end 

Dans votre fichier de spécification de test:

describe HomeController do 
    render_views 

    # login to http basic auth 
    include AuthHelper 
    before(:each) do 
    http_login 
    end 

    describe "GET 'index'" do 
    it "should be successful" do 
     get 'index' 
     response.should be_success 
    end 
    end 

end 

Crédit here

+0

bon exemple, merci. –

+1

il montre la demande est nulle pour moi. une idée de comment obtenir une solution de contournement? – chourobin

+6

Pour les spécifications de la requête, vous pouvez avoir plusieurs requêtes, donc 'request' est' nil'. Au lieu de cela, vous devez créer un env hacha 'env = {}', mettre à jour cela dans votre méthode http_login, et ensuite passer dans l'env explicitement comme dans 'get '/', {}, env'. –

17

Désolé, je ne cherchais pas assez, la solution semble être la suivante:

describe "GET 'index'" do 
    it "should be successful" do 
    @request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("username:password") 
    get 'index' 
    response.should be_success 
    end 
end 
4

Lorsque vous utilisez Rspec pour tester Grape API, la syntaxe suivante fonctionne

 post :create, {:entry => valid_attributes}, valid_session 

où valid_session est

{'HTTP_AUTHORIZATION' => credentials} 

et

credentials = ActionController::HttpAuthentication::Token.encode_credentials("test_access1") 
1

Ce sont des solutions pour les spécifications du contrôleur et demande.

Pour les tests de fonction à l'aide de Capybara, voici une solution pour rendre HTTP travail d'authentification de base:

spec/support/when_authenticated.rb

RSpec.shared_context 'When authenticated' do 
    background do 
    authenticate 
    end 

    def authenticate 
    if page.driver.browser.respond_to?(:authorize) 
     # When headless 
     page.driver.browser.authorize(username, password) 
    else 
     # When javascript test 
     visit "http://#{username}:#{password}@#{host}:#{port}/"  
    end 
    end 

    def username 
    # Your value here. Replace with string or config location 
    Rails.application.secrets.http_auth_username 
    end 

    def password 
    # Your value here. Replace with string or config location 
    Rails.application.secrets.http_auth_password 
    end 

    def host 
    Capybara.current_session.server.host 
    end 

    def port 
    Capybara.current_session.server.port 
    end 
end 

Ensuite, dans votre spec:

feature 'User does something' do 
    include_context 'When authenticated' 

    # test examples 
end 
+0

Très utile! :) –

4

Quelques réponses suggèrent de mettre request.env qui est dangereux, parce que la demande peut être nil et vous finirez avec private method env' called for nil:NilClass, surtout quand exécuter des tests simples avec rspec -e

approche correcte sera:

def http_login 
    user = 'user' 
    password = 'passw' 
    { 
    HTTP_AUTHORIZATION: ActionController::HttpAuthentication::Basic.encode_credentials(user,password) 
    } 
end 

get 'index', nil, http_login 

post 'index', {data: 'post-data'}, http_login 
Questions connexes