Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Skip Rails http_basic_authenticate_with in RSpec test

I'm working on a MVP (minimum viable product). In order to offer a simpler way to secure the admin pages, I just did add http_basic_authenticate_with to my AdminController.

Problem is that when I want to test my AdminController, I get "unauthorized" (401) for not being logged in.

In this scenario, it's irrelevant to test the authentication - it's just temporary, and as soon I go to the next sprint, it's going to removed -, so I'm trying to skip it within RSpec.

Problem is I tried many ways, and none seems to be working.

For example, I tried to modify the http_basic_authenticate_with in order to avoid the authentication. Like this:

require 'spec_helper'

module ActionController
  module HttpAuthentication
    module Basic
      def http_basic_authenticate_with(*args)
      end
    end
  end
end


describe Admin::SubscribersController do  
  describe "GET 'index'" do
    it "should be OK" do 
      get 'index'
      response.should be_successful
    end
  end
end

But when I run it, it still returns "false" for that simple test.

Btw, in order to simplify this test, I just have an empty index action on my AdminController and an empty view (index.html.erb).

like image 839
Nicholas Pufal Avatar asked Oct 13 '11 18:10

Nicholas Pufal


3 Answers

Finally I got it working.

Something as stated in the docs didn't work for me:

get 'index', nil, 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials("admin", "password")

So I tried an "old" approach to do it, which is to set request.env['HTTP_AUTHORIZATION'] :

request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials("admin","password")

None of the other solutions worked, so I will just keep in the meanwhile with this one.

Thanks.

like image 124
Nicholas Pufal Avatar answered Sep 24 '22 16:09

Nicholas Pufal


If it is ok to skip authentication for all tests for a controller, here's the technique I'm using on a current project.

unless Rails.env.test?
  http_basic_authenticate_with name: "slothbear", password: "kuniklo"
end
like image 30
slothbear Avatar answered Sep 20 '22 16:09

slothbear


In Rails 5.x, this works:

allow(subject).to receive(:authenticate_or_request_with_http_basic)
  .with(anything).and_return true

In Rails 6.x, this works:

allow(subject).to receive(:http_basic_authenticate_or_request_with)
  .with(anything).and_return true

This is because http_basic_authenticate_with is a class-level method that adds a before_action that actually calls one of these two methods under the hood.

You can see which one to use by checking out http_authentication.rb here for Rails 6 or here for Rails 5

like image 24
Unixmonkey Avatar answered Sep 22 '22 16:09

Unixmonkey