what did i learn today

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, [ruby] 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('')) end end end [/ruby] 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 : [ruby] =show_for @post do |p| = p.attribute :title = p.attribute :content - if @post.comments = render :partial => 'comments' - else = t('') =content_for :sidebar do = link_to 'Edit', edit_post(@post) if is_allowed_to?(:edit) [/ruby] 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: [ruby] 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 [/ruby] Hope that this helps somebody. Or did you find a better way?

rails3 and rspec2 view testing


  • have_tag is no longer supported: use have_selector from webrat instead
  • response is deprecated, use rendered instead