Capybara 的 HTTP 基本身份验证

发布于 2024-10-05 16:22:58 字数 509 浏览 5 评论 0原文

我正在为我的 Rails 3 应用程序编写一些 RSpec 测试,并尝试从 Webrat 切换到 水豚。到目前为止一切顺利,但应用程序使用 HTTP 基本身份验证来授权我的管理员用户,知道如何使用 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 执行此操作?谢谢!

I'm writing some RSpec tests for my Rails 3 application and trying to switch from Webrat to Capybara. So far so good but the application uses HTTP basic auth to authorize my admin user, any idea how I can test that with Capybara?

Here is my current Webrat step:

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

How do I do this with Capybara? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

让它工作

我使用page.driver.basic_authorize(name,password)代替更新

:目前,在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

I got it to work using page.driver.basic_authorize(name, password) instead

Update:

At the moment, after a Capybara upgrade, I'm using this pile of workarounds:

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
执笏见 2024-10-12 16:22:58

默认的 Capybara 驱动程序rack-test具有用于基本 HTTP 身份验证的 basic_authorize 方法(别名为 authorize),以及用于摘要 HTTP 身份验证的 digest_authorize ,在这里你可以找到它们: https://github.com/brynary/rack -test/blob/master/lib/rack/test.rb

所以你可以这样做:

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

或者你可以为基本 HTTP 身份验证编写一个简单的帮助程序:

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

The default Capybara driver, rack-test, has a basic_authorize method (with alias authorize) for Basic HTTP Auth, and digest_authorize for Digest HTTP Auth, here you can find them: https://github.com/brynary/rack-test/blob/master/lib/rack/test.rb

So you can do:

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

Or you can write a simple helper for Basic HTTP Auth:

def basic_auth(user, password)
  encoded_login = ["#{user}:#{password}"].pack("m*")
  page.driver.header 'Authorization', "Basic #{encoded_login}"
end
有深☉意 2024-10-12 16:22:58

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

None of the page.driver.* solutions worked for me. I'm using Poltergeist, not Selenium, so that might have something to do with it. Here's what did work:

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

Then, in your spec:

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

  # Your test code here...
end
您的好友蓝忘机已上羡 2024-10-12 16:22:58

这在最近版本的 cucumber-rails 中发生了变化(我使用的是 1.0.2)。

cucumber-rails 默认使用 Rack/Test 驱动程序,因此如果您没有更改它,则以下说明将起作用。

创建 features/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"

This has changed in recent versions of cucumber-rails (I am using 1.0.2).

cucumber-rails uses the Rack/Test driver by default, so if you have not changed that, the following instructions will work.

Create features/step_definitions/authorize.rb:

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

Now you can use this in your features:

Given I am logged in as "admin" with "password"
荒人说梦 2024-10-12 16:22:58

我不得不做这个可怕的黑客让它工作值得无头和与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

I had to do this horrible hack to get it work worth headless and with 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
倚栏听风 2024-10-12 16:22:58

伙计,这些解决方案都不适合我。

Pistos 的解决方案非常接近并适用于 js: true 的功能规范,但在无头时失败。

下面的解决方案适用于两者无头和js:true规范。

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

然后,在您的规范中:

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

  # test examples
end

Man, none of these solutions worked for me.

Pistos' solution came close and worked for feature specs with js: true but failed when headless.

This below solution works for me for both headless and 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

Then, in your spec:

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

  # test examples
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文