Testing redirects with ruby

—UPDATE—
Since writing this post, I’ve put together a gem called ‘responsalizr‘ which is a way better solution than what follows in this post. Read about it here. And now back to the original post…

Testing redirects from a web app is simple enough – make a request and check the response code making sure it’s a 301, 302 or whatever you’re expecting. The test you end up writing isn’t nice idiomatic ruby though. So, I wrote a quick monkey patch… here it is:

class Net::HTTPResponse
  #returns true if the response is a 200
  def ok?
    instance_of?(Net::HTTPOK)
  end

  #returns true if the response is a 301
  def found?
    instance_of?(Net::HTTPFound)
  end

  #returns true if the response is a 302
  def moved_permanently?
    instance_of?(Net::HTTPMovedPermanently)
  end

  #returns true for any kind of redirect (301..307)
  def redirect?
    kind_of?(Net::HTTPRedirection)
  end

  #returns the url being redirected to if this response is a redirect
  def redirect_url
    redirect? ? self['location'] : raise("Not a redirect response")
  end
end

Basically, it adds the following predicate methods to the Net::HTTPResponse class: “ok?” (returns true if response code is 200), “found?” (returns true if response code is 301), “moved_permanently?” (returns true if response code is 302) and “redirect?” (returns true if the response is a redirect – from 301..307). Because these are predicate methods, they can be used by rspec – your test code suddenly becomes much cleaner! The moneky patch also adds the “redirect_url” method which returns the url to be redirected to if the response is a redirect of some sort. The advantage of this is that your tests become much more idiomatic:


#the urls we're testing with...
@url_initially_navigated_to = "http://mail.google.com"
@expected_redirect_url = "https://www.google.com/.../etc/..."

#make the request
@response= Net::HTTP.get_response(URI.parse(@url_initially_navigated_to))

#nice idiomatic tests! - use the one you're expecting...
@response.should be_ok                #expecting a 200
@response.should be_found             #expecting a 301
@response.should be_moved_permanently #expecting a 302
@response.should be_a_redirect        #expecting anything between 301..307

#testing the url being redirected to
@response.redirect_url.should match(@expected_redirect_url)

There you go! Nice idiomatic redirect tests! Enjoy.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>