In Rails, how do you functional test a Javascript response format?
Asked Answered
G

9

35

If your controller action looks like this:

respond_to do |format|
  format.html { raise 'Unsupported' }
  format.js # index.js.erb
end

and your functional test looks like this:

test "javascript response..." do
  get :index
end

it will execute the HTML branch of the respond_to block.

If you try this:

test "javascript response..." do
  get 'index.js'
end

it executes the view (index.js.erb) withOUT running the controller action!

Gina answered 1/3, 2010 at 18:49 Comment(0)
G
64

Pass in a :format with your normal params to trigger a response in that format.

get :index, :format => 'js'

No need to mess with your request headers.

Gainsay answered 1/3, 2010 at 19:32 Comment(3)
Note, in Rails 3 you can use symbols, looks neater. get :index, format: :jsGoulette
@Goulette are you sure that’s not just due to Ruby 1.9?Uninterested
2016 updates: github.com/rspec/rspec-rails/issues/950 . It will raise InvalidCrossOriginRequest error. Use answer from @steven below :)Gibbons
R
26

with rspec:

it "should render js" do
  xhr :get, 'index'
  response.content_type.should == Mime::JS
end

and in your controller action:

respond_to do |format|
  format.js
end
Ramose answered 12/6, 2010 at 6:23 Comment(0)
F
5

Set the accepted content type to the type you want:

@request.accept = "text/javascript"

Combine this with your get :index test and it will make the appropriate call to the controller.

Freehanded answered 1/3, 2010 at 19:20 Comment(0)
P
5

RSpec 3.7 and Rails 5.x solution:

A few of these answers were a little outdated in my case so I decided to provide an answer for those running Rails 5 and RSpec 3.7:

it "should render js" do
  get :index, xhr: true

  expect(response.content_type).to eq('text/javascript')
end

Very similar to Steve's answer with a few adjustments. The first being xhr is passed as a boolean key/pair. Second is I now use expect due to should receiving deprecation warnings if used. Comparing the content_type of the response to be equal to text/javascript worked for me.

Papen answered 20/7, 2018 at 15:9 Comment(0)
M
3

Use this before request:

@request.env['HTTP_ACCEPT'] = 'text/javascript'
Malacology answered 1/3, 2010 at 18:52 Comment(0)
P
1

These three seem to be equivalent:

  1. get :index, :format => 'js'
  2. @request.env['HTTP_ACCEPT'] = 'text/javascript'
  3. @request.accept = "text/javascript"

They cause the controller to use a js template (e.g. index.js.erb)

Whereas simulating an XHR request (e.g. to get a HTML snippet) you can use this: @request.env['HTTP_X_REQUESTED_WITH'] = "XMLHttpRequest"

This means request.xhr? will return true.

Note that, when simulating XHR, I had to specify the expected format or I got an error:

get :index, format: "html"

Tested on Rails 3.0.3.

I got the latter from the Rails source, here: https://github.com/rails/rails/blob/6c8982fa137421eebdc55560d5ebd52703b65c65/actionpack/lib/action_dispatch/http/request.rb#L160

Pylon answered 18/5, 2011 at 11:17 Comment(1)
To simulate an XHR request, rather than messing with @request.env, better to use the provided helper: xhr :get, :index, format: "html"Condor
H
0

Use code like this for parameters and user id, etc., notice that format option is in the same hash of other parameters like id and nested_attributes.

put :update, {id: record.id, nested_attributes: {id: 1, name: "John"}, format: :js}, user.id
Havana answered 18/2, 2014 at 19:14 Comment(0)
P
0

Many of the above answers are outdated.

The correct way to do it in RSpec 3+ is post some_path, xhr: true.

Deprecation warning straight from RSpec itself, when attempting to use xhr :post, "some_path":

DEPRECATION WARNING: `xhr` and `xml_http_request` are deprecated and will be removed in Rails 5.1.
Switch to e.g. `post comments_path, params: { comment: { body: 'Honey bunny' } }, xhr: true`.

Also, xhr :post, "some_path" results in some funky errors that doesn't happen with post some_path, xhr: true.

Piling answered 5/8, 2017 at 3:20 Comment(0)
A
0

I had similar problem:

# controller
def create
  respond_to do |format|
    format.js
  end
end

# test

test "call format js" do
  record = promos(:one)
  post some_url(record)
  assert true
end

and the result was this:

> rails test
Error:
ActionController::UnknownFormat: ActionController::UnknownFormat

I fixed it with this adjusting to the test(adding headers):

test "call format js" do
  record = promos(:one)
  headers = { "accept" => "text/javascript" }
  post some_url(record), headers: headers
  assert true
end

rails (6.0.0.beta3)

Ariew answered 19/6, 2019 at 6:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.