Disons que j'ai un FoosController
avec un redirect_to_baz
méthode.
class FoosController < ApplicationController
def redirect_to_baz
redirect_to 'http://example.com/?foo=1&bar=2&baz=3'
end
end
Je teste cela avec spec/controllers/foos_controller_spec.rb
:
require 'spec_helper'
describe FoosController, :type => :controller do
describe "GET redirect_to_baz" do
it "redirects to example.com with params" do
get :redirect_to_baz
expect(response).to redirect_to "http://example.com/?foo=1&bar=2&baz=3"
end
end
end
Ça marche. Cependant, si quelqu'un échange les paramètres de la chaîne de requête (par exemple http://example.com/?bar=2&baz=3&foo=1
), le test échoue.
Je voudrais faire quelque chose comme:
expect(response).to redirect_to("http://example.com/", params: { foo: 1, bar: 2, baz: 3 })
J'ai regardé le documentation et j'ai essayé de rechercher response.parameters
, mais je n'ai rien trouvé de tel. Même Hash#to_query
ne semble pas résoudre ce problème.
Toute aide serait grandement appréciée.
Dans documentation , le chemin de redirection attendu peut correspondre à une expression régulière:
expect(response).to redirect_to %r(\Ahttp://example.com)
Pour vérifier la chaîne de requête de l'emplacement de redirection, cela semble un peu plus compliqué. Vous avez accès à l'emplacement de la réponse, vous devriez donc pouvoir le faire:
response.location
# => http://example.com?foo=1&bar=2&baz=3
Vous devriez pouvoir extraire les paramètres de chaîne de requête comme ceci:
redirect_params = Rack::Utils.parse_query(URI.parse(response.location).query)
# => {"foo"=>"1", "bar"=>"2", "baz"=>"3"}
Et à partir de là, il devrait être simple de vérifier que les paramètres de redirection sont corrects:
expect(redirect_params).to eq("foo" => "1", "baz" => "3", "bar" => "2")
# => true
Si vous devez faire ce type de logique plus d'une fois, il serait certainement pratique de tout regrouper dans un matcher rspec personnalisé.
Êtes-vous en mesure d'utiliser vos aides d'itinéraire plutôt qu'une simple chaîne? Si c'est le cas, vous pouvez simplement passer des paramètres de hachage à un assistant d'itinéraire et ils seront convertis en paramètres de chaîne de requête:
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'))
Cela vous aide-t-il ou êtes-vous limité à utiliser des chaînes plutôt que des aides de route?
Une autre pensée est que vous pouvez simplement affirmer directement sur les valeurs du hachage des paramètres plutôt que sur la chaîne de requête url +, car les paramètres de la chaîne de requête seront sérialisés dans le hachage des paramètres ...
J'avais besoin de quelque chose de similaire et je me suis retrouvé avec ceci:
A pu écrire des tests et ne pas se soucier de l'ordre des paramètres de requête.
expect(response.location).to be_a_similar_url_to("http://example.com/?beta=gamma&alpha=delta")
Déposez ce qui suit dans ./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}"
end
end