ruby-on-rails testing authentication webrat capybara

ruby on rails - Autorización básica HTTP para Capibara



ruby-on-rails testing (6)

Estoy escribiendo algunas pruebas RSpec para mi aplicación Rails 3 e intento cambiar de Webrat a Capybara . Hasta ahora todo bien, pero la aplicación utiliza autenticación básica HTTP para autorizar a mi usuario administrador, ¿alguna idea de cómo puedo probar eso con Capybara?

Aquí está mi paso actual 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

¿Cómo hago esto con Capibara? ¡Gracias!


El controlador de Capybara predeterminado, prueba en rack, tiene un método de authorize básica (con authorize alias) para la autenticación HTTP básica y digest_authorize para digest_authorize HTTP de resumen, aquí puede encontrarlos: https://github.com/brynary/rack-test/blob/master/lib/rack/test.rb

Entonces puedes hacer:

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

O puede escribir un simple ayudante para la autenticación HTTP básica:

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


Esto ha cambiado en las versiones recientes de pepino-rails (estoy usando 1.0.2).

pepino-rails utiliza el controlador Rack / Test por defecto, por lo que si no lo ha cambiado, las siguientes instrucciones funcionarán.

Crear funciones / step_definitions / authorize.rb:

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

Ahora puede usar esto en sus funciones:

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


Hombre, ninguna de estas soluciones funcionó para mí.

La solución de Pistos se acercó y funcionó para las características con js: true pero falló cuando no tenía cabeza.

Esta solución a continuación funciona para mí tanto para headless como para 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

Entonces, en tu especificación:

feature ''User does something'' do include_context ''When authenticated'' # test examples end


Lo hice funcionar usando page.driver.basic_authorize(name, password) lugar

Actualización :

Por el momento, después de una actualización de Capybara, estoy usando este montón de soluciones:

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


Ninguna de las soluciones de page.driver.* para mí. Estoy usando Poltergeist, no Selenium, por lo que podría tener algo que ver con eso. Esto es lo que funcionó:

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

Entonces, en tu especificación:

feature "Your feature", js: true do include_context "When authenticated" # Your test code here... end


Tuve que hacer este truco horrible para hacer que el trabajo valga la pena sin cabeza y con 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:password@#{page.driver.current_url.gsub(/^http/://///, '''')}") end end