51

I want to test rendering a particular partial according to some conditions.

For example, in model show action view show.html.erb I have:

<% if condition1 %>
 <%=  render :partial => "partial1" %>
<% else %>
 <%=  render :partial => "partial1" %>
<% end %>

I tried:

response.should render_template("partial_name")

but it tells that it rendered "show" template

expecting <"partial1"> but rendering with <"model/show, layouts/application">

What I am doing wrong?

Bryan Ash
  • 4,385
  • 3
  • 41
  • 57
Pavel
  • 3,900
  • 6
  • 32
  • 41
  • 3
    https://www.relishapp.com/rspec/rspec-rails/v/2-8/docs/view-specs/view-spec – apneadiving Mar 30 '12 at 16:19
  • 1
    I need to test in controller_spec – Pavel Mar 31 '12 at 20:32
  • `render_template` delegates to `assert_template` in [action_controller/test_case.rb](https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/test_case.rb#L67) so that's where the most detailed documentation lives – Jared Beck Mar 07 '14 at 15:37

7 Answers7

71

Also try this

response.should render_template(:partial => 'partial_name')
Rishav Rastogi
  • 15,484
  • 3
  • 42
  • 47
  • 9
    It works, but you need to specify `render_views` if you're writing controller specs. – Fabio Apr 23 '12 at 16:08
  • Can you expand on the render_views thing? render_template isn't working for me in controller tests. – Abe Petrillo Feb 12 '13 at 16:15
  • 3
    `render_views` is simply called within the describe block.`describe OrganizationsController do; render_views; ...` – aNoble Apr 07 '13 at 19:11
  • 23
    With the latest version of rpec it may look more like this `expect(response).to render_template(:partial => '_partial_name')` – rouan Apr 12 '13 at 05:50
  • 3
    Here's some documentation regarding `render_views`: https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs/render-views – aceofbassgreg May 24 '13 at 17:36
  • Latest rspec will pass with `expect(response).to render_partial("partial_name")` rouan's approach also works. – c.apolzon May 30 '13 at 18:06
  • @c.apolzon I got undefined method 'render_partial' using today's updated rspec-rails ~> 2.14.0 and shoulda-matchers git-branch dp-rails-four. What gem are you using to get `render_partial` matcher? Thanks – Benjamin Bouchet Aug 01 '13 at 22:58
  • For rspec `3.6.0` use `expect(response).to render_partial("_partial_name")` but you have to use `render_views` within `describe`. Mind the `_` in the name of the partial – Amit Patel Nov 28 '17 at 12:56
34

Latest rspec version suggest to use expect syntax rather than should:

expect(response).to render_template(partial: 'partial_name')
Seb Wilgosz
  • 1,240
  • 15
  • 24
7

If you are testing this inside a controller you should do something like this:

RSpec.describe Users::RegistrationsController, type: :controller do
  describe "GET #new" do
    render_views

    it "render customer partial" do
      get :new
      expect(response).to render_template :new
      expect(response).to render_template(partial: '_new_customer')
    end
  end
end

Note that we need render_views as reported into documentation.

And this is the line that will test if "_new_customer" partial is rendered:

expect(response).to render_template(partial: '_new_customer')

You need to provide the name of the partial with the initial underscore.

Also be careful because in your code the IF and the ELSE statements are rendering the same thing.

Diego D
  • 1,706
  • 19
  • 23
  • Should you really be testing a view in a controller spec? RSpec provides spec/views for this; or you could use feature/integration tests. – Kris Khaira Nov 16 '17 at 12:22
  • @KrisKhaira well, may you need both. In a controller spec you could test that the controller is going to render the expected template/view. Then in feature/integration tests you can deeply test the whole floe, in particular the view to test if user is able to perform expected actions. – Diego D Nov 17 '17 at 13:28
1

If using in rspec controllers

expect(response).to render_template(partial: 'home/_sector_performance')
1

You can also test, if your controller inferred required action.

require "spec_helper"

describe "model_name/new.html.erb" do
 it "infers the controller path" do
  expect(controller.request.path_parameters["action"]).to eq("new")
 end
end

The docs are here

Dende
  • 545
  • 6
  • 19
0

Starting from Rails 5.1, this kind of test is discouraged and you should test the controller and the view as a whole.

Checking which partial is rendered by the controlled is part of the implementation details you shouldn't test.

Therefore I suggest you to write a request test and check that some relevant text of your partial is present in the response body.

get root_path
expect(CGI.unescape_html(response.body)).to include('Hello World')
coorasse
  • 5,278
  • 1
  • 34
  • 45
-4

Instead of the above mentioned solution you could check alternatively, if the html that the partial renders is present. E.g.

response.body.should have_tag("div#foo")
auralbee
  • 8,741
  • 4
  • 29
  • 36
  • 2
    that would be a pretty fragile test -- such that the test would fail if you changed the html, but what you're really testing is whether or not the template gets rendered. – jbielick Apr 02 '15 at 16:47
  • Spec should test test rendering partial, not html body. – Argonus Dec 06 '16 at 09:53