HTTP basic auth для Capybara
Я пишу некоторые тесты RSpec для моего приложения Rails 3 и пытаюсь перейти от Webrat к Capybara. Пока что так хорошо, но приложение использует HTTP basic auth для авторизации моего администратора, любая идея, как я могу проверить это с Capybara?
Вот мой текущий шаг 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
Как мне это сделать с Capybara? Спасибо!
Ответы
Ответ 1
Я получил его для работы с page.driver.basic_authorize(name, password)
вместо
Update:
На данный момент, после обновления Capybara, я использую эту кучу обходных решений:
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
Ответ 2
По умолчанию драйвер Capybara, rack-test, имеет метод basic_authorize
(с псевдонимом authorize
) для Basic HTTP Auth и digest_authorize
для Digest HTTP Auth, здесь вы можете найти их: https://github.com/brynary/rack-test/blob/master/lib/rack/test.rb
Итак, вы можете сделать:
page.driver.browser.authorize 'login', 'password'
Или вы можете написать простой помощник для Basic HTTP Auth:
def basic_auth(user, password)
encoded_login = ["#{user}:#{password}"].pack("m*")
page.driver.header 'Authorization', "Basic #{encoded_login}"
end
Ответ 3
Это изменилось в последних версиях огуречных рельсов (я использую 1.0.2).
cucumber-rails по умолчанию использует драйвер Rack/Test, поэтому, если вы его не изменили, будут работать следующие инструкции.
Создать функции /step _definitions/authorize.rb:
Given /^I am logged in as "([^\"]*)" with "([^\"]*)"$/ do |username, password|
authorize username, password
end
Теперь вы можете использовать это в своих возможностях:
Given I am logged in as "admin" with "password"
Ответ 4
Ни один из решений page.driver.*
не работал у меня. Я использую Poltergeist, а не Selenium, так что это может иметь какое-то отношение к этому. Вот что работало:
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
Затем в вашей спецификации:
feature "Your feature", js: true do
include_context "When authenticated"
# Your test code here...
end
Ответ 5
Мне пришлось сделать этот ужасный хак, чтобы заставить его работать без головы и с 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
Ответ 6
Человек, ни один из этих решений не работал у меня.
Решение Pistos приблизилось и работало для спецификаций функций с js: true
, но сбой при использовании без головы.
Это ниже решение работает для меня для обе версии и js: true
.
спецификации/поддержка/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
Затем в вашей спецификации:
feature 'User does something' do
include_context 'When authenticated'
# test examples
end