actionpack 1.13.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (317) hide show
  1. data/CHANGELOG +1400 -20
  2. data/MIT-LICENSE +1 -1
  3. data/README +5 -5
  4. data/RUNNING_UNIT_TESTS +4 -5
  5. data/Rakefile +5 -6
  6. data/install.rb +2 -2
  7. data/lib/action_controller.rb +11 -15
  8. data/lib/action_controller/assertions.rb +12 -25
  9. data/lib/action_controller/assertions/dom_assertions.rb +18 -4
  10. data/lib/action_controller/assertions/model_assertions.rb +8 -1
  11. data/lib/action_controller/assertions/response_assertions.rb +35 -12
  12. data/lib/action_controller/assertions/routing_assertions.rb +56 -12
  13. data/lib/action_controller/assertions/selector_assertions.rb +105 -38
  14. data/lib/action_controller/assertions/tag_assertions.rb +28 -15
  15. data/lib/action_controller/base.rb +318 -250
  16. data/lib/action_controller/benchmarking.rb +33 -29
  17. data/lib/action_controller/caching.rb +130 -64
  18. data/lib/action_controller/cgi_ext.rb +16 -0
  19. data/lib/action_controller/cgi_ext/{cookie_performance_fix.rb → cookie.rb} +25 -40
  20. data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
  21. data/lib/action_controller/cgi_ext/session.rb +73 -0
  22. data/lib/action_controller/cgi_ext/stdinput.rb +23 -0
  23. data/lib/action_controller/cgi_process.rb +34 -57
  24. data/lib/action_controller/components.rb +19 -36
  25. data/lib/action_controller/cookies.rb +10 -9
  26. data/lib/action_controller/dispatcher.rb +195 -0
  27. data/lib/action_controller/filters.rb +35 -34
  28. data/lib/action_controller/flash.rb +30 -35
  29. data/lib/action_controller/helpers.rb +121 -47
  30. data/lib/action_controller/http_authentication.rb +126 -0
  31. data/lib/action_controller/integration.rb +105 -101
  32. data/lib/action_controller/layout.rb +59 -47
  33. data/lib/action_controller/mime_responds.rb +57 -68
  34. data/lib/action_controller/mime_type.rb +43 -80
  35. data/lib/action_controller/mime_types.rb +20 -0
  36. data/lib/action_controller/polymorphic_routes.rb +88 -0
  37. data/lib/action_controller/record_identifier.rb +91 -0
  38. data/lib/action_controller/request.rb +553 -88
  39. data/lib/action_controller/request_forgery_protection.rb +126 -0
  40. data/lib/action_controller/request_profiler.rb +138 -0
  41. data/lib/action_controller/rescue.rb +185 -69
  42. data/lib/action_controller/resources.rb +211 -172
  43. data/lib/action_controller/response.rb +49 -8
  44. data/lib/action_controller/routing.rb +359 -236
  45. data/lib/action_controller/routing_optimisation.rb +119 -0
  46. data/lib/action_controller/session/active_record_store.rb +3 -2
  47. data/lib/action_controller/session/cookie_store.rb +161 -0
  48. data/lib/action_controller/session/mem_cache_store.rb +9 -16
  49. data/lib/action_controller/session_management.rb +17 -8
  50. data/lib/action_controller/streaming.rb +6 -3
  51. data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
  52. data/lib/action_controller/templates/rescues/{_trace.rhtml → _trace.erb} +0 -0
  53. data/lib/action_controller/templates/rescues/{diagnostics.rhtml → diagnostics.erb} +2 -2
  54. data/lib/action_controller/templates/rescues/{layout.rhtml → layout.erb} +0 -0
  55. data/lib/action_controller/templates/rescues/{missing_template.rhtml → missing_template.erb} +0 -0
  56. data/lib/action_controller/templates/rescues/{routing_error.rhtml → routing_error.erb} +0 -0
  57. data/lib/action_controller/templates/rescues/{template_error.rhtml → template_error.erb} +2 -2
  58. data/lib/action_controller/templates/rescues/{unknown_action.rhtml → unknown_action.erb} +0 -0
  59. data/lib/action_controller/test_case.rb +53 -0
  60. data/lib/action_controller/test_process.rb +59 -46
  61. data/lib/action_controller/url_rewriter.rb +48 -24
  62. data/lib/action_controller/vendor/html-scanner/html/document.rb +7 -4
  63. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
  64. data/lib/action_controller/vendor/html-scanner/html/selector.rb +11 -6
  65. data/lib/action_controller/verification.rb +27 -21
  66. data/lib/action_pack.rb +1 -1
  67. data/lib/action_pack/version.rb +4 -4
  68. data/lib/action_view.rb +2 -3
  69. data/lib/action_view/base.rb +218 -63
  70. data/lib/action_view/compiled_templates.rb +1 -2
  71. data/lib/action_view/helpers/active_record_helper.rb +35 -17
  72. data/lib/action_view/helpers/asset_tag_helper.rb +395 -87
  73. data/lib/action_view/helpers/atom_feed_helper.rb +111 -0
  74. data/lib/action_view/helpers/benchmark_helper.rb +12 -5
  75. data/lib/action_view/helpers/cache_helper.rb +29 -0
  76. data/lib/action_view/helpers/capture_helper.rb +97 -63
  77. data/lib/action_view/helpers/date_helper.rb +295 -35
  78. data/lib/action_view/helpers/debug_helper.rb +6 -2
  79. data/lib/action_view/helpers/form_helper.rb +354 -111
  80. data/lib/action_view/helpers/form_options_helper.rb +171 -109
  81. data/lib/action_view/helpers/form_tag_helper.rb +332 -76
  82. data/lib/action_view/helpers/javascript_helper.rb +35 -11
  83. data/lib/action_view/helpers/javascripts/controls.js +484 -354
  84. data/lib/action_view/helpers/javascripts/dragdrop.js +88 -58
  85. data/lib/action_view/helpers/javascripts/effects.js +396 -364
  86. data/lib/action_view/helpers/javascripts/prototype.js +2817 -1107
  87. data/lib/action_view/helpers/number_helper.rb +84 -60
  88. data/lib/action_view/helpers/prototype_helper.rb +419 -43
  89. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  90. data/lib/action_view/helpers/record_tag_helper.rb +59 -0
  91. data/lib/action_view/helpers/sanitize_helper.rb +223 -0
  92. data/lib/action_view/helpers/scriptaculous_helper.rb +63 -4
  93. data/lib/action_view/helpers/tag_helper.rb +69 -39
  94. data/lib/action_view/helpers/text_helper.rb +221 -148
  95. data/lib/action_view/helpers/url_helper.rb +283 -165
  96. data/lib/action_view/partials.rb +134 -62
  97. data/lib/action_view/template_error.rb +4 -12
  98. data/lib/actionpack.rb +1 -0
  99. data/test/abstract_unit.rb +21 -1
  100. data/test/action_view_test.rb +26 -0
  101. data/test/active_record_unit.rb +12 -20
  102. data/test/activerecord/active_record_store_test.rb +2 -2
  103. data/test/activerecord/render_partial_with_record_identification_test.rb +74 -0
  104. data/test/controller/action_pack_assertions_test.rb +21 -152
  105. data/test/controller/addresses_render_test.rb +2 -7
  106. data/test/controller/assert_select_test.rb +120 -14
  107. data/test/controller/base_test.rb +11 -13
  108. data/test/controller/caching_test.rb +125 -5
  109. data/test/controller/capture_test.rb +23 -16
  110. data/test/controller/cgi_test.rb +66 -391
  111. data/test/controller/components_test.rb +31 -42
  112. data/test/controller/content_type_test.rb +1 -1
  113. data/test/controller/cookie_test.rb +42 -14
  114. data/test/controller/deprecation/deprecated_base_methods_test.rb +1 -42
  115. data/test/controller/dispatcher_test.rb +123 -0
  116. data/test/controller/fake_models.rb +5 -0
  117. data/test/controller/filters_test.rb +44 -7
  118. data/test/controller/flash_test.rb +46 -2
  119. data/test/controller/fragment_store_setting_test.rb +10 -8
  120. data/test/controller/helper_test.rb +19 -2
  121. data/test/controller/html-scanner/document_test.rb +124 -0
  122. data/test/controller/html-scanner/node_test.rb +69 -0
  123. data/test/controller/html-scanner/sanitizer_test.rb +250 -0
  124. data/test/controller/html-scanner/tag_node_test.rb +239 -0
  125. data/test/controller/html-scanner/text_node_test.rb +51 -0
  126. data/test/controller/html-scanner/tokenizer_test.rb +125 -0
  127. data/test/controller/http_authentication_test.rb +54 -0
  128. data/test/controller/integration_test.rb +12 -26
  129. data/test/controller/layout_test.rb +64 -12
  130. data/test/controller/mime_responds_test.rb +193 -38
  131. data/test/controller/mime_type_test.rb +30 -8
  132. data/test/controller/new_render_test.rb +104 -22
  133. data/test/controller/polymorphic_routes_test.rb +98 -0
  134. data/test/controller/record_identifier_test.rb +103 -0
  135. data/test/controller/redirect_test.rb +120 -18
  136. data/test/controller/render_test.rb +195 -45
  137. data/test/controller/request_forgery_protection_test.rb +217 -0
  138. data/test/controller/request_test.rb +545 -27
  139. data/test/controller/rescue_test.rb +501 -0
  140. data/test/controller/resources_test.rb +258 -132
  141. data/test/controller/routing_test.rb +502 -106
  142. data/test/controller/selector_test.rb +5 -5
  143. data/test/controller/send_file_test.rb +17 -7
  144. data/test/controller/session/cookie_store_test.rb +246 -0
  145. data/test/controller/session/mem_cache_store_test.rb +182 -0
  146. data/test/controller/session_fixation_test.rb +8 -11
  147. data/test/controller/session_management_test.rb +7 -7
  148. data/test/controller/test_test.rb +150 -38
  149. data/test/controller/url_rewriter_test.rb +87 -12
  150. data/test/controller/verification_test.rb +11 -0
  151. data/test/controller/view_paths_test.rb +137 -0
  152. data/test/controller/webservice_test.rb +11 -75
  153. data/test/fixtures/addresses/{list.rhtml → list.erb} +0 -0
  154. data/test/fixtures/db_definitions/sqlite.sql +2 -1
  155. data/test/fixtures/developer.rb +2 -0
  156. data/test/fixtures/fun/games/{hello_world.rhtml → hello_world.erb} +0 -0
  157. data/test/fixtures/helpers/fun/pdf_helper.rb +1 -1
  158. data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
  159. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
  160. data/test/fixtures/layouts/{builder.rxml → builder.builder} +0 -0
  161. data/test/fixtures/layouts/{standard.rhtml → standard.erb} +0 -0
  162. data/test/fixtures/layouts/{talk_from_action.rhtml → talk_from_action.erb} +0 -0
  163. data/test/fixtures/layouts/{yield.rhtml → yield.erb} +0 -0
  164. data/test/fixtures/multipart/binary_file +0 -0
  165. data/test/fixtures/multipart/bracketed_param +5 -0
  166. data/test/fixtures/override/test/hello_world.erb +1 -0
  167. data/test/fixtures/override2/layouts/test/sub.erb +1 -0
  168. data/test/fixtures/post_test/layouts/post.html.erb +1 -0
  169. data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
  170. data/test/fixtures/post_test/post/index.html.erb +1 -0
  171. data/test/fixtures/post_test/post/index.iphone.erb +1 -0
  172. data/test/fixtures/post_test/super_post/index.html.erb +1 -0
  173. data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
  174. data/test/fixtures/public/404.html +1 -0
  175. data/test/fixtures/public/500.html +1 -0
  176. data/test/fixtures/public/javascripts/application.js +0 -1
  177. data/test/fixtures/public/javascripts/bank.js +1 -0
  178. data/test/fixtures/public/javascripts/robber.js +1 -0
  179. data/test/fixtures/public/stylesheets/bank.css +1 -0
  180. data/test/fixtures/public/stylesheets/robber.css +1 -0
  181. data/test/fixtures/replies.yml +2 -0
  182. data/test/fixtures/reply.rb +2 -1
  183. data/test/fixtures/respond_to/{all_types_with_layout.rhtml → all_types_with_layout.html.erb} +0 -0
  184. data/test/fixtures/respond_to/{all_types_with_layout.rjs → all_types_with_layout.js.rjs} +0 -0
  185. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
  186. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
  187. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
  188. data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
  189. data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
  190. data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
  191. data/test/fixtures/respond_to/{using_defaults.rhtml → using_defaults.html.erb} +0 -0
  192. data/test/fixtures/respond_to/{using_defaults.rjs → using_defaults.js.rjs} +0 -0
  193. data/test/fixtures/respond_to/{using_defaults.rxml → using_defaults.xml.builder} +0 -0
  194. data/test/fixtures/respond_to/{using_defaults_with_type_list.rhtml → using_defaults_with_type_list.html.erb} +0 -0
  195. data/test/fixtures/respond_to/{using_defaults_with_type_list.rjs → using_defaults_with_type_list.js.rjs} +0 -0
  196. data/test/fixtures/respond_to/{using_defaults_with_type_list.rxml → using_defaults_with_type_list.xml.builder} +0 -0
  197. data/test/fixtures/scope/test/{modgreet.rhtml → modgreet.erb} +0 -0
  198. data/test/fixtures/test/{_customer.rhtml → _customer.erb} +0 -0
  199. data/test/fixtures/test/{_customer_greeting.rhtml → _customer_greeting.erb} +0 -0
  200. data/test/fixtures/test/_hash_greeting.erb +1 -0
  201. data/test/fixtures/test/_hash_object.erb +2 -0
  202. data/test/fixtures/test/{_hello.rxml → _hello.builder} +0 -0
  203. data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
  204. data/test/fixtures/test/_partial.erb +1 -0
  205. data/test/fixtures/test/_partial.html.erb +1 -0
  206. data/test/fixtures/test/_partial.js.erb +1 -0
  207. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
  208. data/test/fixtures/test/{_partial_only.rhtml → _partial_only.erb} +0 -0
  209. data/test/fixtures/test/{_person.rhtml → _person.erb} +0 -0
  210. data/test/fixtures/test/{action_talk_to_layout.rhtml → action_talk_to_layout.erb} +0 -0
  211. data/test/fixtures/test/{block_content_for.rhtml → block_content_for.erb} +0 -0
  212. data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
  213. data/test/fixtures/test/{capturing.rhtml → capturing.erb} +0 -0
  214. data/test/fixtures/test/{content_for.rhtml → content_for.erb} +0 -0
  215. data/test/fixtures/test/content_for_concatenated.erb +3 -0
  216. data/test/fixtures/test/content_for_with_parameter.erb +2 -0
  217. data/test/fixtures/test/dot.directory/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
  218. data/test/fixtures/test/{erb_content_for.rhtml → erb_content_for.erb} +0 -0
  219. data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
  220. data/test/fixtures/test/formatted_xml_erb.builder +1 -0
  221. data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
  222. data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
  223. data/test/fixtures/test/{greeting.rhtml → greeting.erb} +0 -0
  224. data/test/fixtures/test/{hello.rxml → hello.builder} +0 -0
  225. data/test/fixtures/test/{hello_world.rxml → hello_world.builder} +0 -0
  226. data/test/fixtures/test/{hello_world.rhtml → hello_world.erb} +0 -0
  227. data/test/fixtures/test/{hello_world_container.rxml → hello_world_container.builder} +0 -0
  228. data/test/fixtures/test/{hello_world_with_layout_false.rhtml → hello_world_with_layout_false.erb} +0 -0
  229. data/test/fixtures/test/{hello_xml_world.rxml → hello_xml_world.builder} +0 -0
  230. data/test/fixtures/test/list.erb +1 -0
  231. data/test/fixtures/test/{non_erb_block_content_for.rxml → non_erb_block_content_for.builder} +0 -0
  232. data/test/fixtures/test/{potential_conflicts.rhtml → potential_conflicts.erb} +0 -0
  233. data/test/fixtures/test/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
  234. data/test/fixtures/test/{render_file_with_locals.rhtml → render_file_with_locals.erb} +0 -0
  235. data/test/fixtures/test/{render_to_string_test.rhtml → render_to_string_test.erb} +0 -0
  236. data/test/fixtures/test/{update_element_with_capture.rhtml → update_element_with_capture.erb} +0 -0
  237. data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
  238. data/test/fixtures/topic.rb +1 -1
  239. data/test/template/active_record_helper_test.rb +67 -20
  240. data/test/template/asset_tag_helper_test.rb +222 -54
  241. data/test/template/atom_feed_helper_test.rb +101 -0
  242. data/test/template/benchmark_helper_test.rb +2 -2
  243. data/test/template/compiled_templates_test.rb +76 -32
  244. data/test/template/date_helper_test.rb +125 -9
  245. data/test/template/form_helper_test.rb +326 -33
  246. data/test/template/form_options_helper_test.rb +822 -15
  247. data/test/template/form_tag_helper_test.rb +96 -30
  248. data/test/template/javascript_helper_test.rb +61 -13
  249. data/test/template/number_helper_test.rb +12 -11
  250. data/test/template/prototype_helper_test.rb +185 -24
  251. data/test/template/sanitize_helper_test.rb +49 -0
  252. data/test/template/scriptaculous_helper_test.rb +9 -3
  253. data/test/template/tag_helper_test.rb +13 -2
  254. data/test/template/text_helper_test.rb +38 -52
  255. data/test/template/url_helper_test.rb +216 -46
  256. metadata +144 -116
  257. data/examples/.htaccess +0 -24
  258. data/examples/address_book/index.rhtml +0 -33
  259. data/examples/address_book/layout.rhtml +0 -8
  260. data/examples/address_book_controller.cgi +0 -9
  261. data/examples/address_book_controller.fcgi +0 -6
  262. data/examples/address_book_controller.rb +0 -52
  263. data/examples/address_book_controller.rbx +0 -4
  264. data/examples/benchmark.rb +0 -52
  265. data/examples/benchmark_with_ar.fcgi +0 -89
  266. data/examples/blog_controller.cgi +0 -53
  267. data/examples/debate/index.rhtml +0 -14
  268. data/examples/debate/new_topic.rhtml +0 -22
  269. data/examples/debate/topic.rhtml +0 -32
  270. data/examples/debate_controller.cgi +0 -57
  271. data/lib/action_controller/assertions/deprecated_assertions.rb +0 -228
  272. data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -36
  273. data/lib/action_controller/cgi_ext/cgi_methods.rb +0 -211
  274. data/lib/action_controller/cgi_ext/pstore_performance_fix.rb +0 -30
  275. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +0 -95
  276. data/lib/action_controller/cgi_ext/session_performance_fix.rb +0 -30
  277. data/lib/action_controller/deprecated_dependencies.rb +0 -65
  278. data/lib/action_controller/deprecated_redirects.rb +0 -17
  279. data/lib/action_controller/deprecated_request_methods.rb +0 -34
  280. data/lib/action_controller/macros/auto_complete.rb +0 -53
  281. data/lib/action_controller/macros/in_place_editing.rb +0 -33
  282. data/lib/action_controller/pagination.rb +0 -408
  283. data/lib/action_controller/scaffolding.rb +0 -189
  284. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -44
  285. data/lib/action_controller/templates/scaffolds/edit.rhtml +0 -7
  286. data/lib/action_controller/templates/scaffolds/layout.rhtml +0 -69
  287. data/lib/action_controller/templates/scaffolds/list.rhtml +0 -27
  288. data/lib/action_controller/templates/scaffolds/new.rhtml +0 -6
  289. data/lib/action_controller/templates/scaffolds/show.rhtml +0 -9
  290. data/lib/action_controller/vendor/xml_node.rb +0 -97
  291. data/lib/action_view/helpers/deprecated_helper.rb +0 -37
  292. data/lib/action_view/helpers/java_script_macros_helper.rb +0 -233
  293. data/lib/action_view/helpers/pagination_helper.rb +0 -86
  294. data/test/activerecord/active_record_assertions_test.rb +0 -92
  295. data/test/activerecord/pagination_test.rb +0 -165
  296. data/test/controller/deprecated_instance_variables_test.rb +0 -48
  297. data/test/controller/raw_post_test.rb +0 -68
  298. data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +0 -1
  299. data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +0 -1
  300. data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +0 -1
  301. data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +0 -1
  302. data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +0 -1
  303. data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +0 -1
  304. data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +0 -1
  305. data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +0 -1
  306. data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +0 -1
  307. data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +0 -1
  308. data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +0 -1
  309. data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +0 -1
  310. data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +0 -1
  311. data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +0 -1
  312. data/test/fixtures/respond_to/layouts/standard.rhtml +0 -1
  313. data/test/fixtures/test/_hash_object.rhtml +0 -1
  314. data/test/fixtures/test/list.rhtml +0 -1
  315. data/test/template/deprecated_helper_test.rb +0 -36
  316. data/test/template/deprecated_instance_variables_test.rb +0 -43
  317. data/test/template/java_script_macros_helper_test.rb +0 -109
@@ -1,6 +1,5 @@
1
- require File.dirname(__FILE__) + '/../abstract_unit'
2
- require 'test/unit'
3
- require File.dirname(__FILE__) + '/fake_controllers'
1
+ require "#{File.dirname(__FILE__)}/../abstract_unit"
2
+ require "#{File.dirname(__FILE__)}/fake_controllers"
4
3
  require 'action_controller/routing'
5
4
 
6
5
  RunTimeTests = ARGV.include? 'time'
@@ -14,14 +13,49 @@ class ROUTING::RouteBuilder
14
13
  end
15
14
  end
16
15
 
16
+ # See RFC 3986, section 3.3 for allowed path characters.
17
+ class UriReservedCharactersRoutingTest < Test::Unit::TestCase
18
+ def setup
19
+ ActionController::Routing.use_controllers! ['controller']
20
+ @set = ActionController::Routing::RouteSet.new
21
+ @set.draw do |map|
22
+ map.connect ':controller/:action/:variable'
23
+ end
24
+
25
+ safe, unsafe = %w(: @ & = + $ , ;), %w(^ / ? # [ ])
26
+ hex = unsafe.map { |char| '%' + char.unpack('H2').first.upcase }
27
+
28
+ @segment = "#{safe}#{unsafe}".freeze
29
+ @escaped = "#{safe}#{hex}".freeze
30
+ end
31
+
32
+ def test_route_generation_escapes_unsafe_path_characters
33
+ assert_equal "/contr#{@segment}oller/act#{@escaped}ion/var#{@escaped}iable",
34
+ @set.generate(:controller => "contr#{@segment}oller",
35
+ :action => "act#{@segment}ion",
36
+ :variable => "var#{@segment}iable")
37
+ end
38
+
39
+ def test_route_recognition_unescapes_path_components
40
+ options = { :controller => "controller",
41
+ :action => "act#{@segment}ion",
42
+ :variable => "var#{@segment}iable" }
43
+ assert_equal options, @set.recognize_path("/controller/act#{@escaped}ion/var#{@escaped}iable")
44
+ end
45
+ end
46
+
17
47
  class LegacyRouteSetTests < Test::Unit::TestCase
18
48
  attr_reader :rs
19
49
  def setup
50
+ # These tests assume optimisation is on, so re-enable it.
51
+ ActionController::Base.optimise_named_routes = true
52
+
20
53
  @rs = ::ActionController::Routing::RouteSet.new
21
54
  @rs.draw {|m| m.connect ':controller/:action/:id' }
55
+
22
56
  ActionController::Routing.use_controllers! %w(content admin/user admin/news_feed)
23
57
  end
24
-
58
+
25
59
  def test_default_setup
26
60
  assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/content"))
27
61
  assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/content/list"))
@@ -136,40 +170,66 @@ class LegacyRouteSetTests < Test::Unit::TestCase
136
170
 
137
171
  def test_basic_named_route
138
172
  rs.add_named_route :home, '', :controller => 'content', :action => 'list'
139
- x = setup_for_named_route.new
140
- assert_equal({:controller => 'content', :action => 'list', :use_route => :home, :only_path => false},
173
+ x = setup_for_named_route
174
+ assert_equal("http://named.route.test/",
141
175
  x.send(:home_url))
142
176
  end
143
177
 
178
+ def test_basic_named_route_with_relative_url_root
179
+ rs.add_named_route :home, '', :controller => 'content', :action => 'list'
180
+ x = setup_for_named_route
181
+ x.relative_url_root="/foo"
182
+ assert_equal("http://named.route.test/foo/",
183
+ x.send(:home_url))
184
+ assert_equal "/foo/", x.send(:home_path)
185
+ end
186
+
144
187
  def test_named_route_with_option
145
188
  rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page'
146
- x = setup_for_named_route.new
147
- assert_equal({:controller => 'content', :action => 'show_page', :title => 'new stuff', :use_route => :page, :only_path => false},
189
+ x = setup_for_named_route
190
+ assert_equal("http://named.route.test/page/new%20stuff",
148
191
  x.send(:page_url, :title => 'new stuff'))
149
192
  end
150
193
 
151
194
  def test_named_route_with_default
152
195
  rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page', :title => 'AboutPage'
153
- x = setup_for_named_route.new
154
- assert_equal({:controller => 'content', :action => 'show_page', :title => 'AboutPage', :use_route => :page, :only_path => false},
155
- x.send(:page_url))
156
- assert_equal({:controller => 'content', :action => 'show_page', :title => 'AboutRails', :use_route => :page, :only_path => false},
196
+ x = setup_for_named_route
197
+ assert_equal("http://named.route.test/page/AboutRails",
157
198
  x.send(:page_url, :title => "AboutRails"))
158
199
 
159
200
  end
160
201
 
161
202
  def test_named_route_with_nested_controller
162
- rs.add_named_route :users, 'admin/user', :controller => '/admin/user', :action => 'index'
163
- x = setup_for_named_route.new
164
- assert_equal({:controller => '/admin/user', :action => 'index', :use_route => :users, :only_path => false},
203
+ rs.add_named_route :users, 'admin/user', :controller => 'admin/user', :action => 'index'
204
+ x = setup_for_named_route
205
+ assert_equal("http://named.route.test/admin/user",
165
206
  x.send(:users_url))
166
207
  end
208
+
209
+ uses_mocha "named route optimisation" do
210
+ def test_optimised_named_route_call_never_uses_url_for
211
+ rs.add_named_route :users, 'admin/user', :controller => '/admin/user', :action => 'index'
212
+ rs.add_named_route :user, 'admin/user/:id', :controller=>'/admin/user', :action=>'show'
213
+ x = setup_for_named_route
214
+ x.expects(:url_for).never
215
+ x.send(:users_url)
216
+ x.send(:users_path)
217
+ x.send(:user_url, 2, :foo=>"bar")
218
+ x.send(:user_path, 3, :bar=>"foo")
219
+ end
220
+
221
+ def test_optimised_named_route_with_host
222
+ rs.add_named_route :pages, 'pages', :controller => 'content', :action => 'show_page', :host => 'foo.com'
223
+ x = setup_for_named_route
224
+ x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => :pages).once
225
+ x.send(:pages_url)
226
+ end
227
+ end
167
228
 
168
229
  def setup_for_named_route
169
- x = Class.new
170
- x.send(:define_method, :url_for) {|x| x}
171
- rs.named_routes.install(x)
172
- x
230
+ klass = Class.new(MockController)
231
+ rs.install_helpers(klass)
232
+ klass.new(rs)
173
233
  end
174
234
 
175
235
  def test_named_route_without_hash
@@ -177,20 +237,29 @@ class LegacyRouteSetTests < Test::Unit::TestCase
177
237
  map.normal ':controller/:action/:id'
178
238
  end
179
239
  end
180
-
240
+
241
+ def test_named_route_root
242
+ rs.draw do |map|
243
+ map.root :controller => "hello"
244
+ end
245
+ x = setup_for_named_route
246
+ assert_equal("http://named.route.test/", x.send(:root_url))
247
+ assert_equal("/", x.send(:root_path))
248
+ end
249
+
181
250
  def test_named_route_with_regexps
182
251
  rs.draw do |map|
183
252
  map.article 'page/:year/:month/:day/:title', :controller => 'page', :action => 'show',
184
253
  :year => /\d+/, :month => /\d+/, :day => /\d+/
185
254
  map.connect ':controller/:action/:id'
186
255
  end
187
- x = setup_for_named_route.new
188
- assert_equal(
189
- {:controller => 'page', :action => 'show', :title => 'hi', :use_route => :article, :only_path => false},
190
- x.send(:article_url, :title => 'hi')
191
- )
256
+ x = setup_for_named_route
257
+ # assert_equal(
258
+ # {:controller => 'page', :action => 'show', :title => 'hi', :use_route => :article, :only_path => false},
259
+ # x.send(:article_url, :title => 'hi')
260
+ # )
192
261
  assert_equal(
193
- {:controller => 'page', :action => 'show', :title => 'hi', :day => 10, :year => 2005, :month => 6, :use_route => :article, :only_path => false},
262
+ "http://named.route.test/page/2005/6/10/hi",
194
263
  x.send(:article_url, :title => 'hi', :day => 10, :year => 2005, :month => 6)
195
264
  )
196
265
  end
@@ -207,8 +276,15 @@ class LegacyRouteSetTests < Test::Unit::TestCase
207
276
  map.path 'file/*path', :controller => 'content', :action => 'show_file'
208
277
  map.connect ':controller/:action/:id'
209
278
  end
279
+
280
+ # No + to space in URI escaping, only for query params.
210
281
  results = rs.recognize_path "/file/hello+world/how+are+you%3F"
211
282
  assert results, "Recognition should have succeeded"
283
+ assert_equal ['hello+world', 'how+are+you?'], results[:path]
284
+
285
+ # Use %20 for space instead.
286
+ results = rs.recognize_path "/file/hello%20world/how%20are%20you%3F"
287
+ assert results, "Recognition should have succeeded"
212
288
  assert_equal ['hello world', 'how are you?'], results[:path]
213
289
 
214
290
  results = rs.recognize_path "/file"
@@ -216,6 +292,14 @@ class LegacyRouteSetTests < Test::Unit::TestCase
216
292
  assert_equal [], results[:path]
217
293
  end
218
294
 
295
+ def test_paths_slashes_unescaped_with_ordered_parameters
296
+ rs.add_named_route :path, '/file/*path', :controller => 'content'
297
+
298
+ # No / to %2F in URI, only for query params.
299
+ x = setup_for_named_route
300
+ assert_equal("/file/hello/world", x.send(:path_path, 'hello/world'))
301
+ end
302
+
219
303
  def test_non_controllers_cannot_be_matched
220
304
  rs.draw do |map|
221
305
  map.connect ':controller/:action/:id'
@@ -264,9 +348,12 @@ class LegacyRouteSetTests < Test::Unit::TestCase
264
348
  rs.draw do |map|
265
349
  map.content '/content/:query', :controller => 'content', :action => 'show'
266
350
  end
351
+
267
352
  exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'content', :action => 'show', :use_route => "content") }
268
- expected_message = "content_url failed to generate from #{{:action=>"show", :controller=>"content"}.inspect} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: [\"content\", :query] - are they all satisifed?"
269
- assert_equal expected_message, exception.message
353
+ assert_match %r[:action=>"show"], exception.message
354
+ assert_match %r[:controller=>"content"], exception.message
355
+ assert_match %r[you may have ambiguous routes, or you may need to supply additional parameters for this route], exception.message
356
+ assert_match %r[content_url has the following required parameters: \["content", :query\] - are they all satisfied?], exception.message
270
357
  end
271
358
 
272
359
  def test_dynamic_path_allowed
@@ -368,8 +455,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase
368
455
  assert_equal '/test', rs.generate(:controller => 'post', :action => 'show')
369
456
  assert_equal '/test', rs.generate(:controller => 'post', :action => 'show', :year => nil)
370
457
 
371
- x = setup_for_named_route.new
372
- assert_equal({:controller => 'post', :action => 'show', :use_route => :blog, :only_path => false},
458
+ x = setup_for_named_route
459
+ assert_equal("http://named.route.test/test",
373
460
  x.send(:blog_url))
374
461
  end
375
462
 
@@ -415,8 +502,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase
415
502
  assert_equal '/', rs.generate(:controller => 'content', :action => 'index')
416
503
  assert_equal '/', rs.generate(:controller => 'content')
417
504
 
418
- x = setup_for_named_route.new
419
- assert_equal({:controller => 'content', :action => 'index', :use_route => :home, :only_path => false},
505
+ x = setup_for_named_route
506
+ assert_equal("http://named.route.test/",
420
507
  x.send(:home_url))
421
508
  end
422
509
 
@@ -491,21 +578,21 @@ class LegacyRouteSetTests < Test::Unit::TestCase
491
578
  Object.const_set(:SubpathBooksController, Class.new(ActionController::Base))
492
579
 
493
580
  rs.draw do |r|
494
- r.connect '/books/:id;edit', :controller => 'subpath_books', :action => 'edit'
495
- r.connect '/items/:id;:action', :controller => 'subpath_books'
496
- r.connect '/posts/new;:action', :controller => 'subpath_books'
581
+ r.connect '/books/:id/edit', :controller => 'subpath_books', :action => 'edit'
582
+ r.connect '/items/:id/:action', :controller => 'subpath_books'
583
+ r.connect '/posts/new/:action', :controller => 'subpath_books'
497
584
  r.connect '/posts/:id', :controller => 'subpath_books', :action => "show"
498
585
  end
499
586
 
500
- hash = rs.recognize_path "/books/17;edit"
587
+ hash = rs.recognize_path "/books/17/edit"
501
588
  assert_not_nil hash
502
589
  assert_equal %w(subpath_books 17 edit), [hash[:controller], hash[:id], hash[:action]]
503
590
 
504
- hash = rs.recognize_path "/items/3;complete"
591
+ hash = rs.recognize_path "/items/3/complete"
505
592
  assert_not_nil hash
506
593
  assert_equal %w(subpath_books 3 complete), [hash[:controller], hash[:id], hash[:action]]
507
594
 
508
- hash = rs.recognize_path "/posts/new;preview"
595
+ hash = rs.recognize_path "/posts/new/preview"
509
596
  assert_not_nil hash
510
597
  assert_equal %w(subpath_books preview), [hash[:controller], hash[:action]]
511
598
 
@@ -520,17 +607,28 @@ class LegacyRouteSetTests < Test::Unit::TestCase
520
607
  Object.const_set(:SubpathBooksController, Class.new(ActionController::Base))
521
608
 
522
609
  rs.draw do |r|
523
- r.connect '/books/:id;edit', :controller => 'subpath_books', :action => 'edit'
524
- r.connect '/items/:id;:action', :controller => 'subpath_books'
525
- r.connect '/posts/new;:action', :controller => 'subpath_books'
610
+ r.connect '/books/:id/edit', :controller => 'subpath_books', :action => 'edit'
611
+ r.connect '/items/:id/:action', :controller => 'subpath_books'
612
+ r.connect '/posts/new/:action', :controller => 'subpath_books'
526
613
  end
527
614
 
528
- assert_equal "/books/7;edit", rs.generate(:controller => "subpath_books", :id => 7, :action => "edit")
529
- assert_equal "/items/15;complete", rs.generate(:controller => "subpath_books", :id => 15, :action => "complete")
530
- assert_equal "/posts/new;preview", rs.generate(:controller => "subpath_books", :action => "preview")
615
+ assert_equal "/books/7/edit", rs.generate(:controller => "subpath_books", :id => 7, :action => "edit")
616
+ assert_equal "/items/15/complete", rs.generate(:controller => "subpath_books", :id => 15, :action => "complete")
617
+ assert_equal "/posts/new/preview", rs.generate(:controller => "subpath_books", :action => "preview")
531
618
  ensure
532
619
  Object.send(:remove_const, :SubpathBooksController) rescue nil
533
620
  end
621
+
622
+ def test_failed_requirements_raises_exception_with_violated_requirements
623
+ rs.draw do |r|
624
+ r.foo_with_requirement 'foos/:id', :controller=>'foos', :requirements=>{:id=>/\d+/}
625
+ end
626
+
627
+ x = setup_for_named_route
628
+ assert_raises(ActionController::RoutingError) do
629
+ x.send(:foo_with_requirement_url, "I am Against the requirements")
630
+ end
631
+ end
534
632
  end
535
633
 
536
634
  class SegmentTest < Test::Unit::TestCase
@@ -559,18 +657,18 @@ class SegmentTest < Test::Unit::TestCase
559
657
  end
560
658
 
561
659
  class StaticSegmentTest < Test::Unit::TestCase
562
-
660
+
563
661
  def test_interpolation_chunk_should_respect_raw
564
662
  s = ROUTING::StaticSegment.new
565
- s.value = 'Hello/World'
663
+ s.value = 'Hello World'
566
664
  assert ! s.raw?
567
- assert_equal 'Hello/World', CGI.unescape(s.interpolation_chunk)
568
-
665
+ assert_equal 'Hello%20World', s.interpolation_chunk
666
+
569
667
  s.raw = true
570
668
  assert s.raw?
571
- assert_equal 'Hello/World', s.interpolation_chunk
669
+ assert_equal 'Hello World', s.interpolation_chunk
572
670
  end
573
-
671
+
574
672
  def test_regexp_chunk_should_escape_specials
575
673
  s = ROUTING::StaticSegment.new
576
674
 
@@ -684,7 +782,7 @@ class DynamicSegmentTest < Test::Unit::TestCase
684
782
 
685
783
  eval(segment.expiry_statement)
686
784
  rescue RuntimeError
687
- flunk "Expiry check should not have occured!"
785
+ flunk "Expiry check should not have occurred!"
688
786
  end
689
787
 
690
788
  def test_expiry_should_occur_according_to_expire_on
@@ -761,6 +859,11 @@ class DynamicSegmentTest < Test::Unit::TestCase
761
859
  assert_equal a_value, eval(%("#{segment.interpolation_chunk}"))
762
860
  end
763
861
 
862
+ def test_interpolation_chunk_should_accept_nil
863
+ a_value = nil
864
+ assert_equal '', eval(%("#{segment.interpolation_chunk('a_value')}"))
865
+ end
866
+
764
867
  def test_value_regexp_should_be_nil_without_regexp
765
868
  assert_equal nil, segment.value_regexp
766
869
  end
@@ -778,6 +881,28 @@ class DynamicSegmentTest < Test::Unit::TestCase
778
881
  assert_kind_of String, segment.regexp_chunk
779
882
  end
780
883
 
884
+ def test_build_pattern_non_optional_with_no_captures
885
+ # Non optional
886
+ a_segment = ROUTING::DynamicSegment.new
887
+ a_segment.regexp = /\d+/ #number_of_captures is 0
888
+ assert_equal "(\\d+)stuff", a_segment.build_pattern('stuff')
889
+ end
890
+
891
+ def test_build_pattern_non_optional_with_captures
892
+ # Non optional
893
+ a_segment = ROUTING::DynamicSegment.new
894
+ a_segment.regexp = /(\d+)(.*?)/ #number_of_captures is 2
895
+ assert_equal "((\\d+)(.*?))stuff", a_segment.build_pattern('stuff')
896
+ end
897
+
898
+ def test_optionality_implied
899
+ a_segment = ROUTING::DynamicSegment.new
900
+ a_segment.key = :id
901
+ assert a_segment.optionality_implied?
902
+
903
+ a_segment.key = :action
904
+ assert a_segment.optionality_implied?
905
+ end
781
906
  end
782
907
 
783
908
  class ControllerSegmentTest < Test::Unit::TestCase
@@ -799,6 +924,59 @@ class ControllerSegmentTest < Test::Unit::TestCase
799
924
 
800
925
  end
801
926
 
927
+ uses_mocha 'RouteTest' do
928
+
929
+ class MockController
930
+ attr_accessor :routes
931
+
932
+ def initialize(routes)
933
+ self.routes = routes
934
+ end
935
+
936
+ def url_for(options)
937
+ only_path = options.delete(:only_path)
938
+
939
+ port = options.delete(:port) || 80
940
+ port_string = port == 80 ? '' : ":#{port}"
941
+
942
+ host = options.delete(:host) || "named.route.test"
943
+ anchor = "##{options.delete(:anchor)}" if options.key?(:anchor)
944
+
945
+ path = routes.generate(options)
946
+
947
+ only_path ? "#{path}#{anchor}" : "http://#{host}#{port_string}#{path}#{anchor}"
948
+ end
949
+
950
+ def request
951
+ @request ||= MockRequest.new(:host => "named.route.test", :method => :get)
952
+ end
953
+
954
+ def relative_url_root=(value)
955
+ request.relative_url_root=value
956
+ end
957
+ end
958
+
959
+ class MockRequest
960
+ attr_accessor :path, :path_parameters, :host, :subdomains, :domain,
961
+ :method, :relative_url_root
962
+
963
+ def initialize(values={})
964
+ values.each { |key, value| send("#{key}=", value) }
965
+ if values[:host]
966
+ subdomain, self.domain = values[:host].split(/\./, 2)
967
+ self.subdomains = [subdomain]
968
+ end
969
+ end
970
+
971
+ def protocol
972
+ "http://"
973
+ end
974
+
975
+ def host_with_port
976
+ (subdomains * '.') + '.' + domain
977
+ end
978
+ end
979
+
802
980
  class RouteTest < Test::Unit::TestCase
803
981
 
804
982
  def setup
@@ -812,7 +990,7 @@ class RouteTest < Test::Unit::TestCase
812
990
  end
813
991
 
814
992
  def default_route
815
- unless @default_route
993
+ unless defined?(@default_route)
816
994
  @default_route = ROUTING::Route.new
817
995
 
818
996
  @default_route.segments << (s = ROUTING::StaticSegment.new)
@@ -873,6 +1051,29 @@ class RouteTest < Test::Unit::TestCase
873
1051
  assert_equal '/accounts/list_all', default_route.generate(o, o, {})
874
1052
  end
875
1053
 
1054
+ def test_default_route_should_uri_escape_pluses
1055
+ expected = { :controller => 'accounts', :action => 'show', :id => 'hello world' }
1056
+ assert_equal expected, default_route.recognize('/accounts/show/hello world')
1057
+ assert_equal expected, default_route.recognize('/accounts/show/hello%20world')
1058
+ assert_equal '/accounts/show/hello%20world', default_route.generate(expected, expected, {})
1059
+
1060
+ expected[:id] = 'hello+world'
1061
+ assert_equal expected, default_route.recognize('/accounts/show/hello+world')
1062
+ assert_equal expected, default_route.recognize('/accounts/show/hello%2Bworld')
1063
+ assert_equal '/accounts/show/hello+world', default_route.generate(expected, expected, {})
1064
+ end
1065
+
1066
+ def test_matches_controller_and_action
1067
+ # requirement_for should only be called for the action and controller _once_
1068
+ @route.expects(:requirement_for).with(:controller).times(1).returns('pages')
1069
+ @route.expects(:requirement_for).with(:action).times(1).returns('show')
1070
+
1071
+ @route.requirements = {:controller => 'pages', :action => 'show'}
1072
+ assert @route.matches_controller_and_action?('pages', 'show')
1073
+ assert !@route.matches_controller_and_action?('not_pages', 'show')
1074
+ assert !@route.matches_controller_and_action?('pages', 'not_show')
1075
+ end
1076
+
876
1077
  def test_parameter_shell
877
1078
  page_url = ROUTING::Route.new
878
1079
  page_url.requirements = {:controller => 'pages', :action => 'show', :id => /\d+/}
@@ -959,6 +1160,8 @@ class RouteTest < Test::Unit::TestCase
959
1160
  end
960
1161
  end
961
1162
 
1163
+ end # uses_mocha
1164
+
962
1165
  class RouteBuilderTest < Test::Unit::TestCase
963
1166
 
964
1167
  def builder
@@ -1110,15 +1313,6 @@ class RouteBuilderTest < Test::Unit::TestCase
1110
1313
  assert_equal nil, builder.warn_output # should only warn on the :person segment
1111
1314
  end
1112
1315
 
1113
- def test_segmentation_of_semicolon_path
1114
- segments = builder.segments_for_route_path '/books/:id;:action'
1115
- defaults = { :action => 'show' }
1116
- assert builder.assign_route_options(segments, defaults, {}).empty?
1117
- segments.each do |segment|
1118
- assert ! segment.optional? || segment.key == :action
1119
- end
1120
- end
1121
-
1122
1316
  def test_segmentation_of_dot_path
1123
1317
  segments = builder.segments_for_route_path '/books/:action.rss'
1124
1318
  assert builder.assign_route_options(segments, {}, {}).empty?
@@ -1244,32 +1438,10 @@ class RouteBuilderTest < Test::Unit::TestCase
1244
1438
 
1245
1439
  end
1246
1440
 
1247
- class RouteSetTest < Test::Unit::TestCase
1248
- class MockController
1249
- attr_accessor :routes
1250
-
1251
- def initialize(routes)
1252
- self.routes = routes
1253
- end
1254
1441
 
1255
- def url_for(options)
1256
- only_path = options.delete(:only_path)
1257
- path = routes.generate(options)
1258
- only_path ? path : "http://named.route.test#{path}"
1259
- end
1260
- end
1261
1442
 
1262
- class MockRequest
1263
- attr_accessor :path, :path_parameters, :host, :subdomains, :domain, :method
1264
1443
 
1265
- def initialize(values={})
1266
- values.each { |key, value| send("#{key}=", value) }
1267
- if values[:host]
1268
- subdomain, self.domain = values[:host].split(/\./, 2)
1269
- self.subdomains = [subdomain]
1270
- end
1271
- end
1272
- end
1444
+ class RouteSetTest < Test::Unit::TestCase
1273
1445
 
1274
1446
  def set
1275
1447
  @set ||= ROUTING::RouteSet.new
@@ -1353,7 +1525,7 @@ class RouteSetTest < Test::Unit::TestCase
1353
1525
  end
1354
1526
 
1355
1527
  klass = Class.new(MockController)
1356
- set.named_routes.install(klass)
1528
+ set.install_helpers(klass)
1357
1529
  klass.new(set)
1358
1530
  end
1359
1531
 
@@ -1388,12 +1560,57 @@ class RouteSetTest < Test::Unit::TestCase
1388
1560
  assert_equal '/admin/users', set.generate(controller.send(:hash_for_users_url), {:controller => 'users', :action => 'index'})
1389
1561
  end
1390
1562
 
1391
- def test_namd_route_url_method_with_ordered_parameters
1563
+ def test_named_route_url_method_with_anchor
1564
+ controller = setup_named_route_test
1565
+
1566
+ assert_equal "http://named.route.test/people/5#location", controller.send(:show_url, :id => 5, :anchor => 'location')
1567
+ assert_equal "/people/5#location", controller.send(:show_path, :id => 5, :anchor => 'location')
1568
+
1569
+ assert_equal "http://named.route.test/people#location", controller.send(:index_url, :anchor => 'location')
1570
+ assert_equal "/people#location", controller.send(:index_path, :anchor => 'location')
1571
+
1572
+ assert_equal "http://named.route.test/admin/users#location", controller.send(:users_url, :anchor => 'location')
1573
+ assert_equal '/admin/users#location', controller.send(:users_path, :anchor => 'location')
1574
+
1575
+ assert_equal "http://named.route.test/people/go/7/hello/joe/5#location",
1576
+ controller.send(:multi_url, 7, "hello", 5, :anchor => 'location')
1577
+
1578
+ assert_equal "http://named.route.test/people/go/7/hello/joe/5?baz=bar#location",
1579
+ controller.send(:multi_url, 7, "hello", 5, :baz => "bar", :anchor => 'location')
1580
+
1581
+ assert_equal "http://named.route.test/people?baz=bar#location",
1582
+ controller.send(:index_url, :baz => "bar", :anchor => 'location')
1583
+ end
1584
+
1585
+ def test_named_route_url_method_with_port
1586
+ controller = setup_named_route_test
1587
+ assert_equal "http://named.route.test:8080/people/5", controller.send(:show_url, 5, :port=>8080)
1588
+ end
1589
+
1590
+ def test_named_route_url_method_with_host
1591
+ controller = setup_named_route_test
1592
+ assert_equal "http://some.example.com/people/5", controller.send(:show_url, 5, :host=>"some.example.com")
1593
+ end
1594
+
1595
+
1596
+ def test_named_route_url_method_with_ordered_parameters
1392
1597
  controller = setup_named_route_test
1393
1598
  assert_equal "http://named.route.test/people/go/7/hello/joe/5",
1394
1599
  controller.send(:multi_url, 7, "hello", 5)
1395
1600
  end
1396
1601
 
1602
+ def test_named_route_url_method_with_ordered_parameters_and_hash
1603
+ controller = setup_named_route_test
1604
+ assert_equal "http://named.route.test/people/go/7/hello/joe/5?baz=bar",
1605
+ controller.send(:multi_url, 7, "hello", 5, :baz => "bar")
1606
+ end
1607
+
1608
+ def test_named_route_url_method_with_no_positional_arguments
1609
+ controller = setup_named_route_test
1610
+ assert_equal "http://named.route.test/people?baz=bar",
1611
+ controller.send(:index_url, :baz => "bar")
1612
+ end
1613
+
1397
1614
  def test_draw_default_route
1398
1615
  ActionController::Routing.with_controllers(['users']) do
1399
1616
  set.draw do |map|
@@ -1489,11 +1706,11 @@ class RouteSetTest < Test::Unit::TestCase
1489
1706
 
1490
1707
  def test_recognize_with_encoded_id_and_regex
1491
1708
  set.draw do |map|
1492
- map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /[a-zA-Z0-9 ]+/
1709
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /[a-zA-Z0-9\+]+/
1493
1710
  end
1494
1711
 
1495
1712
  assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10'))
1496
- assert_equal({:controller => 'pages', :action => 'show', :id => 'hello world'}, set.recognize_path('/page/hello+world'))
1713
+ assert_equal({:controller => 'pages', :action => 'show', :id => 'hello+world'}, set.recognize_path('/page/hello+world'))
1497
1714
  end
1498
1715
 
1499
1716
  def test_recognize_with_conditions
@@ -1522,8 +1739,13 @@ class RouteSetTest < Test::Unit::TestCase
1522
1739
  assert_nothing_raised { set.recognize(request) }
1523
1740
  assert_equal("update", request.path_parameters[:action])
1524
1741
 
1525
- request.method = :update
1526
- assert_raises(ActionController::RoutingError) { set.recognize(request) }
1742
+ begin
1743
+ request.method = :bacon
1744
+ set.recognize(request)
1745
+ flunk 'Should have raised NotImplemented'
1746
+ rescue ActionController::NotImplemented => e
1747
+ assert_equal [:get, :post, :put, :delete], e.allowed_methods
1748
+ end
1527
1749
 
1528
1750
  request.path = "/people/5"
1529
1751
  request.method = :get
@@ -1540,10 +1762,15 @@ class RouteSetTest < Test::Unit::TestCase
1540
1762
  assert_nothing_raised { set.recognize(request) }
1541
1763
  assert_equal("destroy", request.path_parameters[:action])
1542
1764
  assert_equal("5", request.path_parameters[:id])
1543
-
1544
- request.method = :post
1545
- assert_raises(ActionController::RoutingError) { set.recognize(request) }
1546
-
1765
+
1766
+ begin
1767
+ request.method = :post
1768
+ set.recognize(request)
1769
+ flunk 'Should have raised MethodNotAllowed'
1770
+ rescue ActionController::MethodNotAllowed => e
1771
+ assert_equal [:get, :put, :delete], e.allowed_methods
1772
+ end
1773
+
1547
1774
  ensure
1548
1775
  Object.send(:remove_const, :PeopleController)
1549
1776
  end
@@ -1614,18 +1841,6 @@ class RouteSetTest < Test::Unit::TestCase
1614
1841
  Object.send(:remove_const, :PeopleController)
1615
1842
  end
1616
1843
 
1617
- def test_deprecation_warning_for_root_route
1618
- Object.const_set(:PeopleController, Class.new)
1619
-
1620
- set.draw do |map|
1621
- assert_deprecated do
1622
- map.root('', :controller => "people")
1623
- end
1624
- end
1625
- ensure
1626
- Object.send(:remove_const, :PeopleController)
1627
- end
1628
-
1629
1844
  def test_generate_with_default_action
1630
1845
  set.draw do |map|
1631
1846
  map.connect "/people", :controller => "people"
@@ -1635,6 +1850,62 @@ class RouteSetTest < Test::Unit::TestCase
1635
1850
  url = set.generate(:controller => "people", :action => "list")
1636
1851
  assert_equal "/people/list", url
1637
1852
  end
1853
+
1854
+ def test_root_map
1855
+ Object.const_set(:PeopleController, Class.new)
1856
+
1857
+ set.draw { |map| map.root :controller => "people" }
1858
+
1859
+ request.path = ""
1860
+ request.method = :get
1861
+ assert_nothing_raised { set.recognize(request) }
1862
+ assert_equal("people", request.path_parameters[:controller])
1863
+ assert_equal("index", request.path_parameters[:action])
1864
+ ensure
1865
+ Object.send(:remove_const, :PeopleController)
1866
+ end
1867
+
1868
+
1869
+ def test_namespace
1870
+ Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) })
1871
+
1872
+ set.draw do |map|
1873
+
1874
+ map.namespace 'api' do |api|
1875
+ api.route 'inventory', :controller => "products", :action => 'inventory'
1876
+ end
1877
+
1878
+ end
1879
+
1880
+ request.path = "/api/inventory"
1881
+ request.method = :get
1882
+ assert_nothing_raised { set.recognize(request) }
1883
+ assert_equal("api/products", request.path_parameters[:controller])
1884
+ assert_equal("inventory", request.path_parameters[:action])
1885
+ ensure
1886
+ Object.send(:remove_const, :Api)
1887
+ end
1888
+
1889
+
1890
+ def test_namespaced_root_map
1891
+ Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) })
1892
+
1893
+ set.draw do |map|
1894
+
1895
+ map.namespace 'api' do |api|
1896
+ api.root :controller => "products"
1897
+ end
1898
+
1899
+ end
1900
+
1901
+ request.path = "/api"
1902
+ request.method = :get
1903
+ assert_nothing_raised { set.recognize(request) }
1904
+ assert_equal("api/products", request.path_parameters[:controller])
1905
+ assert_equal("index", request.path_parameters[:action])
1906
+ ensure
1907
+ Object.send(:remove_const, :Api)
1908
+ end
1638
1909
 
1639
1910
  def test_generate_finds_best_fit
1640
1911
  set.draw do |map|
@@ -1727,6 +1998,61 @@ class RouteSetTest < Test::Unit::TestCase
1727
1998
  {:controller => 'post', :action => 'show', :parameter => 1}
1728
1999
  )
1729
2000
  end
2001
+
2002
+ def test_expiry_determination_should_consider_values_with_to_param
2003
+ set.draw { |map| map.connect 'projects/:project_id/:controller/:action' }
2004
+ assert_equal '/projects/1/post/show', set.generate(
2005
+ {:action => 'show', :project_id => 1},
2006
+ {:controller => 'post', :action => 'show', :project_id => '1'})
2007
+ end
2008
+
2009
+ def test_generate_all
2010
+ set.draw do |map|
2011
+ map.connect 'show_post/:id', :controller => 'post', :action => 'show'
2012
+ map.connect ':controller/:action/:id'
2013
+ end
2014
+ all = set.generate(
2015
+ {:action => 'show', :id => 10, :generate_all => true},
2016
+ {:controller => 'post', :action => 'show'}
2017
+ )
2018
+ assert_equal 2, all.length
2019
+ assert_equal '/show_post/10', all.first
2020
+ assert_equal '/post/show/10', all.last
2021
+ end
2022
+
2023
+ def test_named_route_in_nested_resource
2024
+ set.draw do |map|
2025
+ map.resources :projects do |project|
2026
+ project.comments 'comments', :controller => 'comments', :action => 'index'
2027
+ end
2028
+ end
2029
+
2030
+ request.path = "/projects/1/comments"
2031
+ request.method = :get
2032
+ assert_nothing_raised { set.recognize(request) }
2033
+ assert_equal("comments", request.path_parameters[:controller])
2034
+ assert_equal("index", request.path_parameters[:action])
2035
+ end
2036
+
2037
+ def test_setting_root_in_namespace_using_symbol
2038
+ assert_nothing_raised do
2039
+ set.draw do |map|
2040
+ map.namespace :admin do |admin|
2041
+ admin.root :controller => 'home'
2042
+ end
2043
+ end
2044
+ end
2045
+ end
2046
+
2047
+ def test_setting_root_in_namespace_using_string
2048
+ assert_nothing_raised do
2049
+ set.draw do |map|
2050
+ map.namespace 'admin' do |admin|
2051
+ admin.root :controller => 'home'
2052
+ end
2053
+ end
2054
+ end
2055
+ end
1730
2056
 
1731
2057
  end
1732
2058
 
@@ -1798,4 +2124,74 @@ class RoutingTest < Test::Unit::TestCase
1798
2124
  assert_equal %w(vendor\\rails\\railties\\builtin\\rails_info vendor\\rails\\actionpack\\lib app\\controllers app\\helpers app\\models lib .), paths
1799
2125
  end
1800
2126
 
2127
+ def test_routing_helper_module
2128
+ assert_kind_of Module, ActionController::Routing::Helpers
2129
+
2130
+ h = ActionController::Routing::Helpers
2131
+ c = Class.new
2132
+ assert ! c.ancestors.include?(h)
2133
+ ActionController::Routing::Routes.install_helpers c
2134
+ assert c.ancestors.include?(h)
2135
+ end
2136
+
2137
+ end
2138
+
2139
+ uses_mocha 'route loading' do
2140
+ class RouteLoadingTest < Test::Unit::TestCase
2141
+
2142
+ def setup
2143
+ routes.instance_variable_set '@routes_last_modified', nil
2144
+ silence_warnings { Object.const_set :RAILS_ROOT, '.' }
2145
+
2146
+ @stat = stub_everything
2147
+ end
2148
+
2149
+ def teardown
2150
+ Object.send :remove_const, :RAILS_ROOT
2151
+ end
2152
+
2153
+ def test_load
2154
+ File.expects(:stat).returns(@stat)
2155
+ routes.expects(:load).with(regexp_matches(/routes\.rb$/))
2156
+
2157
+ routes.reload
2158
+ end
2159
+
2160
+ def test_no_reload_when_not_modified
2161
+ @stat.expects(:mtime).times(2).returns(1)
2162
+ File.expects(:stat).times(2).returns(@stat)
2163
+ routes.expects(:load).with(regexp_matches(/routes\.rb$/)).at_most_once
2164
+
2165
+ 2.times { routes.reload }
2166
+ end
2167
+
2168
+ def test_reload_when_modified
2169
+ @stat.expects(:mtime).at_least(2).returns(1, 2)
2170
+ File.expects(:stat).at_least(2).returns(@stat)
2171
+ routes.expects(:load).with(regexp_matches(/routes\.rb$/)).times(2)
2172
+
2173
+ 2.times { routes.reload }
2174
+ end
2175
+
2176
+ def test_bang_forces_reload
2177
+ @stat.expects(:mtime).at_least(2).returns(1)
2178
+ File.expects(:stat).at_least(2).returns(@stat)
2179
+ routes.expects(:load).with(regexp_matches(/routes\.rb$/)).times(2)
2180
+
2181
+ 2.times { routes.reload! }
2182
+ end
2183
+
2184
+ def test_adding_inflections_forces_reload
2185
+ Inflector::Inflections.instance.expects(:uncountable).with('equipment')
2186
+ routes.expects(:reload!)
2187
+
2188
+ Inflector.inflections { |inflect| inflect.uncountable('equipment') }
2189
+ end
2190
+
2191
+ private
2192
+ def routes
2193
+ ActionController::Routing::Routes
2194
+ end
2195
+
2196
+ end
1801
2197
  end