HTTP basic auth for Capybara

后端 未结 6 970
伪装坚强ぢ
伪装坚强ぢ 2020-12-05 00:06

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 m

相关标签:
6条回答
  • 2020-12-05 00:44

    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
    
    0 讨论(0)
  • 2020-12-05 00:46

    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
    
    0 讨论(0)
  • 2020-12-05 00:47

    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
    
    0 讨论(0)
  • 2020-12-05 00:48

    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"
    
    0 讨论(0)
  • 2020-12-05 01:01

    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
    
    0 讨论(0)
  • 2020-12-05 01:08

    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
    
    0 讨论(0)
提交回复
热议问题