One of the many great things about Rspec is that it allows you to test helper methods. Helpers can be complex at times. And when it matters, they definitely need some testing love.
An example of a typical helper may be something like:
def h1(text) "<h1 class='heading'>#{text}</h1>" end
Then you can do <%=h1 'Text Here' -%> in your views. That’s trivial to test, so I won’t go into that. The tricky tests (I think) deal with block helpers. Block helpers are extremely useful and can improve the readability of what’s going on in your view(s). Probably the most useful case is when you have <% if current_user.admin? %> scattered all over the place. Wouldn’t it be better (and DRYer) to wrap that “admin condition” up in one place?
def content_for_admin(&block) yield if current_user.admin? end
Pretty simple. But, how would you test that? Initially, I had somewhat of a hard time writing tests to see if the block was actually yielded or not. Here’s what I do now, but I’m open to (and seeking more) alternatives. Using the content_for_admin helper as the guinea pig:
describe ApplicationHelper do attr_accessor :_erbout fixtures :users before(:each) do self._erbout = '' @block = "This is the block content" @current_user = users(:admin) end # current_user.admin? # => true it "should yield block for an admin" do should_receive(:current_user).and_return(@current_user) @current_user.should_receive(:admin?).and_return(true) html = content_for_admin do self._erbout << "<div>#{@block}</div>" end html.should have_tag('div', @block) end # current_user.admin? # => false it "should not yield block for a non-admin" do should_receive(:current_user).and_return(@current_user) @current_user.should_receive(:admin?).and_return(false) html = content_for_admin do self._erbout << "<div>#{@block}</div>" end html.should_not have_tag('div', @block) end end
Another, similar, approach is to use eval_erb, which let’s you actually write out the ERB as a string (or heredoc) and evaluate the output. I think that’s a little messy, but then again, I’ve never actually tried it.
But other than that, this is the only way I know to test the yielded output of a block helper with Rspec. Do you know of a better way? Or at least, a different way?






Comments
Thanks for that Ryan l playing with something similar but had not got it yet. Made life a lot easier.
Thanks