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