2010-12-01 41 views
31

J'écris quelques tests RSpec pour mon application Rails 3 et j'essaie de passer de Webrat à . Jusqu'à présent, tout va bien, mais l'application utilise HTTP basic auth pour autoriser mon utilisateur admin, aucune idée de comment je peux tester ça avec Capybara?Authentification de base HTTP pour Capybara

Voici mon étape en cours de Webrat:

it 'should authenticate for admin' do 
    basic_auth('user', 'secret') 
    visit '/admin' 
    response.status.should eql 200 
    response.status.should_not eql 401 
end 

Comment puis-je faire avec Capybara? Merci!

Répondre

39

Je l'ai à travailler en utilisant à la place page.driver.basic_authorize(name, password)

Mise à jour:

Actuellement, après une mise à niveau Capybara, j'utilise ce tas de solutions de contournement:

if page.driver.respond_to?(:basic_auth) 
    page.driver.basic_auth(name, password) 
elsif page.driver.respond_to?(:basic_authorize) 
    page.driver.basic_authorize(name, password) 
elsif page.driver.respond_to?(:browser) && page.driver.browser.respond_to?(:basic_authorize) 
    page.driver.browser.basic_authorize(name, password) 
else 
    raise "I don't know how to log in!" 
end 
+1

Cool, cela fonctionne! Pour référence future: J'ai trouvé un commentaire de Jonas Nicklas, le créateur de Capybara, déconseillant d'utiliser le pilote car tous les pilotes Capybara ne supportent pas les en-têtes HTTP (https://github.com/jnicklas/capybara/issues/issue/17) ... si quelqu'un aurait besoin de ça. En ce qui me concerne, c'est la solution dont j'ai besoin. Merci Anders! – Cimm

+2

'page.driver.browser.basic_authorize' a fonctionné pour moi. Je vous remercie!!! –

+0

Vous rock! 'page.driver.browser.basic_authorize' travaillé pour moi –

1

I a dû faire ce hack horrible pour le faire fonctionner sans valeur et avec javascript

Given /^I am logged in$/ do 
if page.driver.respond_to?(:basic_authorize) 
    page.driver.basic_authorize('admin', 'password') 
else 
    # FIXME for this to work you need to add pref("network.http.phishy-userpass-length", 255); to /Applications/Firefox.app/Contents/MacOS/defaults/pref/firefox.js 
    page.driver.visit('/') 
    page.driver.visit("http://admin:[email protected]#{page.driver.current_url.gsub(/^http\:\/\//, '')}") 
end 
end 
2

Cela a changé dans les versions récentes de cucumber-rails (j'utilise 1.0.2). Cucumber-rails utilise le pilote Rack/Test par défaut, donc si vous n'avez pas changé cela, les instructions suivantes fonctionneront.

Créer fonctionnalités/step_definitions/authorize.rb:

Given /^I am logged in as "([^\"]*)" with "([^\"]*)"$/ do |username, password| 
    authorize username, password 
end 

Maintenant, vous pouvez utiliser dans vos fonctions:

Given I am logged in as "admin" with "password" 
+0

Merci Joost mais la question n'a pas mentionné le concombre. C'était une question de Capybara seulement. Bon à savoir, il y a un moyen simple dans le concombre pour faire cela. – Cimm

+0

Peu importe si vous utilisez RSpec et non Cucumber pour exécuter les fonctionnalités, la réponse est également valide si vous avez conservé le pilote par défaut dans Capybara qui est Rack :: Test. –

24

Le pilote par défaut Capybara, porte-test, a une méthode basic_authorize (avec l'alias authorize) pour l'authentification HTTP de base, et digest_authorize pour Digest HTTP Auth, ici vous pouvez les trouver:

Vous pouvez le faire:

page.driver.browser.authorize 'login', 'password' 

Ou vous pouvez écrire une aide simple pour HTTP Basic Auth:

def basic_auth(user, password) 
    encoded_login = ["#{user}:#{password}"].pack("m*") 
    page.driver.header 'Authorization', "BasiC#{encoded_login}" 
end 
+1

Votre première ligne {page.driver.browser.authorize 'login', 'mot de passe'} fonctionne un régal, dommage qu'elle ne fonctionne pas dans un avant: chaque bloc pour un test rspec 2 mais ça marche bien avant un appel à visiter. Merci pour la réponse – jamesc

+2

A noter que cette méthode fonctionne en ajoutant l'en-tête 'Authorization' à la requête, vous devez donc appeler cela AVANT' visit'. –

+0

Merci @LachlanCotter, je me tortillais le cerveau autour de ça. – Calvin

2

Aucune des solutions page.driver.* a fonctionné pour moi. J'utilise Poltergeist, pas Selenium, donc ça pourrait avoir quelque chose à voir avec ça. Voici ce que fait le travail:

RSpec.shared_context "When authenticated" do 
    before do 
    username = 'yourusername' 
    password = 'yourpassword' 
    visit "http://#{username}:#{password}@#{Capybara.current_session.server.host}:#{Capybara.current_session.server.port}/" 
    end 
end 

Ensuite, dans votre spec:

feature "Your feature", js: true do 
    include_context "When authenticated" 

    # Your test code here... 
end 
+0

C'est facile et propre. Au lieu d'un shared_context, je mets le bloc 'config.before (: each) do'. –

0

Man, aucune de ces solutions a fonctionné pour moi.

La solution de Pistos s'est rapprochée et a fonctionné pour les spécifications de fonctionnalité avec js: true mais a échoué en l'absence d'interface.

Cette solution ci-dessous fonctionne pour moi pour les deux sans tête et js: true specs.

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