138

In the controller spec, I can set http accept header like this:

request.accept = "application/json"

but in the request spec, "request" object is nil. So how can I do it here?

The reason I want to set http accept header to json is so I can do this:

get '/my/path'

instead of this

get '/my/path.json'
Roseaboveit
  • 174
  • 10
Sergey
  • 4,702
  • 6
  • 26
  • 32

10 Answers10

139

You should be able to specify HTTP headers as the third argument to your get() method as described here:

http://api.rubyonrails.org/classes/ActionDispatch/Integration/RequestHelpers.html#method-i-get

and here

http://api.rubyonrails.org/classes/ActionDispatch/Integration/Session.html#method-i-process

So, you can try something like this:

get '/my/path', nil, {'HTTP_ACCEPT' => "application/json"}
chriscz
  • 169
  • 2
  • 9
awaage
  • 2,669
  • 1
  • 17
  • 15
  • 3
    We needed to use 'HTTP_ACCEPT': `get '/my/path', nil, {'HTTP_ACCEPT' => "application/json"}` – Matt Scilipoti Apr 11 '12 at 13:29
  • 59
    NOTE: This is for integration testing, similar to comment below, in rspec-rails controller tests, you would use: request.env["HTTP_ACCEPT"] = – Alex Soto Feb 06 '13 at 21:54
  • 5
    Small gotcha that I ran into because I am silly: The header keys have to be Strings. Symbols will not show up. – ajmurmann Sep 27 '13 at 23:21
  • @ajmurmann Now symbols work: "Authorization" header can be `:authorization`. – Franklin Yu Sep 07 '16 at 18:59
  • This is correct for generic headers, but if you're only trying to specify a JSON format with a rails controller like the OP is then `get(:action, format: :json)` should do the trick – yuval Oct 20 '16 at 06:55
  • 18
    New RSspec 3 syntax would be like `get my_resource_path, params: {}, headers: { 'HTTP_ACCEPT' => "application/json" }` ` – Cyril Duchon-Doris Jun 08 '17 at 20:24
  • Thanks @CyrilDuchon-Doris, yours was the only correct solution I've been able to find in order to set an auth header. – SexxLuthor Jun 21 '18 at 19:04
40

I used this in Test::Unit:

@request.env['HTTP_ACCEPT'] = "*/*, application/youtube-client"
get :index
Sytse Sijbrandij
  • 1,885
  • 2
  • 22
  • 20
  • 3
    Similarly, as Alex Soto notes in a comment on another answer, in rspec-rails controller tests, you can use: request.env["HTTP_ACCEPT"] – gerry3 Feb 10 '13 at 09:28
  • thanks a lot dude, only example that worked for me on an old 2.3 app with `ActionController::TestCase` – ecoologic Jul 16 '13 at 04:03
  • +1 I tried using a key named `Cookie` in the headers hash (because that's what my browser sends), but it didn't work. Then I did `request.keys` and saw a key named `HTTP_COOKIE`. Using that worked. They really should document this better. – Kelvin Jul 22 '13 at 17:47
  • It really works! I also found that answer in https://github.com/rspec/rspec-rails/issues/65 – Stepan Zakharov Oct 30 '14 at 09:00
  • @Sytse Sijbrandij Nobody asked about Test::Unit. Question asked about rspec. – Bryan Dimas Oct 01 '16 at 04:57
28

I'm adding this here, as I got majorly stuck trying to do this in Rails 5.1.rc1

The get method signature is slightly different now.

You need to specify the options after the path as keyword arguments, i.e.

get /some/path, headers: {'ACCEPT' => 'application/json'}

FYI, the full set of keywords arguments are:

params: {}, headers: {}, env: {}, xhr: false, as: :symbol

Jules Copeland
  • 1,690
  • 17
  • 22
21

This is working for controller specs, not request specs:

request.headers["My Header"] = "something"
slhck
  • 36,575
  • 28
  • 148
  • 201
morgoth
  • 1,357
  • 1
  • 13
  • 21
10

Using rspec with Rack::Test::Methods

header 'X_YOUR_HEADER_VAR', 'val'
get '/path'

The header var will come through as X-Your-Header-Var

marcusb
  • 612
  • 5
  • 11
10

With RSpec 3 you can use the following syntax

get my_resource_path, params: {}, headers: { 'HTTP_ACCEPT' => "application/json" }

As described in the official Rspec documentation (the link points to v3.7)

Cyril Duchon-Doris
  • 12,964
  • 9
  • 77
  • 164
9

I have to set up headers separately

request.headers["Accept"] = "application/json"

Trying sending it via get/delete/.... is complete garbage in rails4 and causing pain in my head because it is never send as header but as parameter.

{"Accept" => "application/json"}
user4694178
  • 119
  • 1
  • 1
  • 5
    Does this really provide an answer to the OP question ? If it is a new question, it is a better idea to open up a new question. – β.εηοιτ.βε Mar 20 '15 at 13:28
  • This is working for controller specs: request.headers["Accept"] = "application/json" This is working for request specs: get path, headers: {"Accept" => "application/json"} – Ivan Skotsyk Aug 01 '23 at 12:37
8

To send both xhr: true and headers, I had to do e.g.:

my_headers = { "HTTP_ACCEPT": "application/json" }
get my_path, xhr: true, headers: my_headers
Jim Stewart
  • 16,964
  • 5
  • 69
  • 89
2

Your question was already answered but in case you want to POST something to another action you have to do this:

post :save, {format: :json, application: {param1: "test", param2: "test"}}
Igor Escobar
  • 1,047
  • 1
  • 12
  • 13
2

Try something like:

get :index, :format => 'json' 
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
gayavat
  • 18,910
  • 11
  • 45
  • 55
  • Not sure, but probably works because the rails is looking for .format for that route; this happened to work for me too. – Alan Nov 05 '13 at 22:42
  • 2
    In case anyone is wondering, this just adds `format=json` as a query param. Not the same as a header field. – Kevin Carmody Oct 20 '14 at 14:39