Permalink
Browse files

Add basic request redirection specs

  • Loading branch information...
1 parent 81679d4 commit 985eb532f8e2a133fd8a387792bbb65f106a9b22 @nbibler nbibler committed Mar 7, 2012
Showing with 177 additions and 0 deletions.
  1. +86 −0 spec/rack/canonical_host_spec.rb
  2. +5 −0 spec/spec_helper.rb
  3. +86 −0 spec/support/redirect.rb
@@ -0,0 +1,86 @@
+require 'spec_helper'
+
+require 'rack'
+require 'uri'
+
+require 'rack-canonical-host'
+
+describe Rack::CanonicalHost do
+ context '#call' do
+ let(:requested_uri) { URI.parse('http://myapp.com/test/path') }
+ let(:env) { Rack::MockRequest.env_for(requested_uri.to_s) }
+ let(:response) { stack(requested_uri.host).call(env) }
+
+ subject { response }
+
+ context 'with a request to a matching host' do
+ it { should_not redirect }
+
+ it 'calls up the stack with the received env' do
+ parent_app.should_receive(:call).with(env).and_return(parent_response)
+ subject
+ end
+ end
+
+ context 'with a request to a non-matching host' do
+ let(:response) { stack('new-host.com').call(env) }
+
+ it { should redirect.via(301) }
+ it { should redirect.to('http://new-host.com/test/path') }
+
+ it 'does not call further up the stack' do
+ parent_app.should_receive(:call).never
+ subject
+ end
+ end
+
+ context 'when initialized with a block' do
+ let(:block) { Proc.new { |env| "block-host.com" } }
+ let(:response) { stack(&block).call(env) }
+
+ context 'with a request to a host matching the block result' do
+ let(:requested_uri) { URI.parse('http://block-host.com') }
+
+ it { should_not redirect }
+
+ it 'calls up the stack with the received env' do
+ parent_app.should_receive(:call).with(env).and_return(parent_response)
+ subject
+ end
+ end
+
+ context 'with a request host that does not match the block result' do
+ let(:requested_uri) { URI.parse('http://block-host.com') }
+ let(:env) { Rack::MockRequest.env_for('http://different-host.com/path') }
+
+ it { should redirect.via(301) }
+ it { should redirect.to('http://block-host.com/path') }
+
+ it 'does not call further up the stack' do
+ parent_app.should_receive(:call).never
+ subject
+ end
+ end
+ end
+ end
+
+
+ private
+
+
+ def parent_response
+ [200, {'Content-Type' => 'text/plain'}, 'Success']
+ end
+
+ def parent_app
+ @parent_app ||= Proc.new { |env| parent_response }
+ end
+
+ def stack(host = nil, parent_app = parent_app, &block)
+ Rack::Builder.new do
+ use Rack::Lint
+ use Rack::CanonicalHost, host, &block
+ run parent_app
+ end
+ end
+end
View
@@ -4,6 +4,11 @@
# loaded once.
#
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+
+Dir[File.expand_path('../support/**/*.rb', __FILE__)].each do |support|
+ require support
+end
+
RSpec.configure do |config|
config.treat_symbols_as_metadata_keys_with_true_values = true
config.run_all_when_everything_filtered = true
View
@@ -0,0 +1,86 @@
+module Redirect
+ class Matcher
+ attr_reader :expected_status_code
+ attr_reader :expected_location
+ attr_reader :response
+ attr_reader :status_code
+ attr_reader :location
+
+ def matches?(response)
+ @response = response
+ @status_code = @response.to_a.first
+ @location = @response.to_a[1]['Location']
+
+ status_code_matches? && location_matches?
+ end
+
+ def via(expected_status_code)
+ @expected_status_code = expected_status_code
+ self
+ end
+
+ def to(expected_location)
+ @expected_location = expected_location
+ self
+ end
+
+ def description
+ case
+ when expected_status_code && expected_location
+ "return a #{expected_status_code} to \"#{expected_location}\" response"
+ when expected_status_code
+ "return a #{expected_status_code} status response"
+ when expected_location
+ "return a Location header containing \"#{expected_location}\""
+ else
+ "return a redirection response"
+ end
+ end
+
+ def failure_message_for_should
+ case
+ when expected_status_code && !status_code_matches?
+ "expected #{status_code} to be #{expected_status_code}"
+ when expected_location && !location_matches?
+ "expected #{location.inspect} to be \"#{expected_location}\""
+ else
+ "expected #{status_code} to be a redirection code (301, 302, 303, 307)"
+ end
+ end
+
+ def failure_message_for_should_not
+ case
+ when expected_status_code && status_code_matches?
+ "expected #{status_code} to not be #{expected_status_code}"
+ when expected_location && location_matches?
+ "expected #{location.inspect} to not be \"#{expected_location}\""
+ else
+ "expected #{status_code} to not be a redirection code (301, 302, 303, 307)"
+ end
+ end
+
+
+ private
+
+
+ def status_code_matches?
+ if expected_status_code
+ expected_status_code == status_code
+ else
+ status_code.to_s =~ /^30[1237]$/
+ end
+ end
+
+ def location_matches?
+ !expected_location || (expected_location == location)
+ end
+ end
+
+ def redirect
+ Matcher.new
+ end
+end
+
+RSpec.configure do |config|
+ config.include(Redirect)
+end

0 comments on commit 985eb53

Please sign in to comment.