Froze rails gems
[depot.git] / vendor / rails / actionpack / lib / action_controller / assertions / routing_assertions.rb
1 module ActionController
2 module Assertions
3 # Suite of assertions to test routes generated by Rails and the handling of requests made to them.
4 module RoutingAssertions
5 # Asserts that the routing of the given +path+ was handled correctly and that the parsed options (given in the +expected_options+ hash)
6 # match +path+. Basically, it asserts that Rails recognizes the route given by +expected_options+.
7 #
8 # Pass a hash in the second argument (+path+) to specify the request method. This is useful for routes
9 # requiring a specific HTTP method. The hash should contain a :path with the incoming request path
10 # and a :method containing the required HTTP verb.
11 #
12 # # assert that POSTing to /items will call the create action on ItemsController
13 # assert_recognizes {:controller => 'items', :action => 'create'}, {:path => 'items', :method => :post}
14 #
15 # You can also pass in +extras+ with a hash containing URL parameters that would normally be in the query string. This can be used
16 # to assert that values in the query string string will end up in the params hash correctly. To test query strings you must use the
17 # extras argument, appending the query string on the path directly will not work. For example:
18 #
19 # # assert that a path of '/items/list/1?view=print' returns the correct options
20 # assert_recognizes {:controller => 'items', :action => 'list', :id => '1', :view => 'print'}, 'items/list/1', { :view => "print" }
21 #
22 # The +message+ parameter allows you to pass in an error message that is displayed upon failure.
23 #
24 # ==== Examples
25 # # Check the default route (i.e., the index action)
26 # assert_recognizes {:controller => 'items', :action => 'index'}, 'items'
27 #
28 # # Test a specific action
29 # assert_recognizes {:controller => 'items', :action => 'list'}, 'items/list'
30 #
31 # # Test an action with a parameter
32 # assert_recognizes {:controller => 'items', :action => 'destroy', :id => '1'}, 'items/destroy/1'
33 #
34 # # Test a custom route
35 # assert_recognizes {:controller => 'items', :action => 'show', :id => '1'}, 'view/item1'
36 #
37 # # Check a Simply RESTful generated route
38 # assert_recognizes list_items_url, 'items/list'
39 def assert_recognizes(expected_options, path, extras={}, message=nil)
40 if path.is_a? Hash
41 request_method = path[:method]
42 path = path[:path]
43 else
44 request_method = nil
45 end
46
47 clean_backtrace do
48 ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
49 request = recognized_request_for(path, request_method)
50
51 expected_options = expected_options.clone
52 extras.each_key { |key| expected_options.delete key } unless extras.nil?
53
54 expected_options.stringify_keys!
55 routing_diff = expected_options.diff(request.path_parameters)
56 msg = build_message(message, "The recognized options <?> did not match <?>, difference: <?>",
57 request.path_parameters, expected_options, expected_options.diff(request.path_parameters))
58 assert_block(msg) { request.path_parameters == expected_options }
59 end
60 end
61
62 # Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+.
63 # The +extras+ parameter is used to tell the request the names and values of additional request parameters that would be in
64 # a query string. The +message+ parameter allows you to specify a custom error message for assertion failures.
65 #
66 # The +defaults+ parameter is unused.
67 #
68 # ==== Examples
69 # # Asserts that the default action is generated for a route with no action
70 # assert_generates "/items", :controller => "items", :action => "index"
71 #
72 # # Tests that the list action is properly routed
73 # assert_generates "/items/list", :controller => "items", :action => "list"
74 #
75 # # Tests the generation of a route with a parameter
76 # assert_generates "/items/list/1", { :controller => "items", :action => "list", :id => "1" }
77 #
78 # # Asserts that the generated route gives us our custom route
79 # assert_generates "changesets/12", { :controller => 'scm', :action => 'show_diff', :revision => "12" }
80 def assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)
81 clean_backtrace do
82 expected_path = "/#{expected_path}" unless expected_path[0] == ?/
83 # Load routes.rb if it hasn't been loaded.
84 ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
85
86 generated_path, extra_keys = ActionController::Routing::Routes.generate_extras(options, defaults)
87 found_extras = options.reject {|k, v| ! extra_keys.include? k}
88
89 msg = build_message(message, "found extras <?>, not <?>", found_extras, extras)
90 assert_block(msg) { found_extras == extras }
91
92 msg = build_message(message, "The generated path <?> did not match <?>", generated_path,
93 expected_path)
94 assert_block(msg) { expected_path == generated_path }
95 end
96 end
97
98 # Asserts that path and options match both ways; in other words, it verifies that <tt>path</tt> generates
99 # <tt>options</tt> and then that <tt>options</tt> generates <tt>path</tt>. This essentially combines +assert_recognizes+
100 # and +assert_generates+ into one step.
101 #
102 # The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The
103 # +message+ parameter allows you to specify a custom error message to display upon failure.
104 #
105 # ==== Examples
106 # # Assert a basic route: a controller with the default action (index)
107 # assert_routing '/home', :controller => 'home', :action => 'index'
108 #
109 # # Test a route generated with a specific controller, action, and parameter (id)
110 # assert_routing '/entries/show/23', :controller => 'entries', :action => 'show', id => 23
111 #
112 # # Assert a basic route (controller + default action), with an error message if it fails
113 # assert_routing '/store', { :controller => 'store', :action => 'index' }, {}, {}, 'Route for store index not generated properly'
114 #
115 # # Tests a route, providing a defaults hash
116 # assert_routing 'controller/action/9', {:id => "9", :item => "square"}, {:controller => "controller", :action => "action"}, {}, {:item => "square"}
117 #
118 # # Tests a route with a HTTP method
119 # assert_routing { :method => 'put', :path => '/product/321' }, { :controller => "product", :action => "update", :id => "321" }
120 def assert_routing(path, options, defaults={}, extras={}, message=nil)
121 assert_recognizes(options, path, extras, message)
122
123 controller, default_controller = options[:controller], defaults[:controller]
124 if controller && controller.include?(?/) && default_controller && default_controller.include?(?/)
125 options[:controller] = "/#{controller}"
126 end
127
128 assert_generates(path.is_a?(Hash) ? path[:path] : path, options, defaults, extras, message)
129 end
130
131 private
132 # Recognizes the route for a given path.
133 def recognized_request_for(path, request_method = nil)
134 path = "/#{path}" unless path.first == '/'
135
136 # Assume given controller
137 request = ActionController::TestRequest.new({}, {}, nil)
138 request.env["REQUEST_METHOD"] = request_method.to_s.upcase if request_method
139 request.path = path
140
141 ActionController::Routing::Routes.recognize(request)
142 request
143 end
144 end
145 end
146 end