How can I set the request headers before doing the request on a request spec?
I'm moving controller specs to request specs on my API using Rails. One thing I'm stuck on is that I have no access to a request object to allow the requests.
On my controller specs, I have access to a method I created which signs a specific user:
def sign_in(user)
  token = user.api_keys.first.token
  # note the request object being used in the next line
  request.env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Token.encode_credentials(token)
end
This works fine on controller specs, I can safely do:
before { sign_in(user) }
it { post :endpoint, params }
But on a request spec, the request object is not available. 
If I try to:
before { sign_in(user) }
it { post "/api/endpoint", params }
I get request on my helper method as nil.
I know I could do:
it { post "/api/endpoint", {"HTTP_AUTHORIZATION" => ... } }
But this seems a lot of clutter in the spec, specially compared to a controller spec.
I've tried using ActionDispatch::TestRequest::DEFAULT_ENV as suggested by this answer, but it didn't work too (I get a 401).
If you're not already using Rack::Test for this then you should be. Rack::Test is better suited than Capybara for testing API requests. It can be configured in your rspec/spec_helper.rb
RSpec.configure do |config|
  # ...
  config.include Rack::Test::Methods
end
When you're configured to use Rack::Test, you can set headers before the request like so:
it 'POST /api/enpoint authenticates successfully' do
  header 'Authorization', '...'
  post "/api/endpoint", params
  expect(last_response).to be_ok
end
This will be accessible in your controller as request.headers['HTTP_AUTHORIZATION'].
The source code for this method can be found here - https://github.com/brynary/rack-test/blob/master/lib/rack/test.rb#L127-L141
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With