public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Simplify the implementation of assert_redirected_to to normalise the urls before 
comparing.  Also allows for a simpler implementation of redirect_to without most 
of the recursion.

Also allows for assert_redirected_to @some_record
NZKoz (author)
Mon Jun 23 09:46:15 -0700 2008
commit  c3aaba0180f0710094d974b4ba4659bce81446df
tree    bed34c6b4caa1952dabba71af6f95dae02322af4
parent  db5839107951b000633fa8405f78e5c315b6656a
...
18
19
20
 
 
 
 
 
21
22
23
...
18
19
20
21
22
23
24
25
26
27
28
0
@@ -18,6 +18,11 @@
0
 
0
 * Made ActionView::Base#render_file private [Josh Peek]
0
 
0
+* Refactor and simplify the implementation of assert_redirected_to.  Arguments are now normalised relative to the controller being tested,  not the root of the application.  [Michael Koziarski]
0
+
0
+  This could cause some erroneous test failures if you were redirecting between controllers
0
+  in different namespaces and wrote your assertions relative to the root of the application.
0
+
0
 * Remove follow_redirect from controller functional tests.
0
 
0
   If you want to follow redirects you can use integration tests.  The functional test
...
56
57
58
 
 
 
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
 
 
124
125
126
127
 
 
128
129
130
...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
 
 
 
 
 
 
 
 
 
 
 
 
 
170
171
172
...
56
57
58
59
60
61
62
63
64
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
67
68
 
 
 
69
70
71
72
73
...
93
94
95
 
 
 
 
 
 
 
 
 
 
 
 
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
0
@@ -56,75 +56,18 @@ module ActionController
0
       #   # assert that the redirection was to the named route login_url
0
       #   assert_redirected_to login_url
0
       #
0
+      #   # assert that the redirection was to the url for @customer
0
+      #   assert_redirected_to @customer
0
+      #
0
       def assert_redirected_to(options = {}, message=nil)
0
         clean_backtrace do
0
           assert_response(:redirect, message)
0
           return true if options == @response.redirected_to
0
-          ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
0
-
0
-          begin
0
-            url  = {}
0
-            original = { :expected => options, :actual => @response.redirected_to.is_a?(Symbol) ? @response.redirected_to : @response.redirected_to.dup }
0
-            original.each do |key, value|
0
-              if value.is_a?(Symbol)
0
-                value = @controller.respond_to?(value, true) ? @controller.send(value) : @controller.send("hash_for_#{value}_url")
0
-              end
0
-
0
-              unless value.is_a?(Hash)
0
-                request = case value
0
-                  when NilClass    then nil
0
-                  when /^\w+:\/\// then recognized_request_for(%r{^(\w+://.*?(/|$|\?))(.*)$} =~ value ? $3 : nil)
0
-                  else                  recognized_request_for(value)
0
-                end
0
-                value = request.path_parameters if request
0
-              end
0
-
0
-              if value.is_a?(Hash) # stringify 2 levels of hash keys
0
-                if name = value.delete(:use_route)
0
-                  route = ActionController::Routing::Routes.named_routes[name]
0
-                  value.update(route.parameter_shell)
0
-                end
0
-
0
-                value.stringify_keys!
0
-                value.values.select { |v| v.is_a?(Hash) }.collect { |v| v.stringify_keys! }
0
-                if key == :expected && value['controller'] == @controller.controller_name && original[:actual].is_a?(Hash)
0
-                  original[:actual].stringify_keys!
0
-                  value.delete('controller') if original[:actual]['controller'].nil? || original[:actual]['controller'] == value['controller']
0
-                end
0
-              end
0
-
0
-              if value.respond_to?(:[]) && value['controller']
0
-                value['controller'] = value['controller'].to_s
0
-                if key == :actual && value['controller'].first != '/' && !value['controller'].include?('/')
0
-                  new_controller_path = ActionController::Routing.controller_relative_to(value['controller'], @controller.class.controller_path)
0
-                  value['controller'] = new_controller_path if value['controller'] != new_controller_path && ActionController::Routing.possible_controllers.include?(new_controller_path) && @response.redirected_to.is_a?(Hash)
0
-                end
0
-                value['controller'] = value['controller'][1..-1] if value['controller'].first == '/' # strip leading hash
0
-              end
0
-              url[key] = value
0
-            end
0
-
0
-            @response_diff = url[:actual].diff(url[:expected]) if url[:actual]
0
-            msg = build_message(message, "expected a redirect to <?>, found one to <?>, a difference of <?> ", url[:expected], url[:actual], @response_diff)
0
-
0
-            assert_block(msg) do
0
-              url[:expected].keys.all? do |k|
0
-                if k == :controller then url[:expected][k] == ActionController::Routing.controller_relative_to(url[:actual][k], @controller.class.controller_path)
0
-                else parameterize(url[:expected][k]) == parameterize(url[:actual][k])
0
-                end
0
-              end
0
-            end
0
-          rescue ActionController::RoutingError # routing failed us, so match the strings only.
0
-            msg = build_message(message, "expected a redirect to <?>, found one to <?>", options, @response.redirect_url)
0
-            url_regexp = %r{^(\w+://.*?(/|$|\?))(.*)$}
0
-            eurl, epath, url, path = [options, @response.redirect_url].collect do |url|
0
-              u, p = (url_regexp =~ url) ? [$1, $3] : [nil, url]
0
-              [u, (p.first == '/') ? p : '/' + p]
0
-            end.flatten
0
+          redirected_to_after_normalisation = normalize_argument_to_redirection(@response.redirected_to)
0
+          options_after_normalisation       = normalize_argument_to_redirection(options)
0
 
0
-            assert_equal(eurl, url, msg) if eurl && url
0
-            assert_equal(epath, path, msg) if epath && path
0
-          end
0
+          assert_equal redirected_to_after_normalisation, options_after_normalisation,
0
+                       "Expected response to be a redirect to <#{options_after_normalisation}> but was a redirect to <#{redirected_to_after_normalisation}>"
0
         end
0
       end
0
 
0
@@ -150,23 +93,24 @@ module ActionController
0
       end
0
 
0
       private
0
-        # Recognizes the route for a given path.
0
-        def recognized_request_for(path, request_method = nil)
0
-          path = "/#{path}" unless path.first == '/'
0
-
0
-          # Assume given controller
0
-          request = ActionController::TestRequest.new({}, {}, nil)
0
-          request.env["REQUEST_METHOD"] = request_method.to_s.upcase if request_method
0
-          request.path   = path
0
-
0
-          ActionController::Routing::Routes.recognize(request)
0
-          request
0
-        end
0
 
0
         # Proxy to to_param if the object will respond to it.
0
         def parameterize(value)
0
           value.respond_to?(:to_param) ? value.to_param : value
0
         end
0
+
0
+        def normalize_argument_to_redirection(fragment)
0
+          after_routing = @controller.url_for(fragment)
0
+          if after_routing =~ %r{^\w+://.*}
0
+            after_routing
0
+          else
0
+            # FIXME - this should probably get removed.
0
+            if after_routing.first != '/'
0
+              after_routing = '/' + after_routing
0
+            end
0
+            @request.protocol + @request.host_with_port + after_routing
0
+          end
0
+        end
0
     end
0
   end
0
 end
...
1042
1043
1044
 
 
 
1045
1046
1047
1048
1049
1050
1051
1052
 
1053
1054
1055
 
1056
1057
1058
1059
1060
1061
1062
 
 
 
 
 
1063
1064
 
1065
1066
1067
 
 
 
 
 
 
1068
1069
1070
...
1042
1043
1044
1045
1046
1047
1048
1049
 
 
 
 
 
 
1050
1051
 
 
1052
1053
 
 
 
 
 
 
1054
1055
1056
1057
1058
1059
 
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
0
@@ -1042,29 +1042,31 @@ module ActionController #:nodoc:
0
           status = 302
0
         end
0
 
0
+        response.redirected_to= options
0
+        logger.info("Redirected to #{options}") if logger && logger.info?
0
+
0
         case options
0
           when %r{^\w+://.*}
0
-            raise DoubleRenderError if performed?
0
-            logger.info("Redirected to #{options}") if logger && logger.info?
0
-            response.redirect(options, interpret_status(status))
0
-            response.redirected_to = options
0
-            @performed_redirect = true
0
-
0
+            redirect_to_full_url(options, status)
0
           when String
0
-            redirect_to(request.protocol + request.host_with_port + options, :status=>status)
0
-
0
+            redirect_to_full_url(request.protocol + request.host_with_port + options, status)
0
           when :back
0
-            request.env["HTTP_REFERER"] ? redirect_to(request.env["HTTP_REFERER"], :status=>status) : raise(RedirectBackError)
0
-
0
-          when Hash
0
-            redirect_to(url_for(options), :status=>status)
0
-            response.redirected_to = options
0
-
0
+            if referer = request.headers["Referer"]
0
+              redirect_to(referer, :status=>status)
0
+            else
0
+              raise RedirectBackError
0
+            end
0
           else
0
-            redirect_to(url_for(options), :status=>status)
0
+            redirect_to_full_url(url_for(options), status)
0
         end
0
       end
0
 
0
+      def redirect_to_full_url(url, status)
0
+        raise DoubleRenderError if performed?
0
+        response.redirect(url, interpret_status(status))
0
+        @performed_redirect = true
0
+      end
0
+
0
       # Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a "private" instruction, so that
0
       # intermediate caches shouldn't cache the response.
0
       #
...
232
233
234
235
236
237
238
...
253
254
255
256
257
258
259
260
261
...
432
433
434
435
 
436
437
438
 
439
440
441
442
 
443
444
445
...
459
460
461
462
 
463
464
465
...
232
233
234
 
235
236
237
...
252
253
254
 
 
 
255
256
257
...
428
429
430
 
431
432
433
434
435
436
437
438
439
440
441
442
443
...
457
458
459
 
460
461
462
463
0
@@ -232,7 +232,6 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
0
       process :redirect_to_named_route
0
       assert_redirected_to 'http://test.host/route_one'
0
       assert_redirected_to route_one_url
0
-      assert_redirected_to :route_one_url
0
     end
0
   end
0
 
0
@@ -253,9 +252,6 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
0
       assert_raise(Test::Unit::AssertionFailedError) do
0
         assert_redirected_to route_two_url
0
       end
0
-      assert_raise(Test::Unit::AssertionFailedError) do
0
-        assert_redirected_to :route_two_url
0
-      end
0
     end
0
   end
0
 
0
@@ -432,14 +428,16 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
0
     assert_redirected_to :controller => 'action_pack_assertions', :action => "flash_me", :id => 1, :params => { :panda => 'fun' }
0
   end
0
 
0
-  def test_redirected_to_url_leadling_slash
0
+  def test_redirected_to_url_leading_slash
0
     process :redirect_to_path
0
     assert_redirected_to '/some/path'
0
   end
0
+
0
   def test_redirected_to_url_no_leadling_slash
0
     process :redirect_to_path
0
     assert_redirected_to 'some/path'
0
   end
0
+
0
   def test_redirected_to_url_full_url
0
     process :redirect_to_path
0
     assert_redirected_to 'http://test.host/some/path'
0
@@ -459,7 +457,7 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
0
   def test_redirected_to_with_nested_controller
0
     @controller = Admin::InnerModuleController.new
0
     get :redirect_to_absolute_controller
0
-    assert_redirected_to :controller => 'content'
0
+    assert_redirected_to :controller => '/content'
0
 
0
     get :redirect_to_fellow_controller
0
     assert_redirected_to :controller => 'admin/user'
...
119
120
121
122
 
123
124
125
...
119
120
121
 
122
123
124
125
0
@@ -119,7 +119,7 @@ class ComponentsTest < Test::Unit::TestCase
0
   def test_component_redirect_redirects
0
     get :calling_redirected
0
 
0
-    assert_redirected_to :action => "being_called"
0
+    assert_redirected_to :controller=>"callee", :action => "being_called"
0
   end
0
 
0
   def test_component_multiple_redirect_redirects
...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
...
235
236
237
 
238
239
240
 
241
242
243
...
283
284
285
286
 
287
288
289
...
168
169
170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
172
173
...
220
221
222
223
224
225
226
227
228
229
230
...
270
271
272
 
273
274
275
276
0
@@ -168,21 +168,6 @@ class RedirectTest < Test::Unit::TestCase
0
     assert_redirected_to :action => "other_host", :only_path => false, :host => 'other.test.host'
0
   end
0
 
0
-  def test_redirect_error_with_pretty_diff
0
-    get :host_redirect
0
-    assert_response :redirect
0
-    begin
0
-      assert_redirected_to :action => "other_host", :only_path => true
0
-    rescue Test::Unit::AssertionFailedError => err
0
-      expected_msg, redirection_msg, diff_msg = err.message.scan(/<\{[^\}]+\}>/).collect { |s| s[2..-3] }
0
-      assert_match %r("only_path"=>false),        redirection_msg
0
-      assert_match %r("host"=>"other.test.host"), redirection_msg
0
-      assert_match %r("action"=>"other_host"),    redirection_msg
0
-      assert_match %r("only_path"=>false),        diff_msg
0
-      assert_match %r("host"=>"other.test.host"), diff_msg
0
-    end
0
-  end
0
-
0
   def test_module_redirect
0
     get :module_redirect
0
     assert_response :redirect
0
@@ -235,9 +220,11 @@ class RedirectTest < Test::Unit::TestCase
0
     
0
     get :redirect_to_existing_record
0
     assert_equal "http://test.host/workshops/5", redirect_to_url
0
+    assert_redirected_to Workshop.new(5, false)
0
 
0
     get :redirect_to_new_record
0
     assert_equal "http://test.host/workshops", redirect_to_url
0
+    assert_redirected_to Workshop.new(5, true)
0
   end
0
 
0
   def test_redirect_to_nil
0
@@ -283,7 +270,7 @@ module ModuleTest
0
     def test_module_redirect_using_options
0
       get :module_redirect
0
       assert_response :redirect
0
-      assert_redirected_to :controller => 'redirect', :action => "hello_world"
0
+      assert_redirected_to :controller => '/redirect', :action => "hello_world"
0
     end
0
   end
0
 end

Comments