Rspec test to render no layout - ruby-on-rails

I can test my controller to render a certain layout with
expect { get :index }.to render_template(layout: 'my_layout')
But how can I test the controller to render NO layout?
The following first expectation passes, but be careful: the second expectation also passes! (testing the same code)
expect { get :index }.to render_template(layout: false)
expect { get :index }.to render_template(layout: true)
In Nov 2008, #david-chelimsky said:
One way I've handled this successfully is to integrate_views for this
one example (in its own group) and specify that html elements from the
layout are not present in the form. It's a brittle example, but it's
only one.
I dont want to check the rendered view, but I did not find any better solution so far.
Does someone has a good approach?

In my tests when there is no layout I just check if it is not loading "application" layout
expect { get :index }.to_not render_template(layout: "application")

While not a pretty one liner (you can always add a helper method), I've found that you can do this:
get :index
#templates.keys.should include(nil)
I tested this and it only works when I set layout false. Based on the implementation of assert_template it gathers some information in to instance variables. The relevant ones are #templates and #layouts - each is a hash keyed by a string corresponding with how many times it was rendered.
#templates will contain the template used for your action (e.g "users/show") but #layouts will only list layouts. If no layout was used, it looks like {nil=>1}. This seems the only thing you can tap in to.
So maybe it might be nice to make a helper method or custom matcher to do this.

I did it using this one liner
expect { get :index }.to render_template(layout: [])
Versions: Rspec = 3.4.0 , Rails ~> 4.2.5

Related

In Rspec, how test a controller action that does not have a route?

In a few of my controllers I have an action that does not have a corresponding route because it is accessed only via a render ... and return in other controller actions.
For example, I have an action
def no_such_page
# displays a generic error screen
end
In my RSpec controller test, how do I 'get' that method and look at the response body?
If I try:
get :no_such_page
response.status.should be(200)
it of course gives the error
No route matches {:controller=>"foo", :action=>"{:action=>:no_such_page}"}
Update
Looking back over your question, it doesn't make sense to me now since you say that you are only accessing this action via render ... and return, but render renders a view, not an action. Are you sure that you even need this action? I think a view spec is the place for this test.
Original answer
It doesn't make sense to test the response code of an action which will never be called via an HTTP request. Likewise get :no_such_page doesn't make sense as you can't "get" the action (there is no route to it), you can only call the method.
In that sense, the best way to test it would be to treat it just like any other method on a class, in this case the class being your controller, e.g. PostsController. So you could do something like this:
describe PostsController do
... other actions ...
describe "no_such_page" do
it "displays a generic error screen" do
p = PostsController.new
p.should_receive(:some_method).with(...)
p.no_such_page
end
end
end
But in fact, judging from what you've written, it sounds to me like your action has nothing in it, and you're just testing the HTML output generated by the corresponding view. If that's the case, then you really shouldn't be testing this in controller specs at all, just test it using a view spec, which is more appropriate for testing the content of the response body.
before :all do
Rails.application.routes.draw do
get '/no_such_page', to: "foo#no_such_page"
end
end
after :all do
Rails.application.reload_routes!
end

How do you test render_remote_content receives the correct locals

In a controller spec, I'm trying to test that a controller action calling render_remote_content renders the right partial with the correct.
Currently, I'm trying to do something like:
response.should render_template(partial: "path/to/_template", locals: {local_array: []})
This causes rspec to blow up in assert_template. I'd prefer to avoid stubbing render methods.
Anyone have any good ideas on how to accomplish this?
Rails 3.1
RSpec 2.7
When you are checking for locals, it appears that there is a bug in the rspec code, and you have to drop the underscore in the partial name.
Specifically:
response.should render_template(partial: "path/to/template", locals: {local_array: []})
will work, but your example will not.
EDIT:
This issue is actually in assert_template, since render_template delegates to that. This issue is being tracked here: https://github.com/rails/rails/issues/8516

Using Factory Girl with Rspec Views

So I want to test some views using Rspec and Factory Girl, but I don't know how to assign a factory to a view properly. All of the information I see online uses stubbing, and although stubbing is fine, I want to keep my rspec stuff somewhat consistent.
I want to use a factory for an edition model and associate that with the page when I render the page, but everything I've considered seems to be broken. Here's sort of a ridiculous example:
require 'spec_helper'
describe "catalog/editions/rationale.html.haml" do
before do
#edition = Factory.create(:edition)
assign(:editions, #edition)
render :action => 'rationale', :id => #edition
end
context "GET rationale" do
it "should not have the preamble to the United States constitution" do
rendered.should_not contain(/We the People of the United States/)
end
end
end
In this I've tried changing render :action => 'rationale', :id => #edition to just render, and other similar tweaks to the render action. I just have no idea where to start a factory_girl helped view. Any help would be greatly appreciated.
Versions:
Rails 3.0.10
RSpec 2.7
Factory_Girl 2.2
I think the error is that #editions is expecting an array, so you should write
assign(:editions, [#edition])
or, otherwise, if it should be a single element, you should write:
assign(:edition, #edition)
Secondly, unless your view is a partial that expects variables, you should just write
render
You do not have to give the action, rspec knows which view to render from the describe, and the view does not retrieve any data (so you don't have to set the id), you just have to set the instance variables correctly using the assigns. Testing the view does nothing more than rendering the view.
Hope this helps.
Now that you've got the answer, stop writing view specs. They are needlessly hard to write, and they really don't test enough to be at all worthwhile. Do your view and controller testing with Cucumber instead.

stubbing helpers using mocha

it "should have edit button if user has permission to edit" do
EntitiesHelper.stubs(:permission_to_edit_entity?).returns(true)
get :index
#entities[0..3].each do |entity|
response.should have_selector("form",
:method => "get",
:action => "/entities/edit/#{entity[:id]}") do |form|
form.should have_selector("input", :value => "Edit")
end
end
end
I am trying to write a simple test case which tests that an edit button is showed if the user has permission to edit. I am trying to use stubbing for this. However, it doesn't seem to work. The output view does not show the edit button next to every single entity which I would expect if the stubbing works. I am new to mocha and stubbing - I am doing something wrong here?
Thanks!
I assume EntitiesHelper is a plain-old rails helper that gets mixed into the controller - thus all it's instance methods (such as permission_to_edit_entity?) are available to the controller and views have access to these helper methods (via the controller) ... so You might stub the method on the controller :
controller.stubs(:permission_to_edit_entity?).returns(true)
in this particular case I would even consider changing the stub to mock since You expect the method to be called (although You're testing the button presence, it's good to know that the flow did not happen as expected) :
controller.expects(:permission_to_edit_entity?).returns(true)
but this of course is debatable and You should be fine either way ...

Rails 3 - Rendering layout corrupts tests

I define a function called location on wsp_controller:
def location
#title ="Edit account"
#page_name = "edit"
end
And it works fine. But when I try to render a layout like this:
def location
#title ="Edit account"
#page_name = "edit"
render :layout => 'signup_login'
end
RSpec tests start to fail. However, the app does what is supposed but the tests fail.
I have javascript code in the layout that I need to run when I go to /location, if I put the javascripts on the application layout, it works (tests and app), however there's no need to put it there, so I want a new layout and render it.
How can I do that?
Edit: Here's what I have in the routes.rb
match '/wsps/:id/location', :to =>'wsps#location'
Thanks.
Edit:
Some of the RSpec errors:
Failures:
1) WspsController GET 'index' for non-signed-in wsps should deny access to 'index'
Failure/Error: get :index
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.errors
It simple doesn't pass the tests when I render the layout. But it's only in that method.
You might need to provide a bit more info about the failures that you're getting. You mention that you have javascript that needs to run when the page is rendered? Don't forget that in your functional tests the page is rendered as html, but there isn't a real browser used, so no javascript is run. For tests that involve javascript you should look at something like Cucumber to define some acceptance tests, combined with something like Watir, or Selenium to drive a browser.

Resources