Testing content_for

March 29th, 2008

After we started writing view specs we came across views similar to this:

<p>Stuff in the main content area</p>

<% content_for "secondary_content" do %>
  <p>Stuff that will go in an side panel in the view </p>
<% end %>

Obviously when rendering the view inside the spec, only the blurb about main content area will be in the response.body. For instance the second spec written will fail:

describe "/path/to/view" do
  def do_render
    render "/path/to/view"
  end

  it "should have blurb about main content" do
    do_render
    response.should have_text(/main content/i)
  end

  ##
  # This won't pass.
  ##
  it "should have blub about side panel" do
    do_render
    response.should have_text(/side panel/i)
  end
end

However, you can shove something in your spec_helpers.rb to test items inside the content_for blocks.

def content_for(section)
  template.send(:instance_variable_get, "@content_for_#{section}") || ""
end

And rewrite your spec like this:

describe "/path/to/view" do
  def do_render
    render "/path/to/view"
  end

  it "should have blurb about main content" do
    do_render
    response.should have_text(/main content/i)
  end

  ##
  # This will now pass
  ##
  it "should have blub about side panel" do
    do_render
    content_for("secondary_content").should match(/side panel/i)
  end
end

The have_text() matcher won't work, but you can use the have_tag().

If you haven't toyed with content_for, I suggest looking into it. It will help clean and organize your views and layout(s).

1 Response to “Testing content_for”

  1. Zach Dennis Says:

    Another way to do this is to use a testing layout and then specify the layout option when you render. For example: render “foo”, :layout => “testing”. The testing layout would have a “yield :secondary_content” for the content_for block and also a generic yield.

    Granted if you have a lot of content_for blocks you’ll end up with a lot of yield calls in your testing layout, but that doesn’t cause any issues because they just don’t render anything. In the past I’ve just kept one testing layout file, rather then one for each content_for block.

    Thanks for sharing,

Sorry, comments are closed for this article.