OSDN Git Service

add rspec-rails
[praisedb/praisedb.git] / vendor / plugins / rspec-rails / lib / spec / rails / matchers / redirect_to.rb
1 module Spec
2   module Rails
3     module Matchers
4
5       class RedirectTo  #:nodoc:
6
7         include ActionController::StatusCodes
8
9         def initialize(request, expected)
10           @expected = expected
11           @request = request
12         end
13
14         def matches?(response_or_controller)
15           response  = response_or_controller.respond_to?(:response) ?
16                       response_or_controller.response :
17                       response_or_controller
18
19           @redirected = response.redirect?
20           @actual = response.redirect_url
21           return false unless @redirected
22
23           if @expected_status
24             @actual_status = interpret_status(response.code.to_i)
25             @status_matched = @expected_status == @actual_status
26           else
27             @status_matched = true
28           end
29
30           if @expected.instance_of? Hash
31             return false unless @actual =~ %r{^\w+://#{@request.host}}
32             return false unless actual_redirect_to_valid_route
33             return actual_hash == expected_hash && @status_matched
34           else
35             return @actual == expected_url && @status_matched
36           end
37         end
38
39         def actual_hash
40           hash_from_url @actual
41         end
42
43         def expected_hash
44           hash_from_url expected_url
45         end
46
47         def actual_redirect_to_valid_route
48           actual_hash
49         end
50
51         def hash_from_url(url)
52           query_hash(url).merge(path_hash(url)).with_indifferent_access
53         end
54
55         def path_hash(url)
56           path = url.sub(%r{^\w+://#{@request.host}(?::\d+)?}, "").split("?", 2)[0]
57           ActionController::Routing::Routes.recognize_path path, { :method => :get }
58         end
59
60         def query_hash(url)
61           query = url.split("?", 2)[1] || ""
62           Rack::Utils.parse_query(query)
63         end
64
65         def with(options)
66           @expected_status = interpret_status(options[:status])
67           self
68         end
69         
70        def expected_url
71           case @expected
72             when Hash
73               return ActionController::UrlRewriter.new(@request, {}).rewrite(@expected)
74             when :back
75               return @request.env['HTTP_REFERER']
76             when %r{^\w+://.*}
77               return @expected
78             else
79               return "http://#{@request.host}" + (@expected.split('')[0] == '/' ? '' : '/') + @expected
80           end
81         end
82
83         def failure_message_for_should
84           if @redirected
85             if @status_matched
86               return %Q{expected redirect to #{@expected.inspect}, got redirect to #{@actual.inspect}}
87             else
88               return %Q{expected redirect to #{@expected.inspect} with status #{@expected_status}, got #{@actual_status}}
89             end
90           else
91             return %Q{expected redirect to #{@expected.inspect}, got no redirect}
92           end
93         end
94
95         def failure_message_for_should_not
96             return %Q{expected not to be redirected to #{@expected.inspect}, but was} if @redirected
97         end
98
99         def description
100           "redirect to #{@expected.inspect}"
101         end
102       end
103
104       # :call-seq:
105       #   response.should redirect_to(url)
106       #   response.should redirect_to(:action => action_name)
107       #   response.should redirect_to(:controller => controller_name, :action => action_name)
108       #   response.should_not redirect_to(url)
109       #   response.should_not redirect_to(:action => action_name)
110       #   response.should_not redirect_to(:controller => controller_name, :action => action_name)
111       #
112       # Passes if the response is a redirect to the url, action or controller/action.
113       # Useful in controller specs (integration or isolation mode).
114       #
115       # == Examples
116       #
117       #   response.should redirect_to("path/to/action")
118       #   response.should redirect_to("http://test.host/path/to/action")
119       #   response.should redirect_to(:action => 'list')
120       def redirect_to(opts)
121         RedirectTo.new(request, opts)
122       end
123     end
124
125   end
126 end