redirect_to_baz
メソッドを持つFoosController
があるとします。
class FoosController < ApplicationController
def redirect_to_baz
redirect_to 'http://example.com/?foo=1&bar=2&baz=3'
end
end
これを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
できます。ただし、誰かがクエリ文字列パラメーター(例:http://example.com/?bar=2&baz=3&foo=1
)を交換すると、テストは失敗します。
私は次のようなことをしたいと思います:
expect(response).to redirect_to("http://example.com/", params: { foo: 1, bar: 2, baz: 3 })
documentation を見て、response.parameters
を検索してみましたが、そのようなものは見つかりませんでした。 Hash#to_query
でもこの問題を解決できないようです。
どんな助けでも大歓迎です。
documentation から、予期されるリダイレクトパスは正規表現と一致する可能性があります。
expect(response).to redirect_to %r(\Ahttp://example.com)
リダイレクト場所のクエリ文字列を確認することは、もう少し複雑に思えます。レスポンスの場所にアクセスできるので、これを実行できるはずです。
response.location
# => http://example.com?foo=1&bar=2&baz=3
次のようにクエリ文字列パラメータを抽出できるはずです。
redirect_params = Rack::Utils.parse_query(URI.parse(response.location).query)
# => {"foo"=>"1", "bar"=>"2", "baz"=>"3"}
それから、リダイレクトパラメータが正しいことを確認するのは簡単です。
expect(redirect_params).to eq("foo" => "1", "baz" => "3", "bar" => "2")
# => true
ただし、この種のロジックを複数回実行する必要がある場合は、それをすべてカスタムのrspecマッチャーにラップすると便利です。
プレーンな文字列ではなく、ルートヘルパーを使用できますか?その場合は、ハッシュパラメータをルートヘルパーに渡すだけで、クエリ文字列パラメータに変換されます。
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'))
それは役に立ちますか、それともルートヘルパーではなく文字列の使用に制限されていますか?
もう1つの考えは、クエリ文字列paramsがparamsハッシュにシリアル化されるため、url +クエリ文字列ではなく、paramsハッシュの値を直接アサートするだけでよいということです...
私は似たようなものが必要で、これで終わりました:
テストを記述でき、クエリパラメータの順序を気にしませんでした。
expect(response.location).to be_a_similar_url_to("http://example.com/?beta=gamma&alpha=delta")
以下を./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