Estidev
Estidev

Reputation: 41

Problems for request rspec with basic http auth using Devise

Devise: 4.20
Rails: 5.0.1
Rspec: 3.5

I had used this link https://github.com/plataformatec/devise/wiki/How-To:-Use-HTTP-Basic-Authentication, but I havproblems to test the http basic auth for my api using rspec for requests tests. Below is the example the error:

app/controllers/api/base_controller.rb

module Api
  class BaseController < ApplicationController
    before_action :authenticate_user!

    protected

    def authenticate_user!
      authenticate_or_request_with_http_basic do |username, password|
        resource = User.find_by_username(username)
        if resource
          sign_in :user, resource if resource.valid_password?(password)
        else
          request_http_basic_authentication
        end
      end
    end
  end
end

app/controllers/api/v1/car_controller.rb

module Api
  module V1
    class CarController < Api::BaseController
      respond_to :json

      def index
        @cars = Car.all
        render :json => {:content => @cars}, :status => 200
      end
    end
  end
end

spec/requests/api/v1/car_controller_spec.rb

require 'rails_helper'

RSpec.describe "Servers API", :type => :request do
  it 'sends a list of servers' do
    admin = FactoryGirl.create(:admin)
    @env = {}
    @env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(admin.username, admin.password)
    get "/api/cars", :params => {}, :headers => @env

    # test for the 200 status-code
    expect(response.status).to eq(200)

  end
end

When I run the spec, I have the below error:

# --- Caused by: ---
     # NoMethodError:
     #   undefined method `sign_in' for #<Api::V1::CarController:0x0000000609ef12>
     # ./app/controllers/api/base_controller.rb:10 in block in authenticate_user!

Anyone can help me? Thanks.

Upvotes: 2

Views: 987

Answers (1)

Ignacy Kasperowicz
Ignacy Kasperowicz

Reputation: 421

I have similar setup where my specs are passing, would you also show your spec_helper content, looks like you are not including Devise::TestHelpers.

spec_helper

RSpec.configure do |config|
  config.include Devise::TestHelpers
  config.include Warden::Test::Helpers
  config.before { Warden.test_mode! }
  config.after { Warden.test_reset! }

  config.before(:each) do
    @headers = { 'CONTENT_TYPE' => 'application/json', 'ACCEPT' => 'application/json' }
  end
end

and my test looks something like this:

RSpec.describe 'Users' do
  context 'when client is authorized' do
    let(:user) { FactoryGirl.create(:user) }

    it 'gets user' do
      @headers['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.
        encode_credentials(
          user.authentication_token,
          email: user.email
        )
      get api_v1_user_url(id: user.id), {}, @headers
      expect(response.status).to eq(200)
    end
  end
end

Upvotes: 1

Related Questions