I normally do not do a lot of view specs, but at least I want to make sure that my view renders without errors. And sometimes I really need to make sure that some link is shown or hidden depending on e.g. the role of the user or linked objects.
For example,
describe "posts/show.html.haml" do
context "without any comments" do
it "displays no comments" do
@post = Factory(:post)
render
rendered.should contain(I18n.t('posts.show.no_comments'))
end
end
end
So we check the rendered
result, whether it contains a specific text.
But what happens if your view is rendering different yield regions? Like a body (the default region) and a sidebar.
Let's use a view like this :
= show_for @post do |p|
= p.attribute :title
= p.attribute :content
- if @post.comments
= render :partial => 'comments'
- else
= t('posts.show.no_comments')
= content_for :sidebar do
= link_to 'Edit', edit_post(@post) if is_allowed_to?(:edit)
It renders the attributes using the show_for
gem, and then renders inside the sidebar a link if the current user is allowed to edit it.
Now I want to test what is rendered into the sidebar. To my dismay I found that neither content_for
or content_for?
worked at all inside rspec.
And rendered
does not contain the data for the other regions.
So somehow I would want to get to the content for :sidebar
.
It appears that the different regions are actually stored inside an instance variable of the view. Once I figured that out, the rest was easy:
describe "posts/show.html.haml" do
def rendered_content_for(name)
view.instance_variable_get(:@_content_for)[name]
end
context "with enough rights" do
it "displays a link to edit the post" do
@post = Factory(:post)
view.stub(:is_allowed_to?) { true }
render
rendered_content_for(:sidebar).should contain('Edit')
end
end
context "with no rights" do
it "does not display a link to edit the post" do
@post = Factory(:post)
view.stub(:is_allowed_to?) { false }
render rendered_content_for(:sidebar).should_not contain('Edit')
end
end
end
Hope that this helps somebody. Or did you find a better way?
Comments
Hi, in 2021, you can now do `view.content_for(:sidebar)`
Add comment