July 14, 2014

Authenticating with HTTP basic authentication from request specs

In one of my previous posts I mentioned that I used HTTP basic authentication for REST API. In this post I will show you how to authenticate with HTTP simple authentication from RSpec request specs.

In the example below you can see one API spec and then different private methods for HTTP GET, POST, PATH and DELETE methods.

# spec/request/api_spec.rb

require 'spec_helper'

describe 'REST API' do
  describe 'GET /runs' do
    let(:user) { create(:user) }

    it 'retrieves all runs for user' do
      run1 = create(:run, distance: 5, user: user).reload
      run2 = create(:run, distance: 10, user: user).reload

      get_with_auth '/runs', user.email, user.password

      expect(response).to be_success
      expect(response.body).to eq [run1, run2].to_json
    end
  end

  # other specs...

  private

  def get_with_auth(path, email, password)
    get path, {}, env_with_auth(email, password)
  end

  def delete_with_auth(path, email, password)
    delete path, {}, env_with_auth(email, password)
  end

  def post_with_auth(path, params, email, password)
    post path, params, env_with_auth(email, password)
  end

  def patch_with_auth(path, params, email, password)
    patch path, params, env_with_auth(email, password)
  end

  def env
    {
      'Accept' => 'application/json',
      'Content-Type' => 'application/json'
    }
  end

  def env_with_auth(email, password)
    env.merge({
      'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(email, password)
    })
  end
end

As you can see, basic RSpec methods are used with some additional parameters. The most important is env_with_auth hash which sets HTTP_AUTHORIZATION HTTP header.

In this example everything is in one file. But in bigger projects you may need to extract above mentioned methods into their own module and use them in different specs.

# spec/support/request_spec_helpers.rb

module RequestSpecHelpers
  # all private methods from the above example
end

And then just include this module to all request specs.

# spec/spec_helper.rb

# ...

RSpec.configure do |config|
  config.include RequestSpecHelpers, type: :request
  # ...
end

Hey there!

My name is Patrik Bóna and I am the only programmer at Memberful. This blog is kind of dead, but I just started my own Ruby on Rails screencast. Follow me on Twitter if you want to be notified about my newest videos.