An RJS Redirect Matcher for rspec
You know what’s stupid? Clumsily checking for a javascript redirect in your RJS with this kind of shit:
it "should redirect to the collaborative quote screen" do xhr :post, 'attach', :attachment_id => '4023' response.body.should =~ /window\.location\.href = \"/collabquote\";" end
Not only is this ugly, but it ties your test to a particular route, rather than allowing you to use your named route. So I whipped up a custom RJS redirect matcher in about 10 minutes following the guidelines in this post, and I was surprised how easy it was. It should be pretty self explanatory.
module RedirectViaRjsToMatcher class RedirectViaRjsTo def initialize(expected) @expected = expected end def matches?(target) @target = target @url = target.body.split('"')[1] @target.body == "window.location.href = \"#{@expected}\";" end def failure_message "expected redirect via rjs to #{@expected}, redirected instead to #{@url}" end def negative_failure_message "unexpected redirect via rjs to #{@expected}" end end # Actual matcher that is exposed def redirect_via_rjs_to(expected) RedirectViaRjsTo.new(expected) end end
All you need to do is save this file in /spec/custom/redirect_via_rjs_to.rb and include it in /spec/spec_helper.rb like so:
require 'spec/be_the_same_as' Spec::Runner.configure do |config| config.include(RedirectViaRjsToMatcher) end
Voilla! It really is that easy, and turns that first spec into something a bit more readable and reusable:
it "should redirect to the collaborative quote screen" do xhr :post, 'attach', :attachment_id => '4023' response.should redirect_via_rjs_to quote_path(@quote) end
UPDATE: Jim clued me into simple_matcher, which appears to be yet another very easy way to create custom matchers.