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.
Related
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
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
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 ...
Using rspec, is it possible to test a view to make sure all the syntax in the view doesn't have any errors?
Views call helpers, they might reference controller/action names like controller => 'blah', action => 'show' etc.
If I rename/delete a controller I want to make sure that if my views reference them, I have a test that will fail.
A couple of things:
1) I wouldn't recommend using :controller or :action anywhere in your views, because RESTful helpers are much shorter. For instance:
:controller => :projects, :action => "show", :id => 1
vs.
project_path(1)
2) Rather than testing for syntax errors this way, have proper integration tests which test your application, performing the same actions a user would. Commonly, this is provided by RSpec+Capybara or Cucumber.
Now that we have the formalities out of the way, you can change the describe of your controller tests to this:
describe ProjectsController
render_views
By default, views in RSpec controller tests are stubbed out, meaning they are not accessed at all. By putting render_views inside your describe (or context) blocks, you enable this option.
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.