0

I want to test the build-in basic http authentication mechanism in Rails 3.2.3. I have tried to test the http authentication in both RSpec and Cucumber but with a failing step in both tools. In Cucumber I get the following message on running my Feature:

When I perform HTTP authentication as "admin" with "test" # features/step_definitions/web_steps.rb:1
  undefined method `env' for nil:NilClass (NoMethodError)
  ./features/step_definitions/web_steps.rb:3:in `/^I perform HTTP authentication as "([^\"]*)" with "([^\"]*)"$/'
  features/sign_in_http.feature:4:in `When I perform HTTP authentication as "admin" with "test"'

Here is my ApplicationController class:

class ApplicationController < ActionController::Base
  protect_from_forgery

  http_basic_authenticate_with :name => "admin", :password => "test"
end

The step definition in Cucumber:

When /^I perform HTTP authentication as "([^\"]*)" with "([^\"]*)"$/ do |username, password|
  @request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("username:password")
  visit '/'
end

The cucumber feature:

Feature: Signing in via http

Scenario: HTTP sign-in
  When I perform HTTP authentication as "admin" with "test"
  Then I should see "Welcome to the app."

In RSpec the http authentication step seems to pass but I get the message from the subsequent step, that it couldn't find the expected content on the page because "Access was denied":

1) ApplicationController sign in via http should be successful
 Failure/Error: page.should have_content("Welcome to the app.")
   expected there to be content "Welcome to the app." in "HTTP Basic: Access denied.\n"
 # ./spec/controllers/application_controller_spec.rb:12:in `block (3 levels) in <top (required)>'

Here is my associated spec:

require 'spec_helper'

describe ApplicationController do

  describe "sign in via http" do
    it "should be successful" do
      @request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("admin:test")
      visit '/'
      response.should be_success
      page.should have_content("Welcome to the app.")
    end
  end
end

I have also tried to visit the root path before the http authorization line in the cucumber step but this gave me the same message about the NilClass for @request. Login via the browser with the defined "admin:test" credentials is no problem and I can see the root page of my app.

I would be thankful for any suggestions.

2 Answers 2

3

Here's how I got it to work. The key is to run your authentication step before you visit any pages, else you've already failed the authentication.

In my Feature I put:

Background:
    Given I perform HTTP authentication as "<id>/<password>"
    When I go to the homepage
    Then I should see "Text-that-you-should-see-on-your-home-page"

The step definition for the HTTP authentication is as follows (I found this code elsewhere and added the puts statements to see what was going on).

Given /^I perform HTTP authentication as "([^\"]*)\/([^\"]*)"$/ do |username, password|
    puts "id/pswd: #{username}/#{password}"
    ### Following works ONLY if performed first before even going to a page!!!
    if page.driver.respond_to?(:basic_auth)
        puts 'Responds to basic_auth'
        page.driver.basic_auth(username, password)
    elsif page.driver.respond_to?(:basic_authorize)
        puts 'Responds to basic_authorize'
        page.driver.basic_authorize(username, password)
    elsif page.driver.respond_to?(:browser) && page.driver.browser.respond_to?(:basic_authorize)
        puts 'Responds to browser_basic_authorize'
        page.driver.browser.basic_authorize(username, password)
    else
        raise "I don't know how to log in!"
    end
end
Sign up to request clarification or add additional context in comments.

Comments

0

There's a much simpler solution now. I don't know when it was implemented, but Cucumber now has a method basic_authorize that takes care of this. Here's the step that I used:

Given /^I perform basic HTTP authentication with username "([^"]*)" and password "([^"]*)"$/ do |username, password|
  basic_authorize(username, password)
end

And here's an example use case:

Given I perform basic HTTP authentication with username "cool_user" and password "hunter22"

As with JESii's answer, you need to perform this step before you visit any pages.

I hope this saves someone else some time, I spent way to long on this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.