Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manually authenticate for testing #521

Closed
noahmatisoff opened this issue Feb 2, 2016 · 13 comments
Closed

Manually authenticate for testing #521

noahmatisoff opened this issue Feb 2, 2016 · 13 comments

Comments

@noahmatisoff
Copy link

How can I manually authenticate and set the HTTP headers (client, access-token, uid, etc.)? I'm running a test for a controller that requires authentication.

How can I authenticate in DTA?

@Fudoshiki
Copy link

+1

@Fudoshiki
Copy link

require 'test_helper'

class Api::Operators::CompaniesControllerTest < ActionController::TestCase
  setup do
    @admin = create :user, :admin
  end

  test 'index' do
    @auth_headers = @admin.create_new_auth_token
    request.headers.merge!(@auth_headers)
    get :index, format: :json

    assert_response :success
  end
end

work!

@noahmatisoff
Copy link
Author

@Fudoshiki thanks for the response. I tried this but I'm getting undefined method 'create' in CasesControllerTest.

@Fudoshiki
Copy link

create this is a FactoryGirl method, we used factories. You can replace create(:user, :admin) on fixture.
Examples here https://github.com/lynndylanhurley/devise_token_auth/tree/master/test

@noahmatisoff
Copy link
Author

Ok, I was able to fix that, but now I'm getting this from DTA:

NoMethodError: undefined method `user' for nil:NilClass
    devise_token_auth (0.1.36) app/controllers/devise_token_auth/concerns/set_user_by_token.rb:35:in `set_user_by_token'

Note: I also had to specify confirmed_at in my factory because I was getting a devise confirmation error.

It's creating the User and I can see the auth_headers are correct, but I keep getting the above error.

@RomanKapitonov
Copy link

@matisoffn, Here is the approach I'm using:

module DeviseMapping
  extend ActiveSupport::Concern

  included do
    before(:each) do
      request.env["devise.mapping"] = Devise.mappings[:user]

      allow(SecureRandom).to receive(:urlsafe_base64).with(nil, false).and_return("Nbdlw89hmGAd1y1Ch6fhfw")
    end
  end

  [:get, :post, :put, :patch, :delete].each do |http_method|
    define_method("auth_#{http_method}") do |action_name, params = {}, headers = {}, flash = {}|
      auth_params = {
        'access-token' => controller.current_user.last_token,
        'client' => controller.current_user.last_client_id,
        'uid' => controller.current_user.email
      }
      params = params.merge(auth_params)
      public_send(http_method, action_name, params, headers, flash)
    end
  end
end


RSpec.configure do |config|
  config.include DeviseMapping, type: :controller
end

Then just use auth_get, auth_post and etc to perform a request with headers. Note that SecureRandom is patched to always build the same hash. This is needed since I'm using apipie gem which rebuilds it's docs on each test run.

@noahmatisoff
Copy link
Author

@RomanKapitonov thanks for that, but I'm using Test::Unit not Rspec. Also where do you put this file?

@RomanKapitonov
Copy link

@matisoffn this is usually put into spec/support/whatever_name.rb and then you have a line in spec_helper.rb or rails_helper.rb (depending on the one you use)

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

This will load all files from support directory. Then in your spec you put require 'rails_helper.rb' and hence DeviseMapping gets included into RSpec.config for controllers.

@noahmatisoff
Copy link
Author

Will this work with Test::Unit?

On Feb 9, 2016, at 8:07 AM, Roman Kapitonov <notifications@github.commailto:notifications@github.com> wrote:

@matisoffnhttps://github.com/matisoffn this is usually put into spec/support and then you have a line in spec_helper.rb or rails_helper.rb (depending on the one you use)

Dir[Rails.root.join('spec/support/*/.rb')].each { |f| require f }

This will load all files from support directory. Then in your spec you put require 'rails_helper.rb' and hence DeviseMapping gets included into RSpec.config for controllers.


Reply to this email directly or view it on GitHubhttps://github.com//issues/521#issuecomment-181931075.

@noahmatisoff
Copy link
Author

@RomanKapitonov I'm getting undefined method before when trying to implement that. I'm not using Rspec, so I included the module in my test.

@noahmatisoff
Copy link
Author

Fixed by updating gem.

@CJYate
Copy link

CJYate commented Jan 5, 2017

This took me most of a day to solve, so I'm posting my current solution here.

Also see #75

In a request spec:

  @user = FactoryGirl.create :user
  @user.confirm
  			
  @auth_headers = @user.create_new_auth_token
  get current_users_path, params: {}, headers: @auth_headers
  expect(response).to have_http_status(:success)

@dkniffin
Copy link
Contributor

I also just spent way too long on this. One big fact that I learned: controller tests should be treated differently than request specs for this

Here's what I came up with to handle both cases

module AuthHelper
  module Controller
    def sign_in(user)
      @request.env["devise.mapping"] = Devise.mappings[:merchant]

      @request.headers.merge! user.create_new_auth_token
      sign_in user
    end
  end

  module Request
    %i(get post put patch delete).each do |http_method|
      # auth_get, auth_post, auth_put, auth_patch, auth_delete
      define_method("auth_#{http_method}") do |user, action_name, params: {}, headers: {}|
        auth_headers = user.create_new_auth_token
        headers = headers.merge(auth_headers)
        public_send(http_method, action_name, params: params, headers: headers)
      end
    end
  end
end

RSpec.configure do |config|
  config.include AuthHelper::Controller, type: :controller
  config.include AuthHelper::Request, type: :request
end

Controller test usage:

describe SomeController, type: :controller do
  let(:user) { create(:user) }
  subject { post :create, params: params }
  before { sign_in user }

  ...
end

Request spec usage:

describe SomeRequest, type: :request do
  let(:user) { create(:user) }
  subject { auth_post user, '/api/some_endpoint', params: params }

  ...
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants