I’ve become a big fan of rspec, and the idea of testing models, views and controllers independently of each other. View testing has for me tended to get short shrift, though; there’s not typically a lot of code in there, and who cares what it looks like, right? (kidding)I recently changed how authorization and authentication were handled on a project, though, so I really needed to make sure admin links only appeared for admins, etc. So, what I needed was a matcher for urls; does it have one in this case? Not in this other case? There’s not a url matcher built in to rspec, so I wrote one. Here it is, in case it helps you:
module ViewMatchers
A custom matcher to see if an expected url is included in the response. This one checks# the url itself, not the hyperlink text
class HaveLinkTo
def initialize(expected)
@expected = expected
end
def matches?(response)
result = false
@actual = response.body
@actual =~ /(<a\s+href="(http:\/)?(.?)#{expected}">\s((\n|.)+?)\s*<\/a>).?/
end
def failure_message
"expected #{expected.inspect}, got #{actual.inspect}"
end
def negative_failure_message
"expected #{@actual.inspect} not to include a url of #{@expected}"
end
private
attr_reader :expected
attr_reader :actual
end
A custom matcher to see if an expected url is included in the response. This one checks
the hyperlink text, not the url
class HaveLinkedText
def initialize(expected)
@expected = expected
end
def matches?(response)
@actual = response.body
@actual =~ /(<a\s+href="(http:\/)?(\/.+?)">\s((#{expected})+?)\s<\/a>).?/
end
def failure_message
"expected #{expected.inspect}, got #{actual.inspect}"
end
def negative_failure_message
"expected #{@actual.inspect} not to include a url of #{@expected}"
end
private
attr_reader :expected
attr_reader :actual
end
def have_link_to(expected)
HaveLinkTo.new(expected)
end
def have_linked_text(expected)
HaveLinkedText.new(expected)
end
end</a\s+href="(http:\></pre>
Save that into view_matchers.rb in your /lib dir, and put this at the top of your spec_helper.rb:
<pre>
<code>
config.include(ViewMatchers)
Then, in your view specs you can do things like:
response.should have_link_to(new_user_path)
response.should have_linked_text("New User")
Which is about 90% of the sort of testing I need to do with my views, so I hope that’s helpful to you.
Post a Comment