RSpec testing redirect to URL with GET params RSpec testing redirect to URL with GET params ruby ruby

RSpec testing redirect to URL with GET params


From the documentation, the expected redirect path can match a regex:

expect(response).to redirect_to %r(\Ahttp://example.com)

To verify the redirect location's query string seems a little bit more convoluted. You have access to the response's location, so you should be able to do this:

response.location# => http://example.com?foo=1&bar=2&baz=3

You should be able to extract the querystring params like this:

redirect_params = Rack::Utils.parse_query(URI.parse(response.location).query)# => {"foo"=>"1", "bar"=>"2", "baz"=>"3"}

And from that it should be straightforward to verify that the redirect params are correct:

expect(redirect_params).to eq("foo" => "1", "baz" => "3", "bar" => "2")# => true

If you have to do this sort of logic more than once though, it would definitely be convenient to wrap it all up into a custom rspec matcher.


Are you able to use your route helpers rather than a plain string? If so, you can just pass hash params to a route helper and they will be converted to query string params:

root_url foo: 'bar', baz: 'quux'=> "http://www.your-root.com/?baz=quux&foo=bar"expect(response).to redirect_to(root_url(foo: 'bar', baz: 'quux'))

Does that help, or are you restricted to using strings rather than route helpers?

Another thought is that you could just assert directly on the values in the params hash rather than the url + query string, since the query string params will get serialized into the params hash...


I had a need for something similar and ended up with this:

Was able to write tests and not worry about query parameter ordering.

expect(response.location).to be_a_similar_url_to("http://example.com/?beta=gamma&alpha=delta")

Drop the following into ./spec/support/matchers/be_a_similar_url_to.rb

RSpec::Matchers.define :be_a_similar_url_to do |expected|  match do |actual|    expected_uri = URI.parse(expected)    actual_uri = URI.parse(actual)    expect(actual_uri.host).to eql(expected_uri.host)    expect(actual_uri.port).to eql(expected_uri.port)    expect(actual_uri.scheme).to eql(expected_uri.scheme)    expect(Rack::Utils.parse_nested_query(actual_uri.query)).to eql(Rack::Utils.parse_nested_query(expected_uri.query))    expect(actual_uri.fragment).to eql(expected_uri.fragment)  end  # optional  failure_message do |actual|    "expected that #{actual} would be a similar URL to #{expected}"  end  # optional  failure_message_when_negated do |actual|    "expected that #{actual} would not be a similar URL to #{expected}"  endend